From 3f06a3b4d2e3d41bcf204c3154e67b1b967dbf98 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 18 May 2023 15:14:19 +0100 Subject: [PATCH 001/228] deps: Bump `rules_apple` -> 2.3.0 (#27477) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index f8a3198ab427..123ef48acc52 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -60,10 +60,10 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Apple Rules for Bazel", project_desc = "Bazel rules for Apple platforms", project_url = "https://github.com/bazelbuild/rules_apple", - version = "2.0.0", - sha256 = "43737f28a578d8d8d7ab7df2fb80225a6b23b9af9655fcdc66ae38eb2abcf2ed", + version = "2.3.0", + sha256 = "a6141240657093fa7ccc7ca1ee5a62408dd9996d1bf47bc2369b8b9faefb2698", urls = ["https://github.com/bazelbuild/rules_apple/releases/download/{version}/rules_apple.{version}.tar.gz"], - release_date = "2022-12-21", + release_date = "2023-05-17", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_apple/blob/{version}/LICENSE", From c6e9cd59fda532c1e2b3c1d74d390d6d85d2e2ff Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 18 May 2023 16:18:14 +0200 Subject: [PATCH 002/228] build: include "cstdint" for the types uint8_t and uint16_t (#27343) This fixes a build problem on Fedora 38 with clang 16. (there are other build problems in external libraries) Commit Message: Additional Description: Risk Level: Low Testing: Docs Changes: Release Notes: Platform Specific Features: Signed-off-by: Michael Kaufmann --- source/common/common/hex.h | 1 + source/extensions/clusters/redis/crc16.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/common/common/hex.h b/source/common/common/hex.h index aba722a4fc06..49f78fed6909 100644 --- a/source/common/common/hex.h +++ b/source/common/common/hex.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include diff --git a/source/extensions/clusters/redis/crc16.h b/source/extensions/clusters/redis/crc16.h index 25ba5806dc30..e0b0de8992af 100644 --- a/source/extensions/clusters/redis/crc16.h +++ b/source/extensions/clusters/redis/crc16.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "absl/strings/ascii.h" From 7a6c72ce9bc6a6722a7cdb1a08b86c77868480cf Mon Sep 17 00:00:00 2001 From: Artur Melo Date: Thu, 18 May 2023 15:34:10 +0100 Subject: [PATCH 003/228] dns_cares: Add debug log entry when resolution response holds no records (#27486) Fixes #27214 Signed-off-by: Restless-ET --- .../extensions/network/dns_resolver/cares/dns_impl.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.cc b/source/extensions/network/dns_resolver/cares/dns_impl.cc index 9f514933ca86..1c4bd6fa6a51 100644 --- a/source/extensions/network/dns_resolver/cares/dns_impl.cc +++ b/source/extensions/network/dns_resolver/cares/dns_impl.cc @@ -146,11 +146,14 @@ void DnsResolverImpl::AddrInfoPendingResolution::onAresGetAddrInfoCallback( if (status != ARES_SUCCESS) { parent_.chargeGetAddrInfoErrorStats(status, timeouts); - } - if (status != ARES_SUCCESS && !isResponseWithNoRecords(status)) { - ENVOY_LOG_EVENT(debug, "cares_resolution_failure", - "dns resolution for {} failed with c-ares status {}", dns_name_, status); + if (!isResponseWithNoRecords(status)) { + ENVOY_LOG_EVENT(debug, "cares_resolution_failure", + "dns resolution for {} failed with c-ares status {}", dns_name_, status); + } else { + ENVOY_LOG_EVENT(debug, "cares_resolution_no_records", "dns resolution without records for {}", + dns_name_); + } } // We receive ARES_EDESTRUCTION when destructing with pending queries. From e669e5d40f8820262aee293a9e2773688ffbab96 Mon Sep 17 00:00:00 2001 From: Kuat Date: Thu, 18 May 2023 07:45:33 -0700 Subject: [PATCH 004/228] deps: update re2 (#27464) * deps: update re2 Signed-off-by: Kuat Yessenov --- bazel/repository_locations.bzl | 6 +++--- source/common/common/regex.h | 7 ++----- .../path/match/uri_template/uri_template_match.cc | 3 +-- .../rewrite/uri_template/uri_template_rewrite.cc | 4 ++-- .../path/uri_template_lib/uri_template.cc | 4 ++-- .../path/uri_template_lib/uri_template_internal.cc | 8 ++++---- .../path/uri_template_lib/uri_template_internal.h | 5 ----- .../uri_template_lib/uri_template_internal_test.cc | 14 +++++++------- 8 files changed, 21 insertions(+), 30 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 123ef48acc52..6c72be0aaf91 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1137,12 +1137,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "RE2", project_desc = "RE2, a regular expression library", project_url = "https://github.com/google/re2", - version = "2022-12-01", - sha256 = "665b65b6668156db2b46dddd33405cd422bd611352c5052ab3dae6a5fbac5506", + version = "2023-03-01", + sha256 = "7a9a4824958586980926a300b4717202485c4b4115ac031822e29aa4ef207e48", strip_prefix = "re2-{version}", urls = ["https://github.com/google/re2/archive/{version}.tar.gz"], use_category = ["controlplane", "dataplane_core"], - release_date = "2022-11-30", + release_date = "2023-03-01", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/google/re2/blob/{version}/LICENSE", diff --git a/source/common/common/regex.h b/source/common/common/regex.h index 92b2720bc231..4189df75fc24 100644 --- a/source/common/common/regex.h +++ b/source/common/common/regex.h @@ -28,15 +28,12 @@ class CompiledGoogleReMatcher : public CompiledMatcher { explicit CompiledGoogleReMatcher(const envoy::type::matcher::v3::RegexMatcher& config); // CompiledMatcher - bool match(absl::string_view value) const override { - return re2::RE2::FullMatch(re2::StringPiece(value.data(), value.size()), regex_); - } + bool match(absl::string_view value) const override { return re2::RE2::FullMatch(value, regex_); } // CompiledMatcher std::string replaceAll(absl::string_view value, absl::string_view substitution) const override { std::string result = std::string(value); - re2::RE2::GlobalReplace(&result, regex_, - re2::StringPiece(substitution.data(), substitution.size())); + re2::RE2::GlobalReplace(&result, regex_, substitution); return result; } diff --git a/source/extensions/path/match/uri_template/uri_template_match.cc b/source/extensions/path/match/uri_template/uri_template_match.cc index a156508b9a88..6313c291b4a5 100644 --- a/source/extensions/path/match/uri_template/uri_template_match.cc +++ b/source/extensions/path/match/uri_template/uri_template_match.cc @@ -19,8 +19,7 @@ namespace Match { bool UriTemplateMatcher::match(absl::string_view path) const { RE2 matching_pattern_regex = RE2(convertPathPatternSyntaxToRegex(path_template_).value()); - return RE2::FullMatch(Internal::toStringPiece(Http::PathUtil::removeQueryAndFragment(path)), - matching_pattern_regex); + return RE2::FullMatch(Http::PathUtil::removeQueryAndFragment(path), matching_pattern_regex); } absl::string_view UriTemplateMatcher::uriTemplate() const { return path_template_; } diff --git a/source/extensions/path/rewrite/uri_template/uri_template_rewrite.cc b/source/extensions/path/rewrite/uri_template/uri_template_rewrite.cc index 2e69b72e7b0f..05ab1972ece8 100644 --- a/source/extensions/path/rewrite/uri_template/uri_template_rewrite.cc +++ b/source/extensions/path/rewrite/uri_template/uri_template_rewrite.cc @@ -55,7 +55,7 @@ absl::StatusOr UriTemplateRewriter::rewritePath(absl::string_view p RewriteSegments rewrite_pattern_segments = parseRewritePattern(rewrite_pattern_, regex_pattern_str).value(); - RE2 regex = RE2(Internal::toStringPiece(regex_pattern_str)); + RE2 regex = RE2(regex_pattern_str); if (!regex.ok()) { return absl::InternalError("Regex library failed"); } @@ -63,7 +63,7 @@ absl::StatusOr UriTemplateRewriter::rewritePath(absl::string_view p // First capture is the whole matched regex pattern. int capture_num = regex.NumberOfCapturingGroups() + 1; std::vector captures(capture_num); - if (!regex.Match(Internal::toStringPiece(pattern), /*startpos=*/0, + if (!regex.Match(pattern, /*startpos=*/0, /*endpos=*/pattern.size(), RE2::ANCHOR_BOTH, captures.data(), captures.size())) { return absl::InvalidArgumentError("Pattern not match"); } diff --git a/source/extensions/path/uri_template_lib/uri_template.cc b/source/extensions/path/uri_template_lib/uri_template.cc index af9f3d3e1a59..9eda8154562b 100644 --- a/source/extensions/path/uri_template_lib/uri_template.cc +++ b/source/extensions/path/uri_template_lib/uri_template.cc @@ -43,7 +43,7 @@ absl::StatusOr> parseRewritePattern(absl::string_view // Don't allow contiguous '/' patterns. static const LazyRE2 invalid_regex = {"^.*//.*$"}; - if (RE2::FullMatch(Internal::toStringPiece(path_pattern), *invalid_regex)) { + if (RE2::FullMatch(path_pattern, *invalid_regex)) { return absl::InvalidArgumentError("Invalid rewrite literal"); } @@ -80,7 +80,7 @@ absl::StatusOr> parseRewritePattern(absl::string_view absl::StatusOr parseRewritePattern(absl::string_view pattern, absl::string_view capture_regex) { RewriteSegments parsed_pattern; - RE2 regex = RE2(Internal::toStringPiece(capture_regex)); + RE2 regex = RE2(capture_regex); if (!regex.ok()) { return absl::InternalError(regex.error()); } diff --git a/source/extensions/path/uri_template_lib/uri_template_internal.cc b/source/extensions/path/uri_template_lib/uri_template_internal.cc index 985be5973fa9..0b636fb2f75d 100644 --- a/source/extensions/path/uri_template_lib/uri_template_internal.cc +++ b/source/extensions/path/uri_template_lib/uri_template_internal.cc @@ -122,19 +122,19 @@ bool isValidLiteral(absl::string_view literal) { static const std::string* kValidLiteralRegex = new std::string(absl::StrCat("^[", kLiteral, "]+$")); static const LazyRE2 literal_regex = {kValidLiteralRegex->data()}; - return RE2::FullMatch(toStringPiece(literal), *literal_regex); + return RE2::FullMatch(literal, *literal_regex); } bool isValidRewriteLiteral(absl::string_view literal) { static const std::string* kValidLiteralRegex = new std::string(absl::StrCat("^[", kLiteral, "/]+$")); static const LazyRE2 literal_regex = {kValidLiteralRegex->data()}; - return RE2::FullMatch(toStringPiece(literal), *literal_regex); + return RE2::FullMatch(literal, *literal_regex); } bool isValidVariableName(absl::string_view variable) { static const LazyRE2 variable_regex = {"^[a-zA-Z][a-zA-Z0-9_]*$"}; - return RE2::FullMatch(toStringPiece(variable), *variable_regex); + return RE2::FullMatch(variable, *variable_regex); } absl::StatusOr> parseLiteral(absl::string_view pattern) { @@ -273,7 +273,7 @@ absl::StatusOr parsePathPatternSyntax(absl::string_view path) struct ParsedPathPattern parsed_pattern; static const LazyRE2 printable_regex = {"^/[[:graph:]]*$"}; - if (!RE2::FullMatch(toStringPiece(path), *printable_regex)) { + if (!RE2::FullMatch(path, *printable_regex)) { return absl::InvalidArgumentError("Invalid pattern"); } diff --git a/source/extensions/path/uri_template_lib/uri_template_internal.h b/source/extensions/path/uri_template_lib/uri_template_internal.h index b27bd4062a20..674348e8592b 100644 --- a/source/extensions/path/uri_template_lib/uri_template_internal.h +++ b/source/extensions/path/uri_template_lib/uri_template_internal.h @@ -134,11 +134,6 @@ std::string toRegexPattern(const Variable& pattern); */ std::string toRegexPattern(const struct ParsedPathPattern& pattern); -/** - * Converts string_view to be used in re2::string_piece. - */ -inline re2::StringPiece toStringPiece(absl::string_view text) { return {text.data(), text.size()}; } - /** * Checks end of pattern to ensure glob operator is last. */ diff --git a/test/extensions/path/uri_template_lib/uri_template_internal_test.cc b/test/extensions/path/uri_template_lib/uri_template_internal_test.cc index b7d92e3dd454..dff0e2283ae9 100644 --- a/test/extensions/path/uri_template_lib/uri_template_internal_test.cc +++ b/test/extensions/path/uri_template_lib/uri_template_internal_test.cc @@ -216,24 +216,24 @@ TEST(InternalRegexGen, LiteralEscapes) { TEST(InternalRegexGen, LiteralMatches) { absl::string_view kPattern = "abcABC123/-._~%20!$&'()+,;:@"; - EXPECT_TRUE(RE2::FullMatch(toStringPiece(kPattern), toRegexPattern(kPattern))); + EXPECT_TRUE(RE2::FullMatch(kPattern, toRegexPattern(kPattern))); } TEST(InternalRegexGen, LiteralMatchesInNamedCapture) { - absl::string_view kPattern = "abcABC123/-._~%20!$&'()+,;:@"; + re2::StringPiece kPattern = "abcABC123/-._~%20!$&'()+,;:@"; RE2 regex = RE2(absl::StrCat("(?P", toRegexPattern(kPattern), ")")); ASSERT_EQ(regex.NumberOfCapturingGroups(), 1); // Full matched string + capture groups std::vector captures(2); - ASSERT_TRUE(regex.Match(toStringPiece(kPattern), /*startpos=*/0, /*endpos=*/kPattern.size(), - RE2::ANCHOR_BOTH, captures.data(), captures.size())); + ASSERT_TRUE(regex.Match(kPattern, /*startpos=*/0, /*endpos=*/kPattern.size(), RE2::ANCHOR_BOTH, + captures.data(), captures.size())); // Index 0 would be the full text of the matched string. - EXPECT_EQ(toStringPiece(kPattern), captures[0]); + EXPECT_EQ(kPattern, captures[0]); // Get the pattern matched with the named capture group. - EXPECT_EQ(toStringPiece(kPattern), captures.at(regex.NamedCapturingGroups().at("var"))); + EXPECT_EQ(kPattern, captures.at(regex.NamedCapturingGroups().at("var"))); } TEST(InternalRegexGen, LiteralOnlyMatchesItself) { @@ -434,7 +434,7 @@ TEST_P(GenPatternRegexWithMatch, WithCapture) { /*endpos=*/requestPath().size(), RE2::ANCHOR_BOTH, captures.data(), captures.size())); - EXPECT_EQ(captures[0], toStringPiece(requestPath())); + EXPECT_EQ(captures[0], requestPath()); for (const auto& [name, value] : varValues()) { int capture_index = regex.NamedCapturingGroups().at(name); From 29334c21020d7d823d6851b1d7d9104434d0c1d7 Mon Sep 17 00:00:00 2001 From: Greg Greenway Date: Thu, 18 May 2023 09:03:24 -0700 Subject: [PATCH 005/228] access log: attempt to fix test flake (#27438) CI showed a failure in TEST_F(AccessLogManagerImplTest, ReopenFileOnTimerOnly). Attempting to use more rigid thread-syncronization primitives instead of atomics to avoid races and/or undefined/misunderstood behavior. Signed-off-by: Greg Greenway --- .../access_log/access_log_manager_impl.cc | 25 ++- .../access_log/access_log_manager_impl.h | 4 +- .../access_log_manager_impl_test.cc | 160 +++++------------- test/mocks/filesystem/mocks.cc | 14 +- test/mocks/filesystem/mocks.h | 26 +-- 5 files changed, 82 insertions(+), 147 deletions(-) diff --git a/source/common/access_log/access_log_manager_impl.cc b/source/common/access_log/access_log_manager_impl.cc index 9a9e9b6a23d7..ba3486ca545f 100644 --- a/source/common/access_log/access_log_manager_impl.cc +++ b/source/common/access_log/access_log_manager_impl.cc @@ -72,7 +72,11 @@ Api::IoCallBoolResult AccessLogFileImpl::open() { return result; } -void AccessLogFileImpl::reopen() { reopen_file_ = true; } +void AccessLogFileImpl::reopen() { + Thread::LockGuard lock(write_lock_); + reopen_file_ = true; + flush_event_.notifyOne(); +} AccessLogFileImpl::~AccessLogFileImpl() { { @@ -127,6 +131,11 @@ void AccessLogFileImpl::doWrite(Buffer::Instance& buffer) { void AccessLogFileImpl::flushThreadFunc() { + // Transfer the action from `reopen_file_` to this variable so that `reopen_file_` is only + // accessed while holding the mutex while the actual operation is performed while not holding the + // mutex. + bool do_reopen = false; + while (true) { std::unique_lock flush_lock; @@ -135,6 +144,10 @@ void AccessLogFileImpl::flushThreadFunc() { // flush_event_ can be woken up either by large enough flush_buffer or by timer. // In case it was timer, flush_buffer_ can be empty. + // + // Note: do not stop waiting when only `do_reopen` is true. In this case, we tried to + // reopen and failed. We don't want to retry this in a tight loop, so wait for the next + // event (timer or flush). while (flush_buffer_.length() == 0 && !flush_thread_exit_ && !reopen_file_) { // CondVar::wait() does not throw, so it's safe to pass the mutex rather than the guard. flush_event_.wait(write_lock_); @@ -147,10 +160,14 @@ void AccessLogFileImpl::flushThreadFunc() { flush_lock = std::unique_lock(flush_lock_); about_to_write_buffer_.move(flush_buffer_); ASSERT(flush_buffer_.length() == 0); + + if (reopen_file_) { + do_reopen = true; + reopen_file_ = false; + } } - // if we failed to reopen before, do it next loop. - if (reopen_file_) { + if (do_reopen) { if (file_->isOpen()) { const Api::IoCallBoolResult result = file_->close(); ASSERT(result.return_value_, fmt::format("unable to close file '{}': {}", file_->path(), @@ -160,7 +177,7 @@ void AccessLogFileImpl::flushThreadFunc() { if (!open_result.return_value_) { stats_.reopen_failed_.inc(); } else { - reopen_file_ = false; + do_reopen = false; } } // doWrite no matter file isOpen, if not, we can drain buffer diff --git a/source/common/access_log/access_log_manager_impl.h b/source/common/access_log/access_log_manager_impl.h index 23651b874e1c..e7e150423438 100644 --- a/source/common/access_log/access_log_manager_impl.h +++ b/source/common/access_log/access_log_manager_impl.h @@ -114,8 +114,8 @@ class AccessLogFileImpl : public AccessLogFile { // high performance. It is always local to the process. Thread::ThreadPtr flush_thread_; Thread::CondVar flush_event_; - std::atomic flush_thread_exit_{}; - std::atomic reopen_file_{}; + bool flush_thread_exit_ ABSL_GUARDED_BY(write_lock_){false}; + bool reopen_file_ ABSL_GUARDED_BY(write_lock_){false}; Buffer::OwnedImpl flush_buffer_ ABSL_GUARDED_BY(write_lock_); // This buffer is used by multiple threads. It // gets filled and then flushed either when max diff --git a/test/common/access_log/access_log_manager_impl_test.cc b/test/common/access_log/access_log_manager_impl_test.cc index f72541111172..3bacc57c0bd9 100644 --- a/test/common/access_log/access_log_manager_impl_test.cc +++ b/test/common/access_log/access_log_manager_impl_test.cc @@ -115,12 +115,7 @@ TEST_F(AccessLogManagerImplTest, FlushToLogFilePeriodically) { log_file->write("test"); - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 1) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 1)); waitForCounterEq("filesystem.write_completed", 1); EXPECT_EQ(1UL, store_.counter("filesystem.write_buffered").value()); @@ -144,12 +139,7 @@ TEST_F(AccessLogManagerImplTest, FlushToLogFilePeriodically) { EXPECT_CALL(*timer, enableTimer(timeout_40ms_, _)); timer->invokeCallback(); - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 2) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 2)); waitForCounterEq("filesystem.write_completed", 2); EXPECT_EQ(0UL, store_.counter("filesystem.write_failed").value()); @@ -179,12 +169,7 @@ TEST_F(AccessLogManagerImplTest, FlushToLogFileOnDemand) { })); log_file->write("prime-it"); uint32_t expected_writes = 1; - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != expected_writes) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, expected_writes)); EXPECT_CALL(*file_, write_(_)) .WillOnce(Invoke([](absl::string_view data) -> Api::IoCallSizeResult { @@ -195,18 +180,13 @@ TEST_F(AccessLogManagerImplTest, FlushToLogFileOnDemand) { log_file->write("test"); { - Thread::LockGuard lock(file_->write_mutex_); + absl::MutexLock lock(&file_->mutex_); EXPECT_EQ(expected_writes, file_->num_writes_); } log_file->flush(); expected_writes++; - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != expected_writes) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, expected_writes)); waitForCounterEq("filesystem.write_completed", 2); EXPECT_EQ(0UL, store_.counter("filesystem.flushed_by_timer").value()); @@ -223,12 +203,7 @@ TEST_F(AccessLogManagerImplTest, FlushToLogFileOnDemand) { timer->invokeCallback(); expected_writes++; - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != expected_writes) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, expected_writes)); EXPECT_CALL(*file_, close_()).WillOnce(Return(ByMove(Filesystem::resultSuccess(true)))); } @@ -250,13 +225,7 @@ TEST_F(AccessLogManagerImplTest, FlushCountsIOErrors) { log_file->write("test"); - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 1) { - file_->write_event_.wait(file_->write_mutex_); - } - } - + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 1)); waitForCounterEq("filesystem.write_failed", 1); EXPECT_EQ(0UL, store_.counter("filesystem.write_completed").value()); @@ -282,13 +251,7 @@ TEST_F(AccessLogManagerImplTest, ReopenFile) { log_file->write("before"); timer->invokeCallback(); - - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 1) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 1)); EXPECT_CALL(*file_, close_()) .InSequence(sq) @@ -312,16 +275,12 @@ TEST_F(AccessLogManagerImplTest, ReopenFile) { log_file->write("reopened"); timer->invokeCallback(); - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 2) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 2)); + EXPECT_TRUE(file_->waitForEventCount(file_->num_opens_, 2)); } -// Test that the flush timer will trigger file reopen even if no data is waiting. -TEST_F(AccessLogManagerImplTest, ReopenFileOnTimerOnly) { +// Test that the `reopen()` will trigger file reopen even if no data is waiting. +TEST_F(AccessLogManagerImplTest, ReopenFileNoWrite) { NiceMock* timer = new NiceMock(&dispatcher_); Sequence sq; @@ -340,13 +299,7 @@ TEST_F(AccessLogManagerImplTest, ReopenFileOnTimerOnly) { log_file->write("before"); timer->invokeCallback(); - - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 1) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 1)); EXPECT_CALL(*file_, close_()) .InSequence(sq) @@ -360,14 +313,8 @@ TEST_F(AccessLogManagerImplTest, ReopenFileOnTimerOnly) { .WillOnce(Return(ByMove(Filesystem::resultSuccess(true)))); log_file->reopen(); - timer->invokeCallback(); - { - Thread::LockGuard lock(file_->open_mutex_); - while (file_->num_opens_ != 2) { - file_->open_event_.wait(file_->open_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_opens_, 2)); } TEST_F(AccessLogManagerImplTest, ReopenRetry) { @@ -390,29 +337,28 @@ TEST_F(AccessLogManagerImplTest, ReopenRetry) { log_file->write("before reopen"); timer->invokeCallback(); - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 1) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 1)); EXPECT_CALL(*file_, close_()) .InSequence(sq) .WillOnce(Return(ByMove(Filesystem::resultSuccess(true)))); EXPECT_CALL(*file_, open_(_)) + .Times(3) .InSequence(sq) - .WillOnce(Return(ByMove(Filesystem::resultFailure(false, 0)))); - - EXPECT_CALL(*file_, open_(_)) - .InSequence(sq) + .WillOnce(Return(ByMove(Filesystem::resultFailure(false, 0)))) + .WillOnce(Return(ByMove(Filesystem::resultFailure(false, 0)))) .WillOnce(Return(ByMove(Filesystem::resultSuccess(true)))); EXPECT_CALL(*file_, write_(_)) + .Times(2) .InSequence(sq) .WillOnce(Invoke([](absl::string_view data) -> Api::IoCallSizeResult { - EXPECT_EQ(0, data.compare("after reopen")); + EXPECT_EQ(data, "retry reopen"); + return Filesystem::resultSuccess(static_cast(data.length())); + })) + .WillOnce(Invoke([](absl::string_view data) -> Api::IoCallSizeResult { + EXPECT_EQ(data, "after reopen"); return Filesystem::resultSuccess(static_cast(data.length())); })); @@ -422,26 +368,24 @@ TEST_F(AccessLogManagerImplTest, ReopenRetry) { log_file->reopen(); - log_file->write("drop data during reopen fail"); - timer->invokeCallback(); + EXPECT_TRUE(file_->waitForEventCount(file_->num_opens_, 2)); - { - Thread::LockGuard lock(file_->open_mutex_); - while (file_->num_opens_ != 3) { - file_->open_event_.wait(file_->open_mutex_); - } - } + // Retry the reopen by calling `reopen()` another time. + // This time is also set to fail. + log_file->reopen(); + EXPECT_TRUE(file_->waitForEventCount(file_->num_opens_, 3)); + + // Retry the reopen by writing more data and running the timer. + log_file->write("retry reopen"); + timer->invokeCallback(); + EXPECT_TRUE(file_->waitForEventCount(file_->num_opens_, 4)); + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 2)); log_file->write("after reopen"); timer->invokeCallback(); - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 2) { - file_->write_event_.wait(file_->write_mutex_); - } - } - waitForCounterEq("filesystem.reopen_failed", 1); + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 3)); + waitForCounterEq("filesystem.reopen_failed", 2); waitForGaugeEq("filesystem.write_total_buffered", 0); } @@ -457,13 +401,7 @@ TEST_F(AccessLogManagerImplTest, BigDataChunkShouldBeFlushedWithoutTimer) { })); log_file->write("a"); - - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 1) { - file_->write_event_.wait(file_->write_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 1)); // First write happens without waiting on thread_flush_. Now make a big string and it should be // flushed even when timer is not enabled @@ -476,13 +414,8 @@ TEST_F(AccessLogManagerImplTest, BigDataChunkShouldBeFlushedWithoutTimer) { std::string big_string(1024 * 64 + 1, 'b'); log_file->write(big_string); + EXPECT_TRUE(file_->waitForEventCount(file_->num_writes_, 2)); - { - Thread::LockGuard lock(file_->write_mutex_); - while (file_->num_writes_ != 2) { - file_->write_event_.wait(file_->write_mutex_); - } - } EXPECT_CALL(*file_, close_()).WillOnce(Return(ByMove(Filesystem::resultSuccess(true)))); } @@ -551,19 +484,8 @@ TEST_F(AccessLogManagerImplTest, ReopenAllFiles) { log->write("this is to force reopen"); log2->write("this is to force reopen"); - { - Thread::LockGuard lock(file_->open_mutex_); - while (file_->num_opens_ != 2) { - file_->open_event_.wait(file_->open_mutex_); - } - } - - { - Thread::LockGuard lock(file2->open_mutex_); - while (file2->num_opens_ != 2) { - file2->open_event_.wait(file2->open_mutex_); - } - } + EXPECT_TRUE(file_->waitForEventCount(file_->num_opens_, 2)); + EXPECT_TRUE(file2->waitForEventCount(file2->num_opens_, 2)); EXPECT_CALL(*file_, close_()) .InSequence(sq) diff --git a/test/mocks/filesystem/mocks.cc b/test/mocks/filesystem/mocks.cc index f6f94c91eef5..bd396f2aae2d 100644 --- a/test/mocks/filesystem/mocks.cc +++ b/test/mocks/filesystem/mocks.cc @@ -6,55 +6,51 @@ namespace Envoy { namespace Filesystem { -MockFile::MockFile() : num_opens_(0), num_writes_(0), is_open_(false) {} +MockFile::MockFile() = default; MockFile::~MockFile() = default; Api::IoCallBoolResult MockFile::open(FlagSet flag) { - Thread::LockGuard lock(open_mutex_); + absl::MutexLock lock(&mutex_); Api::IoCallBoolResult result = open_(flag); is_open_ = result.return_value_; num_opens_++; - open_event_.notifyOne(); return result; } Api::IoCallSizeResult MockFile::write(absl::string_view buffer) { - Thread::LockGuard lock(write_mutex_); + absl::MutexLock lock(&mutex_); if (!is_open_) { return {-1, Api::IoErrorPtr(nullptr, [](Api::IoError*) { PANIC("reached unexpected code"); })}; } Api::IoCallSizeResult result = write_(buffer); num_writes_++; - write_event_.notifyOne(); return result; } Api::IoCallSizeResult MockFile::pread(void* buf, uint64_t count, uint64_t offset) { - Thread::LockGuard lock(pread_mutex_); + absl::MutexLock lock(&mutex_); if (!is_open_) { return {-1, Api::IoErrorPtr(nullptr, [](Api::IoError*) { PANIC("reached unexpected code"); })}; } Api::IoCallSizeResult result = pread_(buf, count, offset); num_preads_++; - pread_event_.notifyOne(); return result; } Api::IoCallSizeResult MockFile::pwrite(const void* buf, uint64_t count, uint64_t offset) { - Thread::LockGuard lock(pwrite_mutex_); + absl::MutexLock lock(&mutex_); if (!is_open_) { return {-1, Api::IoErrorPtr(nullptr, [](Api::IoError*) { PANIC("reached unexpected code"); })}; } Api::IoCallSizeResult result = pwrite_(buf, count, offset); num_pwrites_++; - pwrite_event_.notifyOne(); return result; } diff --git a/test/mocks/filesystem/mocks.h b/test/mocks/filesystem/mocks.h index 2ae9642ed474..7f1d61b578da 100644 --- a/test/mocks/filesystem/mocks.h +++ b/test/mocks/filesystem/mocks.h @@ -36,21 +36,21 @@ class MockFile : public File { MOCK_METHOD(Api::IoCallSizeResult, pread_, (void* buf, uint64_t count, uint64_t offset)); MOCK_METHOD(Api::IoCallSizeResult, pwrite_, (const void* buf, uint64_t count, uint64_t offset)); - size_t num_opens_; - size_t num_writes_; - size_t num_preads_; - size_t num_pwrites_; - Thread::MutexBasicLockable open_mutex_; - Thread::MutexBasicLockable write_mutex_; - Thread::MutexBasicLockable pread_mutex_; - Thread::MutexBasicLockable pwrite_mutex_; - Thread::CondVar open_event_; - Thread::CondVar write_event_; - Thread::CondVar pread_event_; - Thread::CondVar pwrite_event_; + absl::Mutex mutex_; + uint64_t num_opens_{0}; + uint64_t num_writes_{0}; + uint64_t num_preads_{0}; + uint64_t num_pwrites_{0}; + + bool waitForEventCount(uint64_t& event_counter, uint64_t expected) { + auto func = [&]() { return event_counter == expected; }; + bool result = mutex_.LockWhenWithTimeout(absl::Condition(&func), absl::Seconds(15)); + mutex_.Unlock(); + return result; + } private: - bool is_open_; + bool is_open_{false}; }; class MockInstance : public Instance { From 58335ef81559035dab055c23215e313f6ed784f5 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Thu, 18 May 2023 09:17:55 -0700 Subject: [PATCH 006/228] Fix typo - adjustNewConnectionIdForRouting (#27456) Signed-off-by: Raven Black --- source/common/quic/envoy_quic_utils.cc | 2 +- source/common/quic/envoy_quic_utils.h | 2 +- .../envoy_deterministic_connection_id_generator.cc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/common/quic/envoy_quic_utils.cc b/source/common/quic/envoy_quic_utils.cc index 4a1325060fb1..1b0047a6537b 100644 --- a/source/common/quic/envoy_quic_utils.cc +++ b/source/common/quic/envoy_quic_utils.cc @@ -278,7 +278,7 @@ void configQuicInitialFlowControlWindow(const envoy::config::core::v3::QuicProto static_cast(session_flow_control_window_to_send))); } -void adjustNewConnectionIdForRoutine(quic::QuicConnectionId& new_connection_id, +void adjustNewConnectionIdForRouting(quic::QuicConnectionId& new_connection_id, const quic::QuicConnectionId& old_connection_id) { char* new_connection_id_data = new_connection_id.mutable_data(); const char* old_connection_id_ptr = old_connection_id.data(); diff --git a/source/common/quic/envoy_quic_utils.h b/source/common/quic/envoy_quic_utils.h index 966d7a6a1e93..5e3333b00bc2 100644 --- a/source/common/quic/envoy_quic_utils.h +++ b/source/common/quic/envoy_quic_utils.h @@ -190,7 +190,7 @@ void configQuicInitialFlowControlWindow(const envoy::config::core::v3::QuicProto // Modify new_connection_id according to given old_connection_id to make sure packets with the new // one can be routed to the same listener. -void adjustNewConnectionIdForRoutine(quic::QuicConnectionId& new_connection_id, +void adjustNewConnectionIdForRouting(quic::QuicConnectionId& new_connection_id, const quic::QuicConnectionId& old_connection_id); } // namespace Quic diff --git a/source/extensions/quic/connection_id_generator/envoy_deterministic_connection_id_generator.cc b/source/extensions/quic/connection_id_generator/envoy_deterministic_connection_id_generator.cc index 538979cfb705..92bb75e6756a 100644 --- a/source/extensions/quic/connection_id_generator/envoy_deterministic_connection_id_generator.cc +++ b/source/extensions/quic/connection_id_generator/envoy_deterministic_connection_id_generator.cc @@ -13,7 +13,7 @@ EnvoyDeterministicConnectionIdGenerator::GenerateNextConnectionId( const quic::QuicConnectionId& original) { auto new_cid = DeterministicConnectionIdGenerator::GenerateNextConnectionId(original); if (new_cid.has_value()) { - adjustNewConnectionIdForRoutine(new_cid.value(), original); + adjustNewConnectionIdForRouting(new_cid.value(), original); } return (new_cid.has_value() && new_cid.value() == original) ? absl::nullopt : new_cid; } @@ -23,7 +23,7 @@ EnvoyDeterministicConnectionIdGenerator::MaybeReplaceConnectionId( const quic::QuicConnectionId& original, const quic::ParsedQuicVersion& version) { auto new_cid = DeterministicConnectionIdGenerator::MaybeReplaceConnectionId(original, version); if (new_cid.has_value()) { - adjustNewConnectionIdForRoutine(new_cid.value(), original); + adjustNewConnectionIdForRouting(new_cid.value(), original); } return (new_cid.has_value() && new_cid.value() == original) ? absl::nullopt : new_cid; } From 3696ca57fdd735e0c8a8dc5a08926e14c328206d Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 18 May 2023 17:20:41 +0100 Subject: [PATCH 007/228] ci: Improve `/retest` (#27458) Signed-off-by: Ryan Northey --- .github/workflows/commands.yml | 10 ++++++++-- ci/repokitteh/modules/azure_pipelines.star | 21 +++++++++------------ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index 6d50ad40a10e..590f0d67b489 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -1,8 +1,12 @@ name: commands + on: issue_comment: types: [created] +permissions: + contents: read + jobs: retest: if: | @@ -13,8 +17,10 @@ jobs: && github.actor != 'dependabot[bot]' }} name: Retest - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 + permissions: + pull-requests: write steps: - - uses: jpsim/retest@c158dec0a7f67cb85f8367468dc8a9a75308bb7f + - uses: envoyproxy/toolshed/gh-actions/retest@56d5781416445ed530e075b71546dedee94cf054 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/ci/repokitteh/modules/azure_pipelines.star b/ci/repokitteh/modules/azure_pipelines.star index 9c6cbe9ecc9f..57d6a78f0056 100644 --- a/ci/repokitteh/modules/azure_pipelines.star +++ b/ci/repokitteh/modules/azure_pipelines.star @@ -31,10 +31,12 @@ def _get_azp_link(check_id): return "https://dev.azure.com/{organization}/{project}/_build/results?buildId={buildId}&view=results".format(organization = _azp_organization, project = project, buildId = build_id) def _retry(config, comment_id, command): - msgs = "Retrying Azure Pipelines:\n" + if len(command.parts) > 1 and command.parts[1] == "mobile": + return check_ids, checks = _get_azp_checks() retried_checks = [] + reaction = "confused" for check_id in check_ids: subchecks = [c for c in checks if c["external_id"] == check_id] if len(subchecks) == 0: @@ -50,20 +52,15 @@ def _retry(config, comment_id, command): if check["status"] == "in_progress": has_running = True - if not has_failure: - msgs += "Check {} didn't fail.\n".format(name_with_link) - else: - if has_running: - msgs += "Check {} isn't fully completed, but will still attempt retrying.\n".format(name_with_link) + if has_failure: _, build_id, project = check_id.split("|") _retry_azp(project, build_id, config["token"]) retried_checks.append(name_with_link) - if len(retried_checks) == 0: - react(comment_id, msgs) - else: - react(comment_id, None) - msgs += "Retried failed jobs in: {}".format(", ".join(retried_checks)) - github.issue_create_comment(msgs) + if len(retried_checks) != 0: + reaction = "+1" + + github.issue_create_comment_reaction(comment_id, reaction) + handlers.command(name = "retry-azp", func = _retry) From 2b1a5bc93910cf763f2e70733277e42a02b9f951 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 18 May 2023 17:31:51 +0100 Subject: [PATCH 008/228] deps: Bump `io_hyperscan` -> 5.4.2 (#27482) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 6c72be0aaf91..f5625d19c428 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -459,16 +459,16 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Hyperscan", project_desc = "High-performance regular expression matching library", project_url = "https://hyperscan.io", - version = "5c724f73d1aa5add73c06c97c59930899c713d47", - sha256 = "c0c9074a9f19db2fe70a78d4fcf39709072068a652b474f30f8f3931aa86ef3a", + version = "5.4.2", + sha256 = "32b0f24b3113bbc46b6bfaa05cf7cf45840b6b59333d078cc1f624e4c40b2b99", strip_prefix = "hyperscan-{version}", - urls = ["https://github.com/intel/hyperscan/archive/{version}.tar.gz"], + urls = ["https://github.com/intel/hyperscan/archive/v{version}.tar.gz"], use_category = ["dataplane_ext"], extensions = [ "envoy.matching.input_matchers.hyperscan", "envoy.regex_engines.hyperscan", ], - release_date = "2023-03-23", + release_date = "2023-04-19", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/intel/hyperscan/blob/{version}/LICENSE", From 071ff2ce42dce7704fde5092d4e1aafd4c9e391c Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 18 May 2023 20:27:38 +0100 Subject: [PATCH 009/228] deps: Bump `com_envoyproxy_protoc_gen_validate` -> 1.0.1 (#27480) Signed-off-by: Ryan Northey --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index 156de3232288..f6fd434d84ab 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -17,11 +17,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_desc = "protoc plugin to generate polyglot message validators", project_url = "https://github.com/bufbuild/protoc-gen-validate", use_category = ["api"], - sha256 = "f2c0f71591052f50d25745b2bcef2c3968e70474e70e84a19443d387bc40c31d", - version = "0.10.1", + sha256 = "f1ec013cfdfffa7a17d75b55d41265dad47d24e0e9d86c02311562e15be52da9", + version = "1.0.1", urls = ["https://github.com/bufbuild/protoc-gen-validate/archive/refs/tags/v{version}.zip"], strip_prefix = "protoc-gen-validate-{version}", - release_date = "2023-03-20", + release_date = "2023-05-09", implied_untracked_deps = [ "com_github_iancoleman_strcase", "com_github_lyft_protoc_gen_star", From 80f30f895ff6ab7b0ac412fa143f4a4474388b70 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 18 May 2023 20:54:36 +0100 Subject: [PATCH 010/228] ci: Maybe fix `/retest` permissions (#27489) Signed-off-by: Ryan Northey --- .github/workflows/commands.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index 590f0d67b489..35da322861f1 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -20,6 +20,7 @@ jobs: runs-on: ubuntu-22.04 permissions: pull-requests: write + actions: write steps: - uses: envoyproxy/toolshed/gh-actions/retest@56d5781416445ed530e075b71546dedee94cf054 with: From 79c1ae5dc797b8aa96c0e8ad8b4dcd131948938d Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 18 May 2023 20:55:13 +0100 Subject: [PATCH 011/228] deps: Bump `com_github_nghttp2_nghttp2` -> 1.53.0 (#27479) Fix #27346 Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index f5625d19c428..e87c24f7f4cc 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -445,12 +445,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Nghttp2", project_desc = "Implementation of HTTP/2 and its header compression algorithm HPACK in C", project_url = "https://nghttp2.org", - version = "1.52.0", - sha256 = "9877caa62bd72dde1331da38ce039dadb049817a01c3bdee809da15b754771b8", + version = "1.53.0", + sha256 = "f5f3f18b377d1e7658e4655a32d9a7ce6fef39fa13f600fe920f5f77c60fc34b", strip_prefix = "nghttp2-{version}", urls = ["https://github.com/nghttp2/nghttp2/releases/download/v{version}/nghttp2-{version}.tar.gz"], use_category = ["controlplane", "dataplane_core"], - release_date = "2023-02-13", + release_date = "2023-05-10", cpe = "cpe:2.3:a:nghttp2:nghttp2:*", license = "MIT", license_url = "https://github.com/nghttp2/nghttp2/blob/v{version}/LICENSE", From 9e15d378f1d43aa3df44f89e029ab40e6fd87f77 Mon Sep 17 00:00:00 2001 From: Robert Femmer <114982872+robertfemmer@users.noreply.github.com> Date: Thu, 18 May 2023 22:15:46 +0200 Subject: [PATCH 012/228] conn_manager_impl_test_base: Use global test symbol table (#27454) Currently, HttpConnectionManagerImplMixin uses a self-allocated symbol table. When used together with other mock classes that use the globally shared symbol table, debug assertions are tripped that require symbol table addresses to be equal. This change would force HttpConnectionManagerImplMixin to use the globally shared test symbol table. Signed-off-by: Robert Femmer --- test/common/http/conn_manager_impl_test_base.cc | 3 ++- test/common/http/conn_manager_impl_test_base.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/common/http/conn_manager_impl_test_base.cc b/test/common/http/conn_manager_impl_test_base.cc index 5d203bc53db0..1c5053246e44 100644 --- a/test/common/http/conn_manager_impl_test_base.cc +++ b/test/common/http/conn_manager_impl_test_base.cc @@ -13,7 +13,8 @@ namespace Envoy { namespace Http { HttpConnectionManagerImplMixin::HttpConnectionManagerImplMixin() - : http_context_(fake_stats_.symbolTable()), access_log_path_("dummy_path"), + : fake_stats_(*symbol_table_), http_context_(fake_stats_.symbolTable()), + access_log_path_("dummy_path"), access_logs_{AccessLog::InstanceSharedPtr{new Extensions::AccessLoggers::File::FileAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, access_log_path_}, {}, Formatter::SubstitutionFormatUtils::defaultSubstitutionFormatter(), log_manager_)}}, diff --git a/test/common/http/conn_manager_impl_test_base.h b/test/common/http/conn_manager_impl_test_base.h index eddca70cb681..99fdc9344118 100644 --- a/test/common/http/conn_manager_impl_test_base.h +++ b/test/common/http/conn_manager_impl_test_base.h @@ -207,6 +207,7 @@ class HttpConnectionManagerImplMixin : public ConnectionManagerConfig { std::shared_ptr route_config_{new NiceMock()}; NiceMock scoped_route_config_provider_; Router::MockScopeKeyBuilder scope_key_builder_; + Stats::TestUtil::TestSymbolTable symbol_table_; Stats::IsolatedStoreImpl fake_stats_; Http::ContextImpl http_context_; NiceMock runtime_; From 60643c6e3463d0593b1b19c9778edb8b323d8dca Mon Sep 17 00:00:00 2001 From: Christoph Pakulski Date: Thu, 18 May 2023 18:20:09 -0400 Subject: [PATCH 013/228] nit: update changelog after PR27296 (#27494) Signed-off-by: Christoph Pakulski --- changelogs/current.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index d9e8e8ea1660..a49260da1d22 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -93,6 +93,9 @@ bug_fixes: Do not display GRPC_STATUS_NUMBER for non gRPC requests. This behavioral change can be temporarily reverted by setting runtime guard ``envoy.reloadable_features.validate_grpc_header_before_log_grpc_status`` to false. +- area: boringssl + change: | + Fixed the crash that occurs when contrib is compiled with ``boringssl=fips`` defined. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` From 3f9f8f76b575ecf962d21f59d7e29fdec2eab610 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Thu, 18 May 2023 16:35:31 -0700 Subject: [PATCH 014/228] [file_system_http_cache] fix broken design doc link (#27498) Signed-off-by: Raven Black --- .../file_system_http_cache/v3/file_system_http_cache.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/http/cache/file_system_http_cache/v3/file_system_http_cache.proto b/api/envoy/extensions/http/cache/file_system_http_cache/v3/file_system_http_cache.proto index 91844d3ae880..ebedf30fa26c 100644 --- a/api/envoy/extensions/http/cache/file_system_http_cache/v3/file_system_http_cache.proto +++ b/api/envoy/extensions/http/cache/file_system_http_cache/v3/file_system_http_cache.proto @@ -26,7 +26,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // // By default this cache uses a least-recently-used eviction strategy. // -// For implementation details, see `DESIGN.md `_. +// For implementation details, see `DESIGN.md `_. // [#next-free-field: 11] message FileSystemHttpCacheConfig { // Configuration of a manager for how the file system is used asynchronously. From f979b22121d5b2c6f72bf1349680560b29815365 Mon Sep 17 00:00:00 2001 From: Xavid Date: Thu, 18 May 2023 19:36:30 -0400 Subject: [PATCH 015/228] server: support using the ApiListener from a worker thread (#27258) Before this change, the SyntheticReadCallbacks used by the ApiListener hard-coded the main thread dispatcher, resulting in dispatcher assertion failures if the ApiListener was used from a worker thread. This change allows it to use the appropriate dispatcher whether used from the main thread or a worker thread. Signed-off-by: Xavid Pretzer --- envoy/server/api_listener.h | 17 ++-- mobile/library/common/engine.cc | 10 +- mobile/library/common/http/client.cc | 2 +- mobile/library/common/http/client.h | 10 +- mobile/test/common/http/client_test.cc | 12 ++- .../network/http_connection_manager/config.cc | 9 +- .../network/http_connection_manager/config.h | 6 +- source/server/api_listener_impl.cc | 39 ++++---- source/server/api_listener_impl.h | 46 +++++++--- source/server/server.cc | 7 -- .../api_listener_integration_test.cc | 92 ++++++++++++++++--- test/server/api_listener_test.cc | 21 +++-- 12 files changed, 180 insertions(+), 91 deletions(-) diff --git a/envoy/server/api_listener.h b/envoy/server/api_listener.h index b14fb7068abd..35e7f61df605 100644 --- a/envoy/server/api_listener.h +++ b/envoy/server/api_listener.h @@ -21,22 +21,21 @@ class ApiListener { */ virtual absl::string_view name() const PURE; - /** - * Shutdown the ApiListener. This is an interrupt, not a drain. In other words, calling this - * function results in termination of all active streams vs. draining where no new streams are - * allowed, but already existing streams are allowed to finish. - */ - virtual void shutdown() PURE; - /** * @return the Type of the ApiListener. */ virtual Type type() const PURE; /** - * @return valid ref IFF type() == Type::HttpApiListener, otherwise nullopt. + * Create an Http::ApiListener capable of starting synthetic HTTP streams. The returned listener + * must only be deleted in the dispatcher's thread. + * + * While Envoy Mobile only uses this from the main thread, taking a dispatcher as a parameter + * allows other users to use this from worker threads as well. + * + * @return valid pointer IFF type() == Type::HttpApiListener, otherwise nullptr. */ - virtual Http::ApiListenerOptRef http() PURE; + virtual Http::ApiListenerPtr createHttpApiListener(Event::Dispatcher& dispatcher) PURE; }; using ApiListenerPtr = std::unique_ptr; diff --git a/mobile/library/common/engine.cc b/mobile/library/common/engine.cc index d54c6f3b5658..a21c37c80ac5 100644 --- a/mobile/library/common/engine.cc +++ b/mobile/library/common/engine.cc @@ -109,9 +109,10 @@ envoy_status_t Engine::main(std::unique_ptr&& options) { // on-the-fly without risking contention on system with lots of threads. // It also comes with ease of programming. stat_name_set_ = client_scope_->symbolTable().makeSet("pulse"); - auto api_listener = server_->listenerManager().apiListener()->get().http(); - ASSERT(api_listener.has_value()); - http_client_ = std::make_unique(api_listener.value(), *dispatcher_, + auto api_listener = server_->listenerManager().apiListener()->get().createHttpApiListener( + server_->dispatcher()); + ASSERT(api_listener != nullptr); + http_client_ = std::make_unique(std::move(api_listener), *dispatcher_, server_->serverFactoryContext().scope(), server_->api().randomGenerator()); dispatcher_->drain(server_->dispatcher()); @@ -156,6 +157,9 @@ envoy_status_t Engine::terminate() { ASSERT(event_dispatcher_); ASSERT(dispatcher_); + // We must destroy the Http::ApiListener in the main thread. + dispatcher_->post([this]() { http_client_->shutdownApiListener(); }); + // Exit the event loop and finish up in Engine::run(...) if (std::this_thread::get_id() == main_thread_.get_id()) { // TODO(goaway): figure out some way to support this. diff --git a/mobile/library/common/http/client.cc b/mobile/library/common/http/client.cc index d2efc7d1e8a6..250e53d437db 100644 --- a/mobile/library/common/http/client.cc +++ b/mobile/library/common/http/client.cc @@ -476,7 +476,7 @@ void Client::startStream(envoy_stream_t new_stream_handle, envoy_http_callbacks // Note: streams created by Envoy Mobile are tagged as is_internally_created. This means that // the Http::ConnectionManager _will not_ sanitize headers when creating a stream. direct_stream->request_decoder_ = - &api_listener_.newStream(*direct_stream->callbacks_, true /* is_internally_created */); + &api_listener_->newStream(*direct_stream->callbacks_, true /* is_internally_created */); streams_.emplace(new_stream_handle, std::move(direct_stream)); ENVOY_LOG(debug, "[S{}] start stream", new_stream_handle); diff --git a/mobile/library/common/http/client.h b/mobile/library/common/http/client.h index 3fb622c3ee0d..5a23f929c7f4 100644 --- a/mobile/library/common/http/client.h +++ b/mobile/library/common/http/client.h @@ -51,9 +51,9 @@ struct HttpClientStats { */ class Client : public Logger::Loggable { public: - Client(ApiListener& api_listener, Event::ProvisionalDispatcher& dispatcher, Stats::Scope& scope, - Random::RandomGenerator& random) - : api_listener_(api_listener), dispatcher_(dispatcher), + Client(ApiListenerPtr&& api_listener, Event::ProvisionalDispatcher& dispatcher, + Stats::Scope& scope, Random::RandomGenerator& random) + : api_listener_(std::move(api_listener)), dispatcher_(dispatcher), stats_( HttpClientStats{ALL_HTTP_CLIENT_STATS(POOL_COUNTER_PREFIX(scope, "http.client."), POOL_HISTOGRAM_PREFIX(scope, "http.client."))}), @@ -129,6 +129,8 @@ class Client : public Logger::Loggable { CONSTRUCT_ON_FIRST_USE(std::string, "client_cancelled_stream"); } + void shutdownApiListener() { api_listener_.reset(); } + private: class DirectStream; friend class ClientTest; @@ -377,7 +379,7 @@ class Client : public Logger::Loggable { void removeStream(envoy_stream_t stream_handle); void setDestinationCluster(RequestHeaderMap& headers); - ApiListener& api_listener_; + ApiListenerPtr api_listener_; Event::ProvisionalDispatcher& dispatcher_; Event::SchedulableCallbackPtr scheduled_callback_; HttpClientStats stats_; diff --git a/mobile/test/common/http/client_test.cc b/mobile/test/common/http/client_test.cc index d64546c8985d..a31c294064c2 100644 --- a/mobile/test/common/http/client_test.cc +++ b/mobile/test/common/http/client_test.cc @@ -131,7 +131,7 @@ class ClientTest : public testing::TestWithParam { // Grab the response encoder in order to dispatch responses on the stream. // Return the request decoder to make sure calls are dispatched to the decoder via the // dispatcher API. - EXPECT_CALL(api_listener_, newStream(_, _)) + EXPECT_CALL(*api_listener_, newStream(_, _)) .WillOnce(Invoke([&](ResponseEncoder& encoder, bool) -> RequestDecoder& { response_encoder_ = &encoder; return *request_decoder_; @@ -146,7 +146,8 @@ class ClientTest : public testing::TestWithParam { } } - MockApiListener api_listener_; + std::unique_ptr owned_api_listener_ = std::make_unique(); + MockApiListener* api_listener_ = owned_api_listener_.get(); std::unique_ptr> request_decoder_{ std::make_unique>()}; NiceMock stream_info_; @@ -157,7 +158,8 @@ class ClientTest : public testing::TestWithParam { NiceMock random_; Stats::IsolatedStoreImpl stats_store_; bool explicit_flow_control_{GetParam()}; - Client http_client_{api_listener_, dispatcher_, *stats_store_.rootScope(), random_}; + Client http_client_{std::move(owned_api_listener_), dispatcher_, *stats_store_.rootScope(), + random_}; envoy_stream_t stream_ = 1; protected: @@ -423,7 +425,7 @@ TEST_P(ClientTest, MultipleStreams) { // Grab the response encoder in order to dispatch responses on the stream. // Return the request decoder to make sure calls are dispatched to the decoder via the dispatcher // API. - EXPECT_CALL(api_listener_, newStream(_, _)) + EXPECT_CALL(*api_listener_, newStream(_, _)) .WillOnce(Invoke([&](ResponseEncoder& encoder, bool) -> RequestDecoder& { response_encoder2 = &encoder; return request_decoder2; @@ -684,7 +686,7 @@ TEST_P(ClientTest, NullAccessors) { // Grab the response encoder in order to dispatch responses on the stream. // Return the request decoder to make sure calls are dispatched to the decoder via the dispatcher // API. - EXPECT_CALL(api_listener_, newStream(_, _)) + EXPECT_CALL(*api_listener_, newStream(_, _)) .WillOnce(Invoke([&](ResponseEncoder& encoder, bool) -> RequestDecoder& { response_encoder_ = &encoder; return *request_decoder_; diff --git a/source/extensions/filters/network/http_connection_manager/config.cc b/source/extensions/filters/network/http_connection_manager/config.cc index 3fabdb579b3a..7594c5f02247 100644 --- a/source/extensions/filters/network/http_connection_manager/config.cc +++ b/source/extensions/filters/network/http_connection_manager/config.cc @@ -766,12 +766,11 @@ HttpConnectionManagerConfig::getHeaderValidatorStats([[maybe_unused]] Http::Prot } #endif -std::function +std::function HttpConnectionManagerFactory::createHttpConnectionManagerFactoryFromProto( const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& proto_config, - Server::Configuration::FactoryContext& context, Network::ReadFilterCallbacks& read_callbacks, - bool clear_hop_by_hop_headers) { + Server::Configuration::FactoryContext& context, bool clear_hop_by_hop_headers) { Utility::Singletons singletons = Utility::createSingletons(context); auto filter_config = Utility::createConfig( @@ -783,8 +782,8 @@ HttpConnectionManagerFactory::createHttpConnectionManagerFactoryFromProto( // reference count. // Keep in mind the lambda capture list **doesn't** determine the destruction order, but it's fine // as these captured objects are also global singletons. - return [singletons, filter_config, &context, &read_callbacks, - clear_hop_by_hop_headers]() -> Http::ApiListenerPtr { + return [singletons, filter_config, &context, clear_hop_by_hop_headers]( + Network::ReadFilterCallbacks& read_callbacks) -> Http::ApiListenerPtr { auto conn_manager = std::make_unique( *filter_config, context.drainDecision(), context.api().randomGenerator(), context.httpContext(), context.runtime(), context.localInfo(), context.clusterManager(), diff --git a/source/extensions/filters/network/http_connection_manager/config.h b/source/extensions/filters/network/http_connection_manager/config.h index da8126fb2aea..09d76f31dcbd 100644 --- a/source/extensions/filters/network/http_connection_manager/config.h +++ b/source/extensions/filters/network/http_connection_manager/config.h @@ -366,11 +366,11 @@ class HttpConnectionManagerConfig : Logger::Loggable, */ class HttpConnectionManagerFactory { public: - static std::function createHttpConnectionManagerFactoryFromProto( + static std::function + createHttpConnectionManagerFactoryFromProto( const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& proto_config, - Server::Configuration::FactoryContext& context, Network::ReadFilterCallbacks& read_callbacks, - bool clear_hop_by_hop_headers); + Server::Configuration::FactoryContext& context, bool clear_hop_by_hop_headers); }; /** diff --git a/source/server/api_listener_impl.cc b/source/server/api_listener_impl.cc index 93aa6e4a5ad7..0ea54f552f7a 100644 --- a/source/server/api_listener_impl.cc +++ b/source/server/api_listener_impl.cc @@ -1,6 +1,7 @@ #include "source/server/api_listener_impl.h" #include "envoy/config/listener/v3/listener.pb.h" +#include "envoy/http/api_listener.h" #include "envoy/stats/scope.h" #include "source/common/http/conn_manager_impl.h" @@ -21,8 +22,7 @@ ApiListenerImplBase::ApiListenerImplBase(const envoy::config::listener::v3::List address_(Network::Address::resolveProtoAddress(config.address())), global_scope_(server.stats().createScope("")), listener_scope_(server.stats().createScope(fmt::format("listener.api.{}.", name_))), - factory_context_(server, config_, *this, *global_scope_, *listener_scope_, isQuic(config)), - read_callbacks_(SyntheticReadCallbacks(*this)) {} + factory_context_(server, config_, *this, *global_scope_, *listener_scope_, isQuic(config)) {} void ApiListenerImplBase::SyntheticReadCallbacks::SyntheticConnection::raiseConnectionEvent( Network::ConnectionEvent event) { @@ -31,6 +31,19 @@ void ApiListenerImplBase::SyntheticReadCallbacks::SyntheticConnection::raiseConn } } +HttpApiListener::ApiListenerWrapper::~ApiListenerWrapper() { + // The Http::ConnectionManagerImpl is a callback target for the read_callback_.connection_. By + // raising connection closure, Http::ConnectionManagerImpl::onEvent is fired. In that case the + // Http::ConnectionManagerImpl will reset any ActiveStreams it has. + read_callbacks_.connection_.raiseConnectionEvent(Network::ConnectionEvent::RemoteClose); +} + +Http::RequestDecoder& +HttpApiListener::ApiListenerWrapper::newStream(Http::ResponseEncoder& response_encoder, + bool is_internally_created) { + return http_connection_manager_->newStream(response_encoder, is_internally_created); +} + HttpApiListener::HttpApiListener(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name) : ApiListenerImplBase(config, server, name) { @@ -46,30 +59,20 @@ HttpApiListener::HttpApiListener(const envoy::config::listener::v3::Listener& co http_connection_manager_factory_ = Envoy::Extensions::NetworkFilters::HttpConnectionManager:: HttpConnectionManagerFactory::createHttpConnectionManagerFactoryFromProto( - typed_config.config(), factory_context_, read_callbacks_, false); + typed_config.config(), factory_context_, false); } else { auto typed_config = MessageUtil::anyConvertAndValidate< envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager>( config.api_listener().api_listener(), factory_context_.messageValidationVisitor()); - http_connection_manager_factory_ = Envoy::Extensions::NetworkFilters::HttpConnectionManager:: - HttpConnectionManagerFactory::createHttpConnectionManagerFactoryFromProto( - typed_config, factory_context_, read_callbacks_, true); - } -} - -Http::ApiListenerOptRef HttpApiListener::http() { - if (!http_connection_manager_) { - http_connection_manager_ = http_connection_manager_factory_(); + http_connection_manager_factory_ = + Envoy::Extensions::NetworkFilters::HttpConnectionManager::HttpConnectionManagerFactory:: + createHttpConnectionManagerFactoryFromProto(typed_config, factory_context_, true); } - return Http::ApiListenerOptRef(std::ref(*http_connection_manager_)); } -void HttpApiListener::shutdown() { - // The Http::ConnectionManagerImpl is a callback target for the read_callback_.connection_. By - // raising connection closure, Http::ConnectionManagerImpl::onEvent is fired. In that case the - // Http::ConnectionManagerImpl will reset any ActiveStreams it has. - read_callbacks_.connection_.raiseConnectionEvent(Network::ConnectionEvent::RemoteClose); +Http::ApiListenerPtr HttpApiListener::createHttpApiListener(Event::Dispatcher& dispatcher) { + return std::make_unique(*this, dispatcher); } } // namespace Server diff --git a/source/server/api_listener_impl.h b/source/server/api_listener_impl.h index 2e260666a8f1..1f18ffe1efac 100644 --- a/source/server/api_listener_impl.h +++ b/source/server/api_listener_impl.h @@ -5,6 +5,7 @@ #include "envoy/config/core/v3/base.pb.h" #include "envoy/config/listener/v3/listener.pb.h" +#include "envoy/event/dispatcher.h" #include "envoy/network/connection.h" #include "envoy/network/filter.h" #include "envoy/network/socket.h" @@ -57,8 +58,8 @@ class ApiListenerImplBase : public ApiListener, // need this and the SyntheticConnection stub anymore. class SyntheticReadCallbacks : public Network::ReadFilterCallbacks { public: - SyntheticReadCallbacks(ApiListenerImplBase& parent) - : parent_(parent), connection_(SyntheticConnection(*this)) {} + SyntheticReadCallbacks(ApiListenerImplBase& parent, Event::Dispatcher& dispatcher) + : parent_(parent), connection_(SyntheticConnection(*this, dispatcher)) {} // Network::ReadFilterCallbacks void continueReading() override { IS_ENVOY_BUG("Unexpected call to continueReading"); } @@ -80,8 +81,8 @@ class ApiListenerImplBase : public ApiListener, // Network::ReadFilterCallbacks. class SyntheticConnection : public Network::Connection { public: - SyntheticConnection(SyntheticReadCallbacks& parent) - : parent_(parent), + SyntheticConnection(SyntheticReadCallbacks& parent, Event::Dispatcher& dispatcher) + : parent_(parent), dispatcher_(dispatcher), connection_info_provider_(std::make_shared( parent.parent_.address_, parent.parent_.address_)), stream_info_(parent_.parent_.factory_context_.timeSource(), connection_info_provider_), @@ -121,9 +122,7 @@ class ApiListenerImplBase : public ApiListener, } void close(Network::ConnectionCloseType) override {} void close(Network::ConnectionCloseType, absl::string_view) override {} - Event::Dispatcher& dispatcher() override { - return parent_.parent_.factory_context_.mainThreadDispatcher(); - } + Event::Dispatcher& dispatcher() override { return dispatcher_; } uint64_t id() const override { return 12345; } void hashKey(std::vector&) const override {} std::string nextProtocol() const override { return EMPTY_STRING; } @@ -174,6 +173,7 @@ class ApiListenerImplBase : public ApiListener, void dumpState(std::ostream& os, int) const override { os << "SyntheticConnection"; } SyntheticReadCallbacks& parent_; + Event::Dispatcher& dispatcher_; Network::ConnectionInfoSetterSharedPtr connection_info_provider_; StreamInfo::StreamInfoImpl stream_info_; Network::ConnectionSocket::OptionsSharedPtr options_; @@ -190,7 +190,6 @@ class ApiListenerImplBase : public ApiListener, Stats::ScopeSharedPtr global_scope_; Stats::ScopeSharedPtr listener_scope_; FactoryContextImpl factory_context_; - SyntheticReadCallbacks read_callbacks_; }; /** @@ -199,22 +198,39 @@ class ApiListenerImplBase : public ApiListener, */ class HttpApiListener : public ApiListenerImplBase { public: + // Class to wrap an Http::ApiListener and the associated SyntheticReadCallbacks to ensure that + // both objects have the same lifetime. + // + // Public for testing. + class ApiListenerWrapper : public Http::ApiListener { + public: + ApiListenerWrapper(HttpApiListener& parent, Event::Dispatcher& dispatcher) + : read_callbacks_(parent, dispatcher), + http_connection_manager_(parent.http_connection_manager_factory_(read_callbacks_)) {} + ~ApiListenerWrapper() override; + + Http::RequestDecoder& newStream(Http::ResponseEncoder& response_encoder, + bool is_internally_created = false) override; + + SyntheticReadCallbacks& readCallbacks() { return read_callbacks_; } + + private: + SyntheticReadCallbacks read_callbacks_; + Http::ApiListenerPtr http_connection_manager_; + }; + HttpApiListener(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name); // ApiListener ApiListener::Type type() const override { return ApiListener::Type::HttpApiListener; } - Http::ApiListenerOptRef http() override; - void shutdown() override; - - Network::ReadFilterCallbacks& readCallbacksForTest() { return read_callbacks_; } + Http::ApiListenerPtr createHttpApiListener(Event::Dispatcher& dispatcher) override; private: // Need to store the factory due to the shared_ptrs that need to be kept alive: date provider, // route config manager, scoped route config manager. - std::function http_connection_manager_factory_; - // Http::ServerConnectionCallbacks is the API surface that this class provides via its handle(). - Http::ApiListenerPtr http_connection_manager_; + std::function + http_connection_manager_factory_; }; } // namespace Server diff --git a/source/server/server.cc b/source/server/server.cc index 42908d7af321..f5c2b062ea8b 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -970,13 +970,6 @@ void InstanceImpl::terminate() { // Shutdown all the workers now that the main dispatch loop is done. if (listener_manager_ != nullptr) { - // Also shutdown the listener manager's ApiListener, if there is one, which runs on the main - // thread. This needs to happen ahead of calling thread_local_.shutdown() below to prevent any - // objects in the ApiListener destructor to reference any objects in thread local storage. - if (listener_manager_->apiListener().has_value()) { - listener_manager_->apiListener()->get().shutdown(); - } - listener_manager_->stopWorkers(); } diff --git a/test/integration/api_listener_integration_test.cc b/test/integration/api_listener_integration_test.cc index e4a206a41a15..e4aa8c4bbbcd 100644 --- a/test/integration/api_listener_integration_test.cc +++ b/test/integration/api_listener_integration_test.cc @@ -86,15 +86,17 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, ApiListenerIntegrationTest, TEST_P(ApiListenerIntegrationTest, Basic) { BaseIntegrationTest::initialize(); absl::Notification done; - test_server_->server().dispatcher().post([this, &done]() -> void { + Http::ApiListenerPtr http_api_listener; + test_server_->server().dispatcher().post([this, &done, &http_api_listener]() -> void { ASSERT_TRUE(test_server_->server().listenerManager().apiListener().has_value()); ASSERT_EQ("api_listener", test_server_->server().listenerManager().apiListener()->get().name()); - ASSERT_TRUE(test_server_->server().listenerManager().apiListener()->get().http().has_value()); - auto& http_api_listener = - test_server_->server().listenerManager().apiListener()->get().http()->get(); + http_api_listener = + test_server_->server().listenerManager().apiListener()->get().createHttpApiListener( + test_server_->server().dispatcher()); + ASSERT_TRUE(http_api_listener != nullptr); ON_CALL(stream_encoder_, getStream()).WillByDefault(ReturnRef(stream_encoder_.stream_)); - auto& stream_decoder = http_api_listener.newStream(stream_encoder_); + auto& stream_decoder = http_api_listener->newStream(stream_encoder_); // The AutonomousUpstream responds with 200 OK and a body of 10 bytes. // In the http1 codec the end stream is encoded with encodeData and 0 bytes. @@ -110,6 +112,14 @@ TEST_P(ApiListenerIntegrationTest, Basic) { true); }); ASSERT_TRUE(done.WaitForNotificationWithTimeout(absl::Seconds(1))); + + absl::Notification cleanup_done; + test_server_->server().dispatcher().post([&cleanup_done, &http_api_listener]() { + // Must be deleted in same thread. + http_api_listener.reset(); + cleanup_done.Notify(); + }); + ASSERT_TRUE(cleanup_done.WaitForNotificationWithTimeout(absl::Seconds(1))); } TEST_P(ApiListenerIntegrationTest, DestroyWithActiveStreams) { @@ -120,12 +130,13 @@ TEST_P(ApiListenerIntegrationTest, DestroyWithActiveStreams) { test_server_->server().dispatcher().post([this, &done]() -> void { ASSERT_TRUE(test_server_->server().listenerManager().apiListener().has_value()); ASSERT_EQ("api_listener", test_server_->server().listenerManager().apiListener()->get().name()); - ASSERT_TRUE(test_server_->server().listenerManager().apiListener()->get().http().has_value()); - auto& http_api_listener = - test_server_->server().listenerManager().apiListener()->get().http()->get(); + auto http_api_listener = + test_server_->server().listenerManager().apiListener()->get().createHttpApiListener( + test_server_->server().dispatcher()); + ASSERT_TRUE(http_api_listener != nullptr); ON_CALL(stream_encoder_, getStream()).WillByDefault(ReturnRef(stream_encoder_.stream_)); - auto& stream_decoder = http_api_listener.newStream(stream_encoder_); + auto& stream_decoder = http_api_listener->newStream(stream_encoder_); // Send a headers-only request stream_decoder.decodeHeaders( @@ -134,10 +145,69 @@ TEST_P(ApiListenerIntegrationTest, DestroyWithActiveStreams) { false); done.Notify(); + // http_api_listener is destroyed here with an active stream; thus this test verifies that + // there is no crash when this happens. + http_api_listener.reset(); }); ASSERT_TRUE(done.WaitForNotificationWithTimeout(absl::Seconds(1))); - // The server should shutdown the ApiListener at the right time during server termination such - // that no crashes occur if termination happens when the ApiListener still has ongoing streams. +} + +TEST_P(ApiListenerIntegrationTest, FromWorkerThread) { + BaseIntegrationTest::initialize(); + + absl::Mutex dispatchers_mutex; + std::vector dispatchers; + absl::Notification has_dispatcher; + ThreadLocal::TypedSlotPtr<> slot = + ThreadLocal::TypedSlot<>::makeUnique(test_server_->server().threadLocal()); + slot->set([&dispatchers_mutex, &dispatchers, &has_dispatcher]( + Event::Dispatcher& dispatcher) -> std::shared_ptr { + absl::MutexLock ml(&dispatchers_mutex); + // A string comparison on thread name seems to be the only way to + // distinguish worker threads from the main thread with the slots interface. + if (dispatcher.name() != "main_thread") { + dispatchers.push_back(&dispatcher); + has_dispatcher.Notify(); + } + return nullptr; + }); + ASSERT_TRUE(has_dispatcher.WaitForNotificationWithTimeout(absl::Seconds(1))); + + absl::Notification done; + Http::ApiListenerPtr http_api_listener; + dispatchers[0]->post([this, &done, &http_api_listener, &dispatchers]() -> void { + ASSERT_TRUE(test_server_->server().listenerManager().apiListener().has_value()); + ASSERT_EQ("api_listener", test_server_->server().listenerManager().apiListener()->get().name()); + http_api_listener = + test_server_->server().listenerManager().apiListener()->get().createHttpApiListener( + *dispatchers[0]); + ASSERT_TRUE(http_api_listener != nullptr); + + ON_CALL(stream_encoder_, getStream()).WillByDefault(ReturnRef(stream_encoder_.stream_)); + auto& stream_decoder = http_api_listener->newStream(stream_encoder_); + + // The AutonomousUpstream responds with 200 OK and a body of 10 bytes. + // In the http1 codec the end stream is encoded with encodeData and 0 bytes. + Http::TestResponseHeaderMapImpl expected_response_headers{{":status", "200"}}; + EXPECT_CALL(stream_encoder_, encodeHeaders(_, false)); + EXPECT_CALL(stream_encoder_, encodeData(_, false)); + EXPECT_CALL(stream_encoder_, encodeData(BufferStringEqual(""), true)).WillOnce(Notify(&done)); + + // Send a headers-only request + stream_decoder.decodeHeaders( + Http::RequestHeaderMapPtr(new Http::TestRequestHeaderMapImpl{ + {":method", "GET"}, {":path", "/api"}, {":scheme", "http"}, {":authority", "host"}}), + true); + }); + ASSERT_TRUE(done.WaitForNotificationWithTimeout(absl::Seconds(1))); + + absl::Notification cleanup_done; + dispatchers[0]->post([&cleanup_done, &http_api_listener]() { + // Must be deleted in same thread. + http_api_listener.reset(); + cleanup_done.Notify(); + }); + ASSERT_TRUE(cleanup_done.WaitForNotificationWithTimeout(absl::Seconds(1))); } } // namespace diff --git a/test/server/api_listener_test.cc b/test/server/api_listener_test.cc index 46a2f74a9567..7183f80b8651 100644 --- a/test/server/api_listener_test.cc +++ b/test/server/api_listener_test.cc @@ -57,7 +57,7 @@ name: test_api_listener ASSERT_EQ("test_api_listener", http_api_listener.name()); ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); - ASSERT_TRUE(http_api_listener.http().has_value()); + ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, MobileApiListener) { @@ -92,7 +92,7 @@ name: test_api_listener ASSERT_EQ("test_api_listener", http_api_listener.name()); ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); - ASSERT_TRUE(http_api_listener.http().has_value()); + ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, HttpApiListenerThrowsWithBadConfig) { @@ -163,21 +163,22 @@ name: test_api_listener ASSERT_EQ("test_api_listener", http_api_listener.name()); ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); - ASSERT_TRUE(http_api_listener.http().has_value()); + auto api_listener = http_api_listener.createHttpApiListener(server_.dispatcher()); + ASSERT_NE(api_listener, nullptr); Network::MockConnectionCallbacks network_connection_callbacks; // TODO(junr03): potentially figure out a way of unit testing this behavior without exposing a // ForTest function. - http_api_listener.readCallbacksForTest().connection().addConnectionCallbacks( - network_connection_callbacks); - EXPECT_FALSE( - http_api_listener.readCallbacksForTest().connection().lastRoundTripTime().has_value()); - http_api_listener.readCallbacksForTest().connection().configureInitialCongestionWindow( - 100, std::chrono::microseconds(123)); + auto& connection = dynamic_cast(api_listener.get()) + ->readCallbacks() + .connection(); + connection.addConnectionCallbacks(network_connection_callbacks); + EXPECT_FALSE(connection.lastRoundTripTime().has_value()); + connection.configureInitialCongestionWindow(100, std::chrono::microseconds(123)); EXPECT_CALL(network_connection_callbacks, onEvent(Network::ConnectionEvent::RemoteClose)); // Shutting down the ApiListener should raise an event on all connection callback targets. - http_api_listener.shutdown(); + api_listener.reset(); } } // namespace Server From 143aafb6e98e2cec5781fe56e7c8905832097105 Mon Sep 17 00:00:00 2001 From: Kuat Date: Thu, 18 May 2023 20:06:11 -0700 Subject: [PATCH 016/228] deps: update abseil (#27463) Commit Message: update abseil to head Additional Description: there's a problem with cel-cpp using an internal macro from abseil. To decouple absl from cel-cpp update, we have to patch cel-cpp temporarily. Risk Level: low Testing: regression --- bazel/cel-cpp.patch | 22 +++++++++++++++++++ bazel/repository_locations.bzl | 6 ++--- .../common/thread_local/thread_local_impl.cc | 2 +- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/bazel/cel-cpp.patch b/bazel/cel-cpp.patch index ac7d82733c0f..12e2f7342f7b 100644 --- a/bazel/cel-cpp.patch +++ b/bazel/cel-cpp.patch @@ -1,3 +1,25 @@ +diff --git a/base/memory_manager.cc b/base/memory_manager.cc +index 1b7b355..4c7810c 100644 +--- a/base/memory_manager.cc ++++ b/base/memory_manager.cc +@@ -234,7 +234,7 @@ class GlobalMemoryManager final : public MemoryManager { + void* Allocate(size_t size, size_t align) override { + static_cast(size); + static_cast(align); +- ABSL_INTERNAL_UNREACHABLE; ++ ABSL_UNREACHABLE(); + return nullptr; + } + +@@ -242,7 +242,7 @@ class GlobalMemoryManager final : public MemoryManager { + void OwnDestructor(void* pointer, void (*destructor)(void*)) override { + static_cast(pointer); + static_cast(destructor); +- ABSL_INTERNAL_UNREACHABLE; ++ ABSL_UNREACHABLE(); + } + }; + diff --git a/eval/eval/evaluator_stack.h b/eval/eval/evaluator_stack.h index 1ecab27..9df65d7 100644 --- a/eval/eval/evaluator_stack.h diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index e87c24f7f4cc..11220c3d18b9 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -151,12 +151,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Abseil", project_desc = "Open source collection of C++ libraries drawn from the most fundamental pieces of Google’s internal codebase", project_url = "https://abseil.io/", - version = "9bff2a9302a8dbf91712fc215eb2e2cf8ec234e7", - sha256 = "ae959138730b55b3fb968d3c357e740e7ffdeab4648dc3eb28843a1e9fa56b57", + version = "c8b33b0191a2db8364cacf94b267ea8a3f20ad83", + sha256 = "a7803eac00bf68eae1a84ee3b9fcf0c1173e8d9b89b2cee92c7b487ea65be2a9", strip_prefix = "abseil-cpp-{version}", urls = ["https://github.com/abseil/abseil-cpp/archive/{version}.tar.gz"], use_category = ["dataplane_core", "controlplane"], - release_date = "2022-12-07", + release_date = "2023-05-16", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/abseil/abseil-cpp/blob/{version}/LICENSE", diff --git a/source/common/thread_local/thread_local_impl.cc b/source/common/thread_local/thread_local_impl.cc index a9b0a21ab5aa..88981133cff0 100644 --- a/source/common/thread_local/thread_local_impl.cc +++ b/source/common/thread_local/thread_local_impl.cc @@ -26,7 +26,7 @@ SlotPtr InstanceImpl::allocateSlot() { ASSERT(!shutdown_); if (free_slot_indexes_.empty()) { - SlotPtr slot = std::make_unique(*this, slots_.size()); + SlotPtr slot = std::make_unique(*this, uint32_t(slots_.size())); slots_.push_back(slot.get()); return slot; } From b82371e8b04a9a9bb61f53e3280da60d726333b7 Mon Sep 17 00:00:00 2001 From: David Schinazi Date: Thu, 18 May 2023 20:33:35 -0700 Subject: [PATCH 017/228] Update QUICHE from d687c5fc0 to 4a5e9e692 (#27467) * Update QUICHE from d687c5fc0 to 8cd348bd2 https://github.com/google/quiche/compare/d687c5fc0..8cd348bd2 ``` $ git log d687c5fc0..8cd348bd2 --date=short --no-merges --format="%ad %al %s" 2023-05-17 danzh Rename QuicSpdyStream::AreHeadersValid() to ValidatedRequestHeaders() and retain error details in the stream if it returns false. 2023-05-17 wub Add alpn to interface QuicTestServer::SessionFactory::CreateSession. 2023-05-17 bnc Add test for MAYBE_BODY_BUT_NO_CONTENT_LENGTH warning. 2023-05-17 elburrito Add token expiration time checks to CachedBlindSignAuth to ensure that it only returns fresh tokens. Token expiration time is based on the AT server's signing public key. 2023-05-16 davidben Log encrypted ClientHellos through QuicConnectionDebugVisitor 2023-05-16 vasilvv Remove the header argument from WebTransport OnSessionReady callback 2023-05-16 martinduke Delete useless member variable QuicFramer::last_serialized_client_connection_id_. ``` Signed-off-by: David Schinazi --- bazel/external/quiche.BUILD | 7 +++++-- bazel/repository_locations.bzl | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/bazel/external/quiche.BUILD b/bazel/external/quiche.BUILD index 216669c395c9..cd3df2b203d3 100644 --- a/bazel/external/quiche.BUILD +++ b/bazel/external/quiche.BUILD @@ -4523,11 +4523,14 @@ envoy_cc_library( name = "quic_core_udp_socket_lib", srcs = select({ "@envoy//bazel:windows_x86_64": [], - "//conditions:default": ["quiche/quic/core/quic_udp_socket_posix.cc"], + "//conditions:default": ["quiche/quic/core/quic_udp_socket.cc"], }), hdrs = select({ "@envoy//bazel:windows_x86_64": [], - "//conditions:default": ["quiche/quic/core/quic_udp_socket.h"], + "//conditions:default": [ + "quiche/quic/core/quic_udp_socket.h", + "quiche/quic/core/quic_udp_socket_posix.inc", + ], }), copts = quiche_copts + select({ # On OSX/iOS, constants from RFC 3542 (e.g. IPV6_RECVPKTINFO) are not usable diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 11220c3d18b9..96730b84e5a3 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1056,12 +1056,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "QUICHE", project_desc = "QUICHE (QUIC, HTTP/2, Etc) is Google‘s implementation of QUIC and related protocols", project_url = "https://github.com/google/quiche", - version = "d687c5fc08dc2d05b4e253237173f99eed06488c", - sha256 = "3c704355f9ee4daab15af666b258071d76f1d985c2c725fe65dbe55d643b92cb", + version = "4a5e9e692040ff0786563c30488a7d29fd58f40d", + sha256 = "59e4712549c8f39fa31b5ded59ab548538384785bcc0854ee59221160f91a16d", urls = ["https://github.com/google/quiche/archive/{version}.tar.gz"], strip_prefix = "quiche-{version}", use_category = ["controlplane", "dataplane_core"], - release_date = "2023-05-12", + release_date = "2023-05-17", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/google/quiche/blob/{version}/LICENSE", From 98a37d0e8839f32b506ac9873448af84dfad0c19 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 19 May 2023 04:35:01 +0100 Subject: [PATCH 018/228] deps: Bump `aspect_bazel_lib` -> 1.32.0 (#27478) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 96730b84e5a3..95e2e28b6b04 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -137,12 +137,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Aspect Bazel helpers", project_desc = "Base Starlark libraries and basic Bazel rules which are useful for constructing rulesets and BUILD files", project_url = "https://github.com/aspect-build/bazel-lib", - version = "1.31.1", - sha256 = "5f3443b1d98a462a8b7330f4742483afc8b2d17c8555dd97ce4146f43e961718", + version = "1.32.0", + sha256 = "f1c181b910f821072f38ee45bb87db6b56275458c7f832c54c54ba6334119eca", strip_prefix = "bazel-lib-{version}", urls = ["https://github.com/aspect-build/bazel-lib/archive/v{version}.tar.gz"], use_category = ["build"], - release_date = "2023-05-05", + release_date = "2023-05-16", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/aspect-build/bazel-lib/blob/v{version}/LICENSE", From 4f3c266bace6c3ddc104fc34d333ceda5d49671c Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 19 May 2023 08:31:18 +0100 Subject: [PATCH 019/228] deps: Bump build-image -> 41c5a05 (#27487) Signed-off-by: Ryan Northey --- .bazelrc | 2 +- .devcontainer/Dockerfile | 2 +- .github/workflows/mobile-android_build.yml | 2 +- .github/workflows/mobile-android_tests.yml | 2 +- .github/workflows/mobile-asan.yml | 2 +- .github/workflows/mobile-cc_tests.yml | 2 +- .github/workflows/mobile-core.yml | 2 +- .github/workflows/mobile-coverage.yml | 2 +- .github/workflows/mobile-docs.yml | 2 +- .github/workflows/mobile-format.yml | 2 +- .github/workflows/mobile-perf.yml | 6 +++--- .github/workflows/mobile-tsan.yml | 2 +- .github/workflows/mobile_release.yml | 2 +- bazel/repository_locations.bzl | 6 +++--- ci/run_envoy_docker.sh | 2 -- examples/shared/build/Dockerfile | 2 +- mobile/third_party/rbe_configs/config/BUILD | 8 ++++---- 17 files changed, 23 insertions(+), 25 deletions(-) diff --git a/.bazelrc b/.bazelrc index 4b8b6c96f71c..fa48c228899a 100644 --- a/.bazelrc +++ b/.bazelrc @@ -304,7 +304,7 @@ build:remote-clang-cl --config=rbe-toolchain-clang-cl # Docker sandbox # NOTE: Update this from https://github.com/envoyproxy/envoy-build-tools/blob/main/toolchains/rbe_toolchains_config.bzl#L8 -build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf +build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 build:docker-sandbox --spawn_strategy=docker build:docker-sandbox --strategy=Javac=docker build:docker-sandbox --strategy=Closure=docker diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e323afcb8855..7dd1f7df667d 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM gcr.io/envoy-ci/envoy-build:818d28832abf2a7c0cb2bff00435be231729a0bf +FROM gcr.io/envoy-ci/envoy-build:41c5a05d708972d703661b702a63ef5060125c33 ARG USERNAME=vscode ARG USER_UID=501 diff --git a/.github/workflows/mobile-android_build.yml b/.github/workflows/mobile-android_build.yml index 200a58d5b4b5..4e1f8ec328e0 100644 --- a/.github/workflows/mobile-android_build.yml +++ b/.github/workflows/mobile-android_build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:mobile-818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile-android_tests.yml b/.github/workflows/mobile-android_tests.yml index d6d53894ba14..f4b44217c0e7 100644 --- a/.github/workflows/mobile-android_tests.yml +++ b/.github/workflows/mobile-android_tests.yml @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:mobile-818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile-asan.yml b/.github/workflows/mobile-asan.yml index 72c2ec95ade1..2681176bc068 100644 --- a/.github/workflows/mobile-asan.yml +++ b/.github/workflows/mobile-asan.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 180 container: - image: envoyproxy/envoy-build-ubuntu:mobile-818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile-cc_tests.yml b/.github/workflows/mobile-cc_tests.yml index f1da9a974d9c..28f6c633ecd8 100644 --- a/.github/workflows/mobile-cc_tests.yml +++ b/.github/workflows/mobile-cc_tests.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 steps: - uses: actions/checkout@v3 - name: Add safe directory diff --git a/.github/workflows/mobile-core.yml b/.github/workflows/mobile-core.yml index edf0a078d8ff..26cd00b8089d 100644 --- a/.github/workflows/mobile-core.yml +++ b/.github/workflows/mobile-core.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 steps: - uses: actions/checkout@v3 - name: Ensure no listener leaks diff --git a/.github/workflows/mobile-coverage.yml b/.github/workflows/mobile-coverage.yml index c2f106a70a3e..e6068b9c2510 100644 --- a/.github/workflows/mobile-coverage.yml +++ b/.github/workflows/mobile-coverage.yml @@ -20,7 +20,7 @@ jobs: run: shell: bash container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/mobile-docs.yml b/.github/workflows/mobile-docs.yml index 292c96c1dd6f..403529803e14 100644 --- a/.github/workflows/mobile-docs.yml +++ b/.github/workflows/mobile-docs.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 20 container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 steps: - uses: actions/checkout@v3 - name: Add safe directory diff --git a/.github/workflows/mobile-format.yml b/.github/workflows/mobile-format.yml index a42b71b5a9ae..97457d9f2015 100644 --- a/.github/workflows/mobile-format.yml +++ b/.github/workflows/mobile-format.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 45 container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 env: CLANG_FORMAT: /opt/llvm/bin/clang-format BUILDIFIER_BIN: /usr/local/bin/buildifier diff --git a/.github/workflows/mobile-perf.yml b/.github/workflows/mobile-perf.yml index 18bb4cacdb85..26084818d469 100644 --- a/.github/workflows/mobile-perf.yml +++ b/.github/workflows/mobile-perf.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ @@ -74,7 +74,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 30 container: - image: envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 steps: - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 diff --git a/.github/workflows/mobile-tsan.yml b/.github/workflows/mobile-tsan.yml index 02ea14dfeb7d..8a5898f2b813 100644 --- a/.github/workflows/mobile-tsan.yml +++ b/.github/workflows/mobile-tsan.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:mobile-818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile_release.yml b/.github/workflows/mobile_release.yml index 4fe5f89f5fa3..8beed1ab6268 100644 --- a/.github/workflows/mobile_release.yml +++ b/.github/workflows/mobile_release.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:mobile-818d28832abf2a7c0cb2bff00435be231729a0bf + image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 95e2e28b6b04..1f7c2b60dc1d 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -91,11 +91,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "envoy-build-tools", project_desc = "Common build tools shared by the Envoy/UDPA ecosystem", project_url = "https://github.com/envoyproxy/envoy-build-tools", - version = "2c557f5c899527b3331c316b2d5ca137fcb046b9", - sha256 = "f7e256ee9ee4d02536fb2124c6b79694633e187fe9b33017273af92e88bbdd6c", + version = "49a27300e7b480955d3a6000eea159ff52998b52", + sha256 = "67fbba8f4329e16f693f9fabaa6e430eddb3f27b80186df884d5b801208be8d9", strip_prefix = "envoy-build-tools-{version}", urls = ["https://github.com/envoyproxy/envoy-build-tools/archive/{version}.tar.gz"], - release_date = "2023-05-06", + release_date = "2023-05-16", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/envoyproxy/envoy-build-tools/blob/{version}/LICENSE", diff --git a/ci/run_envoy_docker.sh b/ci/run_envoy_docker.sh index 2dcda09a6deb..373acfa84773 100755 --- a/ci/run_envoy_docker.sh +++ b/ci/run_envoy_docker.sh @@ -60,8 +60,6 @@ else && usermod -a -G pcap envoybuild \ && chown envoybuild:envoygroup /build \ && chown envoybuild /proc/self/fd/2 \ - && rm -rf /usr/bin/cmake \ - && cmake &> /dev/null || echo 'No cmake here!' \ && sudo -EHs -u envoybuild bash -c 'cd /source && $*'") fi diff --git a/examples/shared/build/Dockerfile b/examples/shared/build/Dockerfile index 9e8e5992fbca..8a4355983a6e 100644 --- a/examples/shared/build/Dockerfile +++ b/examples/shared/build/Dockerfile @@ -1,4 +1,4 @@ -FROM envoyproxy/envoy-build-ubuntu:818d28832abf2a7c0cb2bff00435be231729a0bf +FROM envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 ENV DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ diff --git a/mobile/third_party/rbe_configs/config/BUILD b/mobile/third_party/rbe_configs/config/BUILD index b9281332ad58..298016e321ed 100644 --- a/mobile/third_party/rbe_configs/config/BUILD +++ b/mobile/third_party/rbe_configs/config/BUILD @@ -43,8 +43,8 @@ platform( ], exec_properties = { # Please update both the commented tag and the sha256 - # mobile-818d28832abf2a7c0cb2bff00435be231729a0bf - "container-image": "docker://envoyproxy/envoy-build-ubuntu@sha256:20034a0e6afa28e33125760b2dbb069ba9bf0ba717727fbb2d200a4b633297fe", + # mobile-41c5a05d708972d703661b702a63ef5060125c33 + "container-image": "docker://envoyproxy/envoy-build-ubuntu@sha256:ca26ff05bd3f3a09468242faaf38ae48315e57f0a87c102352162f95ac620e6f", "OSFamily": "Linux", "Pool": "linux", }, @@ -60,8 +60,8 @@ platform( ], exec_properties = { # Please update both the commented tag and the sha256 - # mobile-818d28832abf2a7c0cb2bff00435be231729a0bf - "container-image": "docker://envoyproxy/envoy-build-ubuntu@sha256:20034a0e6afa28e33125760b2dbb069ba9bf0ba717727fbb2d200a4b633297fe", + # mobile-41c5a05d708972d703661b702a63ef5060125c33 + "container-image": "docker://envoyproxy/envoy-build-ubuntu@sha256:ca26ff05bd3f3a09468242faaf38ae48315e57f0a87c102352162f95ac620e6f", "OSFamily": "Linux", "Pool": "linux", # Necessary to workaround https://github.com/google/sanitizers/issues/916, otherwise, dangling threads in the From 76f80cab7ae1f1fd21356cc0bbf57120e7a5dca7 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 19 May 2023 10:05:42 +0100 Subject: [PATCH 020/228] Revert "ci: Workaround dep checker (cves) issue again" (#27505) and fix release date This reverts commit 7e50eecb80669d04c74b4125bfee00fc96c7fb85. Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 2 +- ci/do_ci.sh | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 1f7c2b60dc1d..cb8ff5395b5c 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1061,7 +1061,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( urls = ["https://github.com/google/quiche/archive/{version}.tar.gz"], strip_prefix = "quiche-{version}", use_category = ["controlplane", "dataplane_core"], - release_date = "2023-05-17", + release_date = "2023-05-18", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/google/quiche/blob/{version}/LICENSE", diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 427dfc3a1cf7..662dc101406e 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -438,8 +438,7 @@ case $CI_TARGET in bazel run "${BAZEL_BUILD_OPTIONS[@]}" //tools/dependency:check \ --action_env=TODAY_DATE \ -- -v warn \ - -c cves release_dates releases || echo "WARNING: Dependency check failed" - + -c cves release_dates releases # Run dependabot tests echo "Check dependabot ..." bazel run "${BAZEL_BUILD_OPTIONS[@]}" \ From bf8483c6e02ad4388018027dda1baefdd81cd3c9 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 19 May 2023 11:21:03 +0100 Subject: [PATCH 021/228] ci: Improve workflow staging/publishing (#27493) Signed-off-by: Ryan Northey --- .azure-pipelines/env.yml | 40 ++++++++++++++++++----- .azure-pipelines/stage/publish.yml | 52 +++++++++++++++++++++++------- .azure-pipelines/stages.yml | 10 ++++-- ci/do_ci.sh | 5 +++ ci/run_envoy_docker.sh | 1 + docs/publish.sh | 36 ++------------------- 6 files changed, 88 insertions(+), 56 deletions(-) diff --git a/.azure-pipelines/env.yml b/.azure-pipelines/env.yml index aa9d16de691a..b90813001600 100644 --- a/.azure-pipelines/env.yml +++ b/.azure-pipelines/env.yml @@ -181,15 +181,36 @@ jobs: set -e PUBLISH_GITHUB_RELEASE=false - PUBLISH_NETLIFY=false - if [[ -n "$POSTSUBMIT" && "$NOSYNC" != true ]]; then - PUBLISH_NETLIFY=true - fi - if [[ -n "$POSTSUBMIT" && "$NOSYNC" != true && "$ISSTABLEBRANCH" == True && "$(state.isdev)" == false ]]; then - PUBLISH_GITHUB_RELEASE=true + PUBLISH_DOCKERHUB=false + PUBLISH_DOCS=false + PUBLISH_DOCS_LATEST=false + PUBLISH_DOCS_RELEASE=false + + if [[ "$ISSTABLEBRANCH" == True && -n "$POSTSUBMIT" && "$NOSYNC" != true ]]; then + # Build docs for publishing either latest or a release build + PUBLISH_DOCS=true + if [[ "$ISMAIN" == True ]]; then + # Update the Dockerhub README + PUBLISH_DOCKERHUB=true + if [[ "$(state.isDev)" == true ]]; then + # Postsubmit on `main` trigger rebuild of latest docs + PUBLISH_DOCS_LATEST=true + fi + elif [[ "$(state.isDev)" == false ]]; then + # A stable release, publish docs to the release and create a Github release + PUBLISH_GITHUB_RELEASE=true + PUBLISH_DOCS_RELEASE=true + else + # Postsubmit for non-main/release, skip publishing docs in this case + PUBLISH_DOCS=false + fi fi + echo "##vso[task.setvariable variable=githubRelease;isoutput=true]${PUBLISH_GITHUB_RELEASE}" - echo "##vso[task.setvariable variable=netlify;isoutput=true]${PUBLISH_NETLIFY}" + echo "##vso[task.setvariable variable=dockerhub;isoutput=true]${PUBLISH_DOCKERHUB}" + echo "##vso[task.setvariable variable=docs;isoutput=true]${PUBLISH_DOCS}" + echo "##vso[task.setvariable variable=docsLatest;isoutput=true]${PUBLISH_DOCS_LATEST}" + echo "##vso[task.setvariable variable=docsRelease;isoutput=true]${PUBLISH_DOCS_RELEASE}" displayName: "Decide what to publish" workingDirectory: $(Build.SourcesDirectory) @@ -210,7 +231,10 @@ jobs: echo "env.outputs['run.checks']: $(run.checks)" echo echo "env.outputs['publish.githubRelease']: $(publish.githubRelease)" - echo "env.outputs['publish.netlify']: $(publish.netlify)" + echo "env.outputs['publish.dockerhub]: $(publish.dockerhub)" + echo "env.outputs['publish.docs]: $(publish.docs)" + echo "env.outputs['publish.docsLatest]: $(publish.docsLatest)" + echo "env.outputs['publish.docsRelease]: $(publish.docsRelease)" displayName: "Print build environment" diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml index 3e97ef8bdbc7..444e5db454d0 100644 --- a/.azure-pipelines/stage/publish.yml +++ b/.azure-pipelines/stage/publish.yml @@ -60,14 +60,27 @@ parameters: displayName: "Run Packaging" type: string default: true -- name: publishNetlify - displayName: "Publish Netlify" + +- name: publishDockerhub + displayName: "Publish Dockerhub" type: string - default: true + default: false +- name: publishDocs + displayName: "Publish Docs" + type: string + default: false +- name: publishDocsLatest + displayName: "Publish latest docs" + type: string + default: false +- name: publishDocsRelease + displayName: "Publish release docs" + type: string + default: false - name: publishGithubRelease displayName: "Publish Github release" type: string - default: true + default: false jobs: @@ -233,11 +246,11 @@ jobs: echo "building publishable assets complete" - job: docs - displayName: Publish docs to netlify + displayName: Publish docs dependsOn: ["success"] condition: | and(not(canceled()), - eq(${{ parameters.publishNetlify }}, 'true')) + eq(${{ parameters.publishDocs }}, 'true')) pool: vmImage: "ubuntu-20.04" steps: @@ -261,6 +274,9 @@ jobs: - script: | ci/run_envoy_docker.sh 'ci/do_ci.sh dockerhub-publish' + condition: | + and(not(canceled()), + eq(${{ parameters.publishDockerhub }}, 'true')) displayName: "Publish Dockerhub description and README" env: ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) @@ -272,7 +288,6 @@ jobs: GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} DOCKERHUB_USERNAME: ${{ parameters.authDockerUser }} DOCKERHUB_PASSWORD: ${{ parameters.authDockerPassword }} - condition: and(eq(variables['isMain'], 'true'), eq(variables['PostSubmit'], true)) - script: | ci/run_envoy_docker.sh 'ci/do_ci.sh docs-upload' @@ -287,19 +302,32 @@ jobs: GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} condition: eq(variables['isMain'], 'true') + # Trigger Netlify rebuild of latest docs + - script: ci/run_envoy_docker.sh 'ci/do_ci.sh docs-publish-latest' + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocsLatest }}, 'true')) + displayName: "Publish latest docs" + workingDirectory: $(Build.SourcesDirectory) + env: + NETLIFY_TRIGGER_URL: ${{ parameters.authNetlifyURL }} + + # Publish docs to the website - task: InstallSSHKey@0 + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocsRelease }}, 'true')) inputs: hostName: $(authGithubSSHKeyPublic) sshPublicKey: "${{ parameters.authSSHDocsKeyPublic }}" sshPassphrase: "${{ parameters.authSSHKeyPassphrase }}" sshKeySecureFile: "${{ parameters.authSSHDocsKey }}" - - script: docs/publish.sh - displayName: "Publish to GitHub" + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocsRelease }}, 'true')) + displayName: "Publish release docs" workingDirectory: $(Build.SourcesDirectory) - env: - AZP_BRANCH: $(Build.SourceBranch) - NETLIFY_TRIGGER_URL: ${{ parameters.authNetlifyURL }} - job: github displayName: Publish release tag diff --git a/.azure-pipelines/stages.yml b/.azure-pipelines/stages.yml index 05f9d28fa912..6a36bb8da161 100644 --- a/.azure-pipelines/stages.yml +++ b/.azure-pipelines/stages.yml @@ -137,7 +137,10 @@ stages: RUN_DOCKER: $[stageDependencies.env.repo.outputs['run.docker']] RUN_PACKAGING: $[stageDependencies.env.repo.outputs['run.packaging']] PUBLISH_GITHUB_RELEASE: $[stageDependencies.env.repo.outputs['publish.githubRelease']] - PUBLISH_NETLIFY: $[stageDependencies.env.repo.outputs['publish.netlify']] + PUBLISH_DOCKERHUB: $[stageDependencies.env.repo.outputs['publish.dockerhub']] + PUBLISH_DOCS: $[stageDependencies.env.repo.outputs['publish.docs']] + PUBLISH_DOCS_LATEST: $[stageDependencies.env.repo.outputs['publish.docsLatest']] + PUBLISH_DOCS_RELEASE: $[stageDependencies.env.repo.outputs['publish.docsRelease']] jobs: - template: stage/publish.yml parameters: @@ -157,7 +160,10 @@ stages: timeoutDockerPublish: ${{ parameters.timeoutDockerPublish }} runDocker: variables['RUN_DOCKER'] runPackaging: variables['RUN_PACKAGING'] - publishNetlify: variables['PUBLISH_NETLIFY'] + publishDocs: variables['PUBLISH_DOCS'] + publishDocsLatest: variables['PUBLISH_DOCS_LATEST'] + publishDocsRelease: variables['PUBLISH_DOCS_RELEASE'] + publishDockerhub: variables['PUBLISH_DOCKERHUB'] publishGithubRelease: variables['PUBLISH_GITHUB_RELEASE'] - stage: verify diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 662dc101406e..f35425f4de53 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -508,6 +508,11 @@ case $CI_TARGET in "${ENVOY_SRCDIR}/ci/upload_gcs_artifact.sh" /source/generated/docs docs ;; + docs-publish-latest) + BUILD_SHA=$(git rev-parse HEAD) + curl -X POST -d "$BUILD_SHA" "$NETLIFY_TRIGGER_URL" + ;; + docker-upload) setup_clang_toolchain "${ENVOY_SRCDIR}/ci/upload_gcs_artifact.sh" "${BUILD_DIR}/build_images" docker diff --git a/ci/run_envoy_docker.sh b/ci/run_envoy_docker.sh index 373acfa84773..30cbe0094613 100755 --- a/ci/run_envoy_docker.sh +++ b/ci/run_envoy_docker.sh @@ -133,6 +133,7 @@ docker run --rm \ -e SYSTEM_PULLREQUEST_PULLREQUESTNUMBER \ -e GCS_ARTIFACT_BUCKET \ -e GITHUB_TOKEN \ + -e NETLIFY_TRIGGER_URL \ -e BUILD_SOURCEBRANCHNAME \ -e BAZELISK_BASE_URL \ -e ENVOY_BUILD_ARCH \ diff --git a/docs/publish.sh b/docs/publish.sh index 2a27e1c6266b..dee9cde4303e 100755 --- a/docs/publish.sh +++ b/docs/publish.sh @@ -1,13 +1,6 @@ #!/bin/bash -# This is run on every commit that Azure Pipelines picks up. It assumes that docs have already been built -# via docs/build.sh. The push behavior differs depending on the nature of the commit and non/dev `VERSION.txt`: -# * Main commit (dev): -# pushes docs to https://www.envoyproxy.io/docs/envoy/latest/. -# * Main or release branch commit (non-dev): -# pushes docs to versioned location, e.g. -# https://www.envoyproxy.io/docs/envoy/v1.6.0/. -# * Otherwise: noop. +# This pushes a prebuilt docs version to the website for published releases. set -e @@ -16,30 +9,7 @@ CHECKOUT_DIR=envoy-docs BUILD_SHA=$(git rev-parse HEAD) VERSION="$(cat VERSION.txt)" -MAIN_BRANCH="refs/heads/main" -RELEASE_BRANCH_REGEX="^refs/heads/release/v.*" -DEV_VERSION_REGEX="-dev$" - -if [[ "$VERSION" =~ $DEV_VERSION_REGEX ]]; then - if [[ "$AZP_BRANCH" == "${MAIN_BRANCH}" ]]; then - if [[ -n "$NETLIFY_TRIGGER_URL" ]]; then - echo "Triggering netlify docs build for (${BUILD_SHA})" - curl -X POST -d "$BUILD_SHA" "$NETLIFY_TRIGGER_URL" - fi - else - echo "Ignoring docs push" - fi - exit 0 -else - PUBLISH_DIR="${CHECKOUT_DIR}/docs/envoy/v${VERSION}" -fi - -if [[ "${AZP_BRANCH}" != "${MAIN_BRANCH}" ]] && ! [[ "${AZP_BRANCH}" =~ ${RELEASE_BRANCH_REGEX} ]]; then - # Most likely a tag, do nothing. - echo 'Ignoring non-release branch for docs push.' - exit 0 -fi - +PUBLISH_DIR="${CHECKOUT_DIR}/docs/envoy/v${VERSION}" DOCS_MAIN_BRANCH="main" echo 'cloning' @@ -59,8 +29,6 @@ cd "${CHECKOUT_DIR}" git config user.name "envoy-docs(Azure Pipelines)" git config user.email envoy-docs@users.noreply.github.com -set -x - git add . git commit -m "docs envoy@$BUILD_SHA" git push origin "${DOCS_MAIN_BRANCH}" From 34c49003a4644c0d183c59d2cdd4b145bbc88194 Mon Sep 17 00:00:00 2001 From: code Date: Fri, 19 May 2023 21:26:24 +0800 Subject: [PATCH 022/228] generic proxy: typed metadata support for the generic route (#27503) Signed-off-by: wbpcode --- .../filters/network/source/interface/BUILD | 1 + .../filters/network/source/interface/route.h | 16 ++++-- .../filters/network/source/route.cc | 2 +- .../filters/network/source/route.h | 3 ++ .../filters/network/test/mocks/route.h | 1 + .../filters/network/test/route_test.cc | 49 +++++++++++++++++++ 6 files changed, 67 insertions(+), 5 deletions(-) diff --git a/contrib/generic_proxy/filters/network/source/interface/BUILD b/contrib/generic_proxy/filters/network/source/interface/BUILD index a7144b4fe329..daaa17adde56 100644 --- a/contrib/generic_proxy/filters/network/source/interface/BUILD +++ b/contrib/generic_proxy/filters/network/source/interface/BUILD @@ -68,6 +68,7 @@ envoy_cc_library( "//envoy/event:dispatcher_interface", "//envoy/network:connection_interface", "//envoy/rds:rds_config_interface", + "//envoy/router:router_interface", "//envoy/stream_info:stream_info_interface", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], diff --git a/contrib/generic_proxy/filters/network/source/interface/route.h b/contrib/generic_proxy/filters/network/source/interface/route.h index a417a7a39068..7da77f19f010 100644 --- a/contrib/generic_proxy/filters/network/source/interface/route.h +++ b/contrib/generic_proxy/filters/network/source/interface/route.h @@ -5,6 +5,7 @@ #include "envoy/config/core/v3/base.pb.h" #include "envoy/config/typed_metadata.h" #include "envoy/rds/config.h" +#include "envoy/router/router.h" #include "contrib/generic_proxy/filters/network/source/interface/stream.h" @@ -20,9 +21,10 @@ class RouteSpecificFilterConfig { using RouteSpecificFilterConfigConstSharedPtr = std::shared_ptr; /** - * Interface of typed metadata factory. + * Interface of typed metadata factory. Reuse the same interface as the HTTP's router filter because + * part of these abstractions are protocol independent. */ -class RouteTypedMetadataFactory : public Envoy::Config::TypedMetadataFactory {}; +using RouteTypedMetadataFactory = Envoy::Router::HttpRouteTypedMetadataFactory; class RouteEntry { public: @@ -47,10 +49,16 @@ class RouteEntry { } /** - * @return const envoy::config::core::v3::Metadata& return the metadata provided in the config for - * this route. + * @return const envoy::config::core::v3::Metadata& return the metadata provided in the config + * for this route. */ virtual const envoy::config::core::v3::Metadata& metadata() const PURE; + + /** + * @return const Envoy::Config::TypedMetadata& return the typed metadata provided in the config + * for this route. + */ + virtual const Envoy::Config::TypedMetadata& typedMetadata() const PURE; }; using RouteEntryConstSharedPtr = std::shared_ptr; diff --git a/contrib/generic_proxy/filters/network/source/route.cc b/contrib/generic_proxy/filters/network/source/route.cc index bcbedb2d3136..f58998f18925 100644 --- a/contrib/generic_proxy/filters/network/source/route.cc +++ b/contrib/generic_proxy/filters/network/source/route.cc @@ -20,7 +20,7 @@ namespace GenericProxy { RouteEntryImpl::RouteEntryImpl(const ProtoRouteAction& route_action, Envoy::Server::Configuration::ServerFactoryContext& context) : name_(route_action.name()), cluster_name_(route_action.cluster()), - metadata_(route_action.metadata()) { + metadata_(route_action.metadata()), typed_metadata_(metadata_) { for (const auto& proto_filter_config : route_action.per_filter_config()) { auto& factory = Config::Utility::getAndCheckFactoryByName( diff --git a/contrib/generic_proxy/filters/network/source/route.h b/contrib/generic_proxy/filters/network/source/route.h index bea6961e4e22..010a6ec0be17 100644 --- a/contrib/generic_proxy/filters/network/source/route.h +++ b/contrib/generic_proxy/filters/network/source/route.h @@ -44,6 +44,8 @@ class RouteEntryImpl : public RouteEntry { } const envoy::config::core::v3::Metadata& metadata() const override { return metadata_; } + const Envoy::Config::TypedMetadata& typedMetadata() const override { return typed_metadata_; }; + private: static const uint64_t DEFAULT_ROUTE_TIMEOUT_MS = 15000; @@ -51,6 +53,7 @@ class RouteEntryImpl : public RouteEntry { std::string cluster_name_; const envoy::config::core::v3::Metadata metadata_; + const Envoy::Config::TypedMetadataImpl typed_metadata_; absl::flat_hash_map per_filter_configs_; }; diff --git a/contrib/generic_proxy/filters/network/test/mocks/route.h b/contrib/generic_proxy/filters/network/test/mocks/route.h index 428f4285a672..3b5792362e10 100644 --- a/contrib/generic_proxy/filters/network/test/mocks/route.h +++ b/contrib/generic_proxy/filters/network/test/mocks/route.h @@ -17,6 +17,7 @@ class MockRouteEntry : public RouteEntry { MOCK_METHOD(const std::string&, clusterName, (), (const)); MOCK_METHOD(const RouteSpecificFilterConfig*, perFilterConfig, (absl::string_view), (const)); MOCK_METHOD(const envoy::config::core::v3::Metadata&, metadata, (), (const)); + MOCK_METHOD(const Envoy::Config::TypedMetadata&, typedMetadata, (), (const)); MOCK_METHOD(absl::string_view, name, (), (const)); std::string cluster_name_{"fake_cluster_name"}; diff --git a/contrib/generic_proxy/filters/network/test/route_test.cc b/contrib/generic_proxy/filters/network/test/route_test.cc index 7e948fef3191..b1377849c228 100644 --- a/contrib/generic_proxy/filters/network/test/route_test.cc +++ b/contrib/generic_proxy/filters/network/test/route_test.cc @@ -72,6 +72,55 @@ TEST_F(RouteEntryImplTest, RouteMetadata) { Config::Metadata::metadataValue(&route_->metadata(), "mock_filter", "key_0").string_value()); }; +struct Foo : public Envoy::Config::TypedMetadata::Object {}; +struct Baz : public Envoy::Config::TypedMetadata::Object { + Baz(std::string n) : name(n) {} + std::string name; +}; +class BazFactory : public RouteTypedMetadataFactory { +public: + std::string name() const override { return "baz"; } + // Returns nullptr (conversion failure) if d is empty. + std::unique_ptr + parse(const ProtobufWkt::Struct& d) const override { + if (d.fields().find("name") != d.fields().end()) { + return std::make_unique(d.fields().at("name").string_value()); + } + throw EnvoyException("Cannot create a Baz when metadata is empty."); + } + + std::unique_ptr + parse(const ProtobufWkt::Any&) const override { + return nullptr; + } +}; + +/** + * Test the method that get filter metadata from the route entry. + */ +TEST_F(RouteEntryImplTest, RouteTypedMetadata) { + BazFactory baz_factory; + Registry::InjectFactory registered_factory(baz_factory); + + const std::string yaml_config = R"EOF( + cluster: cluster_0 + metadata: + filter_metadata: + foo: + key_0: value_0 + baz: + name: baz_name + )EOF"; + initialize(yaml_config); + + // Only get valid value when type and name are matched. + EXPECT_EQ("baz_name", route_->typedMetadata().get(baz_factory.name())->name); + + EXPECT_EQ(nullptr, route_->typedMetadata().get(baz_factory.name())); + EXPECT_EQ(nullptr, route_->typedMetadata().get("foo")); + EXPECT_EQ(nullptr, route_->typedMetadata().get("foo")); +}; + /** * Test the method that get route level per filter config from the route entry. This test also * verifies that the proto per filter config can be loaded correctly. From 25a76279b4a51cdf7e21b753da2f57968ea7a75d Mon Sep 17 00:00:00 2001 From: Ryan Hamilton Date: Fri, 19 May 2023 06:28:32 -0700 Subject: [PATCH 023/228] mobile: remove the mobile-specific BoringSSL repo (#27491) mobile: remove the mobile-specific boringssl repo Signed-off-by: Ryan Hamilton --- mobile/bazel/envoy_mobile_repositories.bzl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/mobile/bazel/envoy_mobile_repositories.bzl b/mobile/bazel/envoy_mobile_repositories.bzl index 5583cefcb759..3146aa1a7a52 100644 --- a/mobile/bazel/envoy_mobile_repositories.bzl +++ b/mobile/bazel/envoy_mobile_repositories.bzl @@ -38,15 +38,6 @@ def upstream_envoy_overrides(): build_file_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])""", ) - # This should be kept in sync with Envoy itself, we just need to apply this patch - # Remove this once https://boringssl-review.googlesource.com/c/boringssl/+/37804 is in master-with-bazel - http_archive( - name = "boringssl", - sha256 = "579cb415458e9f3642da0a39a72f79fdfe6dc9c1713b3a823f1e276681b9703e", - strip_prefix = "boringssl-648cbaf033401b7fe7acdce02f275b06a88aab5c", - urls = ["https://github.com/google/boringssl/archive/648cbaf033401b7fe7acdce02f275b06a88aab5c.tar.gz"], - ) - def swift_repos(): http_archive( name = "build_bazel_rules_apple", From 1fd0b996f820ef5a85b0889c7937e82696c95f83 Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Fri, 19 May 2023 09:35:52 -0400 Subject: [PATCH 024/228] ext_proc filter crash when sending trailers when request has no body (#27430) * ext_proc filter crash when sending trailers without sending body. Signed-off-by: Yanjun Xiang --- .../filters/http/ext_proc/ext_proc.cc | 21 +++++++++ .../filters/http/ext_proc/ext_proc.h | 5 +-- .../ext_proc/ext_proc_integration_test.cc | 45 +++++++++++++++++++ ..._proc_unit_test_fuzz-5547889199546368.test | 34 ++++++++++++++ 4 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/clusterfuzz-testcase-minimized-ext_proc_unit_test_fuzz-5547889199546368.test diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 34c4ce953a9d..ad95d50c368d 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -435,6 +435,16 @@ FilterTrailersStatus Filter::onTrailers(ProcessorState& state, Http::HeaderMap& } if (!body_delivered && state.bodyMode() == ProcessingMode::BUFFERED) { + // If no gRPC stream yet, opens it before sending data. + switch (openStream()) { + case StreamOpenState::Error: + return FilterTrailersStatus::StopIteration; + case StreamOpenState::IgnoreError: + return FilterTrailersStatus::Continue; + case StreamOpenState::Ok: + // Fall through + break; + } // We would like to process the body in a buffered way, but until now the complete // body has not arrived. With the arrival of trailers, we now know that the body // has arrived. @@ -516,6 +526,17 @@ void Filter::sendBodyChunk(ProcessorState& state, const Buffer::Instance& data, stats_.stream_msgs_sent_.inc(); } +void Filter::sendBufferedData(ProcessorState& state, ProcessorState::CallbackState new_state, + bool end_stream) { + if (state.hasBufferedData()) { + sendBodyChunk(state, *state.bufferedData(), new_state, end_stream); + } else { + // If there is no buffered data, sends an empty body. + Buffer::OwnedImpl data(""); + sendBodyChunk(state, data, new_state, end_stream); + } +} + void Filter::sendTrailers(ProcessorState& state, const Http::HeaderMap& trailers) { ProcessingRequest req; auto* trailers_req = state.mutableTrailers(req); diff --git a/source/extensions/filters/http/ext_proc/ext_proc.h b/source/extensions/filters/http/ext_proc/ext_proc.h index 2824cb4d1944..1ff10c8d252e 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.h +++ b/source/extensions/filters/http/ext_proc/ext_proc.h @@ -194,9 +194,8 @@ class Filter : public Logger::Loggable, void onNewTimeout(const ProtobufWkt::Duration& override_message_timeout); void sendBufferedData(ProcessorState& state, ProcessorState::CallbackState new_state, - bool end_stream) { - sendBodyChunk(state, *state.bufferedData(), new_state, end_stream); - } + bool end_stream); + void sendBodyChunk(ProcessorState& state, const Buffer::Instance& data, ProcessorState::CallbackState new_state, bool end_stream); diff --git a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc index 1d4565a56470..3c488aaa0e27 100644 --- a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc +++ b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc @@ -210,6 +210,27 @@ class ExtProcIntegrationTest : public HttpIntegrationTest, } } + void processRequestTrailersMessage( + FakeUpstream& grpc_upstream, bool first_message, + absl::optional> cb) { + ProcessingRequest request; + if (first_message) { + ASSERT_TRUE(grpc_upstream.waitForHttpConnection(*dispatcher_, processor_connection_)); + ASSERT_TRUE(processor_connection_->waitForNewStream(*dispatcher_, processor_stream_)); + } + ASSERT_TRUE(processor_stream_->waitForGrpcMessage(*dispatcher_, request)); + ASSERT_TRUE(request.has_request_trailers()); + if (first_message) { + processor_stream_->startGrpcStream(); + } + ProcessingResponse response; + auto* body = response.mutable_request_trailers(); + const bool sendReply = !cb || (*cb)(request.request_trailers(), *body); + if (sendReply) { + processor_stream_->sendGrpcMessage(response); + } + } + void processResponseHeadersMessage( FakeUpstream& grpc_upstream, bool first_message, absl::optional> cb) { @@ -1969,4 +1990,28 @@ TEST_P(ExtProcIntegrationTest, RequestMessageNewTimeoutOutOfBounds) { newTimeoutWrongConfigTest(override_message_timeout); } +// Set the ext_proc filter in SKIP header, BUFFERED body mode. +// Send a request with headers and trailers. +TEST_P(ExtProcIntegrationTest, SendHeaderAndTrailerInBufferedMode) { + proto_config_.mutable_processing_mode()->set_request_body_mode(ProcessingMode::BUFFERED); + proto_config_.mutable_processing_mode()->set_request_header_mode(ProcessingMode::SKIP); + proto_config_.mutable_processing_mode()->set_request_trailer_mode(ProcessingMode::SEND); + initializeConfig(); + HttpIntegrationTest::initialize(); + + codec_client_ = makeHttpConnection(lookupPort("http")); + Http::TestRequestHeaderMapImpl headers; + HttpTestUtility::addDefaultHeaders(headers); + auto encoder_decoder = codec_client_->startRequest(headers); + request_encoder_ = &encoder_decoder.first; + IntegrationStreamDecoderPtr response = std::move(encoder_decoder.second); + Http::TestRequestTrailerMapImpl request_trailers{{"request", "trailer"}}; + codec_client_->sendTrailers(*request_encoder_, request_trailers); + processRequestBodyMessage(*grpc_upstreams_[0], true, absl::nullopt); + processRequestTrailersMessage(*grpc_upstreams_[0], false, absl::nullopt); + handleUpstreamRequest(); + processResponseHeadersMessage(*grpc_upstreams_[0], false, absl::nullopt); + verifyDownstreamResponse(*response, 200); +} + } // namespace Envoy diff --git a/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/clusterfuzz-testcase-minimized-ext_proc_unit_test_fuzz-5547889199546368.test b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/clusterfuzz-testcase-minimized-ext_proc_unit_test_fuzz-5547889199546368.test new file mode 100644 index 000000000000..06f1a08753f1 --- /dev/null +++ b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/clusterfuzz-testcase-minimized-ext_proc_unit_test_fuzz-5547889199546368.test @@ -0,0 +1,34 @@ +config { + grpc_service { + envoy_grpc { + cluster_name: "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + retry_policy { + } + } + timeout { + } + } + processing_mode { + request_header_mode: SKIP + request_body_mode: BUFFERED + } + request_attributes: "\022." +} +request { + trailers { + headers { + key: "." + } + } +} +response { + response_body { + response { + header_mutation { + } + } + } + mode_override { + request_header_mode: SKIP + } +} From 01fe4aec8ef235d0dffa2a09231d87ceb0a6a38b Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Fri, 19 May 2023 11:09:25 -0400 Subject: [PATCH 025/228] match_delegate: skip filter on_no_match (#27332) Signed-off-by: tyxia --- .../common/http/match_delegate/config_test.cc | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/test/common/http/match_delegate/config_test.cc b/test/common/http/match_delegate/config_test.cc index a108b56b84a6..7cbcd104e3bb 100644 --- a/test/common/http/match_delegate/config_test.cc +++ b/test/common/http/match_delegate/config_test.cc @@ -315,6 +315,63 @@ TEST(DelegatingFilterTest, MatchTreeSkipActionDecodingHeaders) { delegating_filter->decodeComplete(); } +// This function creates the matcher tree only with on_no_match set. +template +Matcher::MatchTreeSharedPtr +createMatchTreeWithOnNoMatch(const std::string& name, const std::string& value) { + auto tree = std::make_shared>( + std::make_unique(name), + Matcher::OnMatch{ + []() { return std::make_unique(); }, nullptr}); + + // No action is set on match. i.e., nullptr action factory cb. + tree->addChild( + value, Matcher::OnMatch{[]() { return nullptr; }, nullptr}); + return tree; +} + +TEST(DelegatingFilterTest, MatchTreeOnNoMatchSkipActionDecodingHeaders) { + // The filter is added, but the `on_no_match` action will be invoked since it is not matched on + // request header. The skip action is provided to `on_no_match` so we skip this filter. + std::shared_ptr decoder_filter( + new Envoy::Http::MockStreamDecoderFilter()); + NiceMock callbacks; + + EXPECT_CALL(*decoder_filter, setDecoderFilterCallbacks(_)); + EXPECT_CALL(*decoder_filter, decodeHeaders(_, _)).Times(0); + EXPECT_CALL(*decoder_filter, decodeData(_, _)).Times(0); + EXPECT_CALL(*decoder_filter, decodeMetadata(_)).Times(0); + EXPECT_CALL(*decoder_filter, decodeTrailers(_)).Times(0); + EXPECT_CALL(*decoder_filter, decodeComplete()).Times(0); + + auto match_tree = + createMatchTreeWithOnNoMatch( + "match-header", "match"); + auto delegating_filter = + std::make_shared(match_tree, decoder_filter, nullptr); + + Envoy::Http::RequestHeaderMapPtr request_headers{ + new Envoy::Http::TestRequestHeaderMapImpl{{":authority", "host"}, + {":path", "/"}, + {":method", "GET"}, + {"match-header", "not_match"}, + {"content-type", "application/grpc"}}}; + Envoy::Http::RequestTrailerMapPtr request_trailers{ + new Envoy::Http::TestRequestTrailerMapImpl{{"test", "test"}}}; + Envoy::Http::MetadataMap metadata_map; + Buffer::OwnedImpl buffer; + + delegating_filter->setDecoderFilterCallbacks(callbacks); + EXPECT_EQ(Envoy::Http::FilterHeadersStatus::Continue, + delegating_filter->decodeHeaders(*request_headers, false)); + EXPECT_EQ(Envoy::Http::FilterDataStatus::Continue, delegating_filter->decodeData(buffer, false)); + EXPECT_EQ(Envoy::Http::FilterMetadataStatus::Continue, + delegating_filter->decodeMetadata(metadata_map)); + EXPECT_EQ(Envoy::Http::FilterTrailersStatus::Continue, + delegating_filter->decodeTrailers(*request_trailers)); + delegating_filter->decodeComplete(); +} + TEST(DelegatingFilterTest, MatchTreeQueryParamsSkipActionDecodingHeaders) { // The filter is added, but since we match on the request header we skip the filter. std::shared_ptr decoder_filter( From 5fba0932745c127db853e3036b678873448fc1ab Mon Sep 17 00:00:00 2001 From: Pradeep Rao <84025829+pradeepcrao@users.noreply.github.com> Date: Fri, 19 May 2023 13:05:01 -0400 Subject: [PATCH 026/228] stats: Skip slowRejects if we have a definitive answer from fastRejects. (#27455) * stats: Skip slowRejects if we have a definitive answer from fastRejects. Signed-off-by: pcrao --- source/common/stats/stats_matcher_impl.cc | 27 +++--- test/common/stats/BUILD | 24 +++++ .../stats/stats_matcher_impl_speed_test.cc | 88 +++++++++++++++++++ test/common/stats/stats_matcher_impl_test.cc | 24 +++++ 4 files changed, 150 insertions(+), 13 deletions(-) create mode 100644 test/common/stats/stats_matcher_impl_speed_test.cc diff --git a/source/common/stats/stats_matcher_impl.cc b/source/common/stats/stats_matcher_impl.cc index a4440f90494c..6e974a0b2c2c 100644 --- a/source/common/stats/stats_matcher_impl.cc +++ b/source/common/stats/stats_matcher_impl.cc @@ -89,21 +89,22 @@ bool StatsMatcherImpl::fastRejectMatch(StatName stat_name) const { } bool StatsMatcherImpl::slowRejects(FastResult fast_result, StatName stat_name) const { - bool match = slowRejectMatch(stat_name); - - if (is_inclusive_ || match || fast_result != FastResult::Matches) { - // is_inclusive_ | match | return - // ---------------+-------+-------- - // T | T | T Default-inclusive and matching an (exclusion) matcher, deny. - // T | F | F Otherwise, allow. - // F | T | F Default-exclusive and matching an (inclusion) matcher, allow. - // F | F | T Otherwise, deny. - // - // This is an XNOR, which can be evaluated by checking for equality. - return match == is_inclusive_; + // Skip slowRejectMatch if we already have a definitive answer from fastRejects. + if (fast_result != FastResult::NoMatch) { + return fast_result == FastResult::Rejects; } - return false; + const bool match = slowRejectMatch(stat_name); + + // is_inclusive_ | match | return + // ---------------+-------+-------- + // T | T | T Default-inclusive and matching an (exclusion) matcher, deny. + // T | F | F Otherwise, allow. + // F | T | F Default-exclusive and matching an (inclusion) matcher, allow. + // F | F | T Otherwise, deny. + // + // This is an XNOR, which can be evaluated by checking for equality. + return match == is_inclusive_; } bool StatsMatcherImpl::slowRejectMatch(StatName stat_name) const { diff --git a/test/common/stats/BUILD b/test/common/stats/BUILD index 0463996725d8..6b8dd9689e62 100644 --- a/test/common/stats/BUILD +++ b/test/common/stats/BUILD @@ -231,6 +231,30 @@ envoy_benchmark_test( benchmark_binary = "symbol_table_benchmark", ) +envoy_cc_benchmark_binary( + name = "stats_matcher_impl_benchmark", + srcs = [ + "stats_matcher_impl_speed_test.cc", + ], + external_deps = [ + "abseil_strings", + "benchmark", + ], + deps = [ + "//source/common/memory:stats_lib", + "//source/common/stats:stats_matcher_lib", + "//test/test_common:logging_lib", + "//test/test_common:utility_lib", + "@envoy_api//envoy/config/metrics/v3:pkg_cc_proto", + "@envoy_api//envoy/type/matcher/v3:pkg_cc_proto", + ], +) + +envoy_benchmark_test( + name = "stats_matcher_impl_benchmark_test", + benchmark_binary = "stats_matcher_impl_benchmark", +) + envoy_cc_test( name = "tag_extractor_impl_test", srcs = ["tag_extractor_impl_test.cc"], diff --git a/test/common/stats/stats_matcher_impl_speed_test.cc b/test/common/stats/stats_matcher_impl_speed_test.cc new file mode 100644 index 000000000000..8c8cd6c247ba --- /dev/null +++ b/test/common/stats/stats_matcher_impl_speed_test.cc @@ -0,0 +1,88 @@ +// Note: this should be run with --compilation_mode=opt, and would benefit from a +// quiescent system with disabled cstate power management. + +#include "envoy/config/metrics/v3/stats.pb.h" +#include "envoy/type/matcher/v3/string.pb.h" + +#include "source/common/stats/stats_matcher_impl.h" + +#include "test/test_common/utility.h" + +#include "benchmark/benchmark.h" + +namespace Envoy { +namespace Stats { + +class StatsMatcherPerf { +public: + StatsMatcherPerf() : pool_(symbol_table_) {} + + void initMatcher() { + stats_matcher_impl_ = std::make_unique(stats_config_, symbol_table_); + } + + envoy::type::matcher::v3::StringMatcher* inclusionList() { + return stats_config_.mutable_stats_matcher()->mutable_inclusion_list()->add_patterns(); + } + envoy::type::matcher::v3::StringMatcher* exclusionList() { + return stats_config_.mutable_stats_matcher()->mutable_exclusion_list()->add_patterns(); + } + + SymbolTableImpl symbol_table_; + StatNamePool pool_; + std::unique_ptr stats_matcher_impl_; + +private: + envoy::config::metrics::v3::StatsConfig stats_config_; +}; + +} // namespace Stats +} // namespace Envoy + +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_Inclusion(benchmark::State& state) { + // Create matcher. + Envoy::Stats::StatsMatcherPerf context; + context.inclusionList()->set_suffix("1"); + context.inclusionList()->set_prefix("2."); + context.initMatcher(); + std::vector stat_names; + stat_names.reserve(10); + for (auto idx = 0; idx < 10; ++idx) { + stat_names.push_back(context.pool_.add(absl::StrCat("2.", idx))); + } + + for (auto _ : state) { // NOLINT + for (auto idx = 0; idx < 1000; ++idx) { + const Envoy::Stats::StatName stat_name = stat_names[idx % 10]; + const Envoy::Stats::StatsMatcher::FastResult fast_result = + context.stats_matcher_impl_->fastRejects(stat_name); + context.stats_matcher_impl_->slowRejects(fast_result, stat_name); + } + } +} +BENCHMARK(BM_Inclusion); + +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_Exclusion(benchmark::State& state) { + // Create matcher. + Envoy::Stats::StatsMatcherPerf context; + context.exclusionList()->set_suffix("1"); + context.exclusionList()->set_prefix("2."); + context.initMatcher(); + std::vector stat_names; + stat_names.reserve(10); + for (auto idx = 0; idx < 10; ++idx) { + stat_names.push_back(context.pool_.add(absl::StrCat("2.", idx))); + } + + for (auto _ : state) { // NOLINT + for (auto idx = 0; idx < 1000; ++idx) { + const Envoy::Stats::StatName stat_name = stat_names[idx % 10]; + const Envoy::Stats::StatsMatcher::FastResult fast_result = + context.stats_matcher_impl_->fastRejects(stat_name); + context.stats_matcher_impl_->slowRejects(fast_result, stat_name); + } + } +} +BENCHMARK(BM_Exclusion); diff --git a/test/common/stats/stats_matcher_impl_test.cc b/test/common/stats/stats_matcher_impl_test.cc index 821a47c69b1d..75009010e2b2 100644 --- a/test/common/stats/stats_matcher_impl_test.cc +++ b/test/common/stats/stats_matcher_impl_test.cc @@ -330,5 +330,29 @@ TEST_F(StatsMatcherTest, CheckMultipleAssortedExclusionMatchersWithPrefix) { EXPECT_FALSE(stats_matcher_impl_->rejectsAll()); } +TEST_F(StatsMatcherTest, SkipSlowRejectsOnFastReject) { + inclusionList()->set_suffix("xyz"); + initMatcher(); + StatName stat_name = pool_.add("wxyz"); + // Verify that we skip the slow check if fast_result is not NoMatch. + EXPECT_TRUE(stats_matcher_impl_->slowRejects(StatsMatcher::FastResult::Rejects, stat_name)); + + // Verify we don't skip the slow check if fast_result is NoMatch. + EXPECT_FALSE( + stats_matcher_impl_->slowRejects(stats_matcher_impl_->fastRejects(stat_name), stat_name)); +} + +TEST_F(StatsMatcherTest, SkipSlowRejectsOnFastMatches) { + exclusionList()->set_suffix("xyz"); + initMatcher(); + StatName stat_name = pool_.add("wxyz"); + // Verify that we skip the slow check if fast_result is not NoMatch. + EXPECT_FALSE(stats_matcher_impl_->slowRejects(StatsMatcher::FastResult::Matches, stat_name)); + + // Verify we don't skip the slow check if fast_result is NoMatch. + EXPECT_TRUE( + stats_matcher_impl_->slowRejects(stats_matcher_impl_->fastRejects(stat_name), stat_name)); +} + } // namespace Stats } // namespace Envoy From c2ae2211196a48b12d2e36d00c6c2889ae2f434a Mon Sep 17 00:00:00 2001 From: Shriram Rajagopalan Date: Fri, 19 May 2023 16:09:21 -0400 Subject: [PATCH 027/228] Add metadata to ext_proc and fault filter (#27003) Aids in decorating access logs for requests that are subjected to ext_proc and fault calls. In ext_proc, the struct is copied into the filter state object that contains per grpc exchange stats. In fault case, it is copied into dynamicMetadata under the namespace matching the filter config name. Risk Level: Low Testing: Unit tests Signed-off-by: Shriram Rajagopalan --- .../filters/http/ext_proc/v3/ext_proc.proto | 14 ++++- .../filters/http/fault/v3/fault.proto | 10 +++- changelogs/current.yaml | 12 ++++ envoy/http/filter.h | 5 ++ source/common/http/async_client_impl.h | 1 + source/common/http/filter_manager.h | 1 + source/extensions/filters/http/ext_proc/BUILD | 1 + .../filters/http/ext_proc/ext_proc.cc | 7 ++- .../filters/http/ext_proc/ext_proc.h | 15 ++++- source/extensions/filters/http/fault/BUILD | 2 + .../filters/http/fault/fault_filter.cc | 9 ++- .../filters/http/fault/fault_filter.h | 5 ++ test/extensions/filters/http/ext_proc/BUILD | 1 + .../filters/http/ext_proc/config_test.cc | 2 + .../filters/http/ext_proc/filter_test.cc | 24 +++++++- .../filters/http/fault/config_test.cc | 2 + .../filters/http/fault/fault_filter_test.cc | 55 ++++++++++++++++--- test/mocks/http/mocks.h | 2 + 18 files changed, 149 insertions(+), 19 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index c84c3790d656..dce9b24cfd74 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -8,6 +8,7 @@ import "envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto"; import "envoy/type/matcher/v3/string.proto"; import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; import "xds/annotations/v3/status.proto"; @@ -95,8 +96,12 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // :ref:`ProcessingRequest ` // messages, and the server must reply with // :ref:`ProcessingResponse `. - -// [#next-free-field: 13] +// +// Stats about each gRPC call are recorded in a :ref:`dynamic filter state +// ` object in a namespace matching the filter +// name. +// +// [#next-free-field: 14] message ExternalProcessor { // Configuration for the gRPC service that the filter will communicate with. // The filter supports both the "Envoy" and "Google" gRPC clients. @@ -186,6 +191,11 @@ message ExternalProcessor { // Allow headers matching the ``forward_rules`` to be forwarded to the external processing server. // If not set, all headers are forwarded to the external processing server. HeaderForwardingRules forward_rules = 12; + + // Additional metadata to be added to the filter state for logging purposes. The metadata + // will be added to StreamInfo's filter state under the namespace corresponding to the + // ext_proc filter name. + google.protobuf.Struct filter_metadata = 13; } // The HeaderForwardingRules structure specifies what headers are diff --git a/api/envoy/extensions/filters/http/fault/v3/fault.proto b/api/envoy/extensions/filters/http/fault/v3/fault.proto index 5d55cfe00198..01f056e7927a 100644 --- a/api/envoy/extensions/filters/http/fault/v3/fault.proto +++ b/api/envoy/extensions/filters/http/fault/v3/fault.proto @@ -6,6 +6,7 @@ import "envoy/config/route/v3/route_components.proto"; import "envoy/extensions/filters/common/fault/v3/fault.proto"; import "envoy/type/v3/percent.proto"; +import "google/protobuf/struct.proto"; import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; @@ -55,7 +56,7 @@ message FaultAbort { type.v3.FractionalPercent percentage = 3; } -// [#next-free-field: 16] +// [#next-free-field: 17] message HTTPFault { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.http.fault.v2.HTTPFault"; @@ -148,4 +149,11 @@ message HTTPFault { // If set to false, dynamic stats storage will be allocated for the downstream cluster name. // Default value is false. bool disable_downstream_cluster_stats = 15; + + // When an abort or delay fault is executed, the metadata struct provided here will be added to the + // request's dynamic metadata under the namespace corresponding to the name of the fault filter. + // This data can be logged as part of Access Logs using the :ref:`command operator + // ` %DYNAMIC_METADATA(NAMESPACE)%, where NAMESPACE is the name of + // the fault filter. + google.protobuf.Struct filter_metadata = 16; } diff --git a/changelogs/current.yaml b/changelogs/current.yaml index a49260da1d22..1ff740abec2e 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -65,6 +65,10 @@ minor_behavior_changes: Changed behavior of the fixed heap monitor to count unused mapped pages as free memory. This change can be reverted temporarily by setting the runtime guard ``envoy.reloadable_features.count_unused_mapped_pages_as_free`` to false. +- area: ext_proc + change: | + Filter metadata containing ext proc stats has been moved from ext-proc-logging-info to a namespace corresponding + to the name of the ext_proc filter. bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* @@ -199,6 +203,14 @@ new_features: - area: admin change: | Adds a new admin stats html bucket-mode ``detailed`` to generate all recorded buckets and summary percentiles. +- area: fault + change: | + added new field ``envoy.extensions.filters.http.fault.v3.HTTPFault.filter_metadata`` to aid in logging. + Metadata will be stored in StreamInfo dynamic metadata under a namespace corresponding to the name of the fault filter. +- area: ext_proc + change: | + added new field ``filter_metadata downstreamCallbacks() PURE; + + /** + * @return absl::string_view the name of the filter as configured in the filter chain.. + */ + virtual absl::string_view filterConfigName() const PURE; }; class DecoderFilterWatermarkCallbacks { diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h index 1bc5536b6212..8a4dc0d67284 100644 --- a/source/common/http/async_client_impl.h +++ b/source/common/http/async_client_impl.h @@ -480,6 +480,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, void resetIdleTimer() override {} void setUpstreamOverrideHost(absl::string_view) override {} absl::optional upstreamOverrideHost() const override { return {}; } + absl::string_view filterConfigName() const override { return ""; } // ScopeTrackedObject void dumpState(std::ostream& os, int indent_level) const override { diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index 5c93ef2f9574..87be59dc76a0 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -104,6 +104,7 @@ struct ActiveStreamFilterBase : public virtual StreamFilterCallbacks, Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override; OptRef downstreamCallbacks() override; OptRef upstreamCallbacks() override; + absl::string_view filterConfigName() const override { return filter_context_.config_name; } // Functions to set or get iteration state. bool canIterate() { return iteration_state_ == IterationState::Continue; } diff --git a/source/extensions/filters/http/ext_proc/BUILD b/source/extensions/filters/http/ext_proc/BUILD index 2970272c0494..2c2397d6d304 100644 --- a/source/extensions/filters/http/ext_proc/BUILD +++ b/source/extensions/filters/http/ext_proc/BUILD @@ -27,6 +27,7 @@ envoy_cc_library( "//envoy/http:header_map_interface", "//envoy/stats:stats_macros", "//source/common/buffer:buffer_lib", + "//source/common/protobuf", "//source/common/runtime:runtime_features_lib", "//source/extensions/filters/common/mutation_rules:mutation_rules_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index ad95d50c368d..b56f3da39cb1 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -103,12 +103,13 @@ void Filter::setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& callb decoding_state_.setDecoderFilterCallbacks(callbacks); const Envoy::StreamInfo::FilterStateSharedPtr& filter_state = callbacks.streamInfo().filterState(); - if (!filter_state->hasData(ExtProcLoggingInfoName)) { - filter_state->setData(ExtProcLoggingInfoName, std::make_shared(), + if (!filter_state->hasData(callbacks.filterConfigName())) { + filter_state->setData(callbacks.filterConfigName(), + std::make_shared(config_->filterMetadata()), Envoy::StreamInfo::FilterState::StateType::Mutable, Envoy::StreamInfo::FilterState::LifeSpan::Request); } - logging_info_ = filter_state->getDataMutable(ExtProcLoggingInfoName); + logging_info_ = filter_state->getDataMutable(callbacks.filterConfigName()); } void Filter::setEncoderFilterCallbacks(Http::StreamEncoderFilterCallbacks& callbacks) { diff --git a/source/extensions/filters/http/ext_proc/ext_proc.h b/source/extensions/filters/http/ext_proc/ext_proc.h index 1ff10c8d252e..fbdd050f41ad 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.h +++ b/source/extensions/filters/http/ext_proc/ext_proc.h @@ -4,6 +4,7 @@ #include #include +#include "envoy/config/core/v3/base.pb.h" #include "envoy/config/core/v3/grpc_service.pb.h" #include "envoy/event/timer.h" #include "envoy/extensions/filters/http/ext_proc/v3/ext_proc.pb.h" @@ -14,6 +15,7 @@ #include "envoy/stats/stats_macros.h" #include "source/common/common/logger.h" +#include "source/common/protobuf/protobuf.h" #include "source/extensions/filters/common/mutation_rules/mutation_rules.h" #include "source/extensions/filters/http/common/pass_through_filter.h" #include "source/extensions/filters/http/ext_proc/client.h" @@ -43,10 +45,11 @@ struct ExtProcFilterStats { ALL_EXT_PROC_FILTER_STATS(GENERATE_COUNTER_STRUCT) }; -inline constexpr absl::string_view ExtProcLoggingInfoName = "ext-proc-logging-info"; - class ExtProcLoggingInfo : public Envoy::StreamInfo::FilterState::Object { public: + explicit ExtProcLoggingInfo(const Envoy::ProtobufWkt::Struct& filter_metadata) + : filter_metadata_(filter_metadata) {} + struct GrpcCall { GrpcCall(const std::chrono::microseconds latency, const Grpc::Status::GrpcStatus status, const ProcessorState::CallbackState callback_state) @@ -62,11 +65,13 @@ class ExtProcLoggingInfo : public Envoy::StreamInfo::FilterState::Object { envoy::config::core::v3::TrafficDirection traffic_direction); const GrpcCalls& grpcCalls(envoy::config::core::v3::TrafficDirection traffic_direction) const; + const Envoy::ProtobufWkt::Struct& filterMetadata() const { return filter_metadata_; } private: GrpcCalls& grpcCalls(envoy::config::core::v3::TrafficDirection traffic_direction); GrpcCalls decoding_processor_grpc_calls_; GrpcCalls encoding_processor_grpc_calls_; + const Envoy::ProtobufWkt::Struct filter_metadata_; }; class FilterConfig { @@ -79,7 +84,8 @@ class FilterConfig { disable_clear_route_cache_(config.disable_clear_route_cache()), message_timeout_(message_timeout), max_message_timeout_ms_(max_message_timeout_ms), stats_(generateStats(stats_prefix, config.stat_prefix(), scope)), - processing_mode_(config.processing_mode()), mutation_checker_(config.mutation_rules()) {} + processing_mode_(config.processing_mode()), mutation_checker_(config.mutation_rules()), + filter_metadata_(config.filter_metadata()) {} bool failureModeAllow() const { return failure_mode_allow_; } @@ -99,6 +105,8 @@ class FilterConfig { bool disableClearRouteCache() const { return disable_clear_route_cache_; } + const Envoy::ProtobufWkt::Struct& filterMetadata() const { return filter_metadata_; } + private: ExtProcFilterStats generateStats(const std::string& prefix, const std::string& filter_stats_prefix, Stats::Scope& scope) { @@ -114,6 +122,7 @@ class FilterConfig { ExtProcFilterStats stats_; const envoy::extensions::filters::http::ext_proc::v3::ProcessingMode processing_mode_; const Filters::Common::MutationRules::Checker mutation_checker_; + const Envoy::ProtobufWkt::Struct filter_metadata_; }; using FilterConfigSharedPtr = std::shared_ptr; diff --git a/source/extensions/filters/http/fault/BUILD b/source/extensions/filters/http/fault/BUILD index fbc3b80420c6..a62c90509656 100644 --- a/source/extensions/filters/http/fault/BUILD +++ b/source/extensions/filters/http/fault/BUILD @@ -32,10 +32,12 @@ envoy_cc_library( "//source/common/http:header_map_lib", "//source/common/http:header_utility_lib", "//source/common/http:headers_lib", + "//source/common/protobuf", "//source/common/protobuf:utility_lib", "//source/common/stats:utility_lib", "//source/extensions/filters/common/fault:fault_config_lib", "//source/extensions/filters/http/common:stream_rate_limiter_lib", + "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/http/fault/v3:pkg_cc_proto", "@envoy_api//envoy/type/v3:pkg_cc_proto", ], diff --git a/source/extensions/filters/http/fault/fault_filter.cc b/source/extensions/filters/http/fault/fault_filter.cc index 6c8e89aebdfe..1ddbf8affced 100644 --- a/source/extensions/filters/http/fault/fault_filter.cc +++ b/source/extensions/filters/http/fault/fault_filter.cc @@ -50,7 +50,8 @@ FaultSettings::FaultSettings(const envoy::extensions::filters::http::fault::v3:: response_rate_limit_percent_runtime_( PROTOBUF_GET_STRING_OR_DEFAULT(fault, response_rate_limit_percent_runtime, RuntimeKeys::get().ResponseRateLimitPercentKey)), - disable_downstream_cluster_stats_(fault.disable_downstream_cluster_stats()) { + disable_downstream_cluster_stats_(fault.disable_downstream_cluster_stats()), + filter_metadata_(fault.filter_metadata()) { if (fault.has_abort()) { request_abort_config_ = std::make_unique(fault.abort()); @@ -169,6 +170,9 @@ bool FaultFilter::maybeSetupDelay(const Http::RequestHeaderMap& request_headers) delay_timer_->enableTimer(duration.value(), &decoder_callbacks_->scope()); recordDelaysInjectedStats(); decoder_callbacks_->streamInfo().setResponseFlag(StreamInfo::ResponseFlag::DelayInjected); + auto& dynamic_metadata = decoder_callbacks_->streamInfo().dynamicMetadata(); + (*dynamic_metadata.mutable_filter_metadata())[decoder_callbacks_->filterConfigName()] = + fault_settings_->filterMetadata(); return true; } return false; @@ -467,6 +471,9 @@ void FaultFilter::abortWithStatus(Http::Code http_status_code, absl::optional grpc_status) { recordAbortsInjectedStats(); decoder_callbacks_->streamInfo().setResponseFlag(StreamInfo::ResponseFlag::FaultInjected); + auto& dynamic_metadata = decoder_callbacks_->streamInfo().dynamicMetadata(); + (*dynamic_metadata.mutable_filter_metadata())[decoder_callbacks_->filterConfigName()] = + fault_settings_->filterMetadata(); decoder_callbacks_->sendLocalReply(http_status_code, "fault filter abort", nullptr, grpc_status, RcDetails::get().FaultAbort); } diff --git a/source/extensions/filters/http/fault/fault_filter.h b/source/extensions/filters/http/fault/fault_filter.h index 29ab9ba74f96..b377b0348b2b 100644 --- a/source/extensions/filters/http/fault/fault_filter.h +++ b/source/extensions/filters/http/fault/fault_filter.h @@ -5,6 +5,7 @@ #include #include +#include "envoy/config/core/v3/base.pb.h" #include "envoy/extensions/filters/http/fault/v3/fault.pb.h" #include "envoy/http/filter.h" #include "envoy/http/header_map.h" @@ -16,6 +17,7 @@ #include "source/common/buffer/watermark_buffer.h" #include "source/common/common/token_bucket_impl.h" #include "source/common/http/header_utility.h" +#include "source/common/protobuf/protobuf.h" #include "source/common/stats/symbol_table.h" #include "source/extensions/filters/common/fault/fault_config.h" #include "source/extensions/filters/http/common/stream_rate_limiter.h" @@ -74,6 +76,7 @@ class FaultSettings : public Router::RouteSpecificFilterConfig { return response_rate_limit_percent_runtime_; } bool disableDownstreamClusterStats() const { return disable_downstream_cluster_stats_; } + const Envoy::ProtobufWkt::Struct& filterMetadata() const { return filter_metadata_; } private: class RuntimeKeyValues { @@ -106,6 +109,8 @@ class FaultSettings : public Router::RouteSpecificFilterConfig { const std::string max_active_faults_runtime_; const std::string response_rate_limit_percent_runtime_; const bool disable_downstream_cluster_stats_; + + const Envoy::ProtobufWkt::Struct filter_metadata_; }; /** diff --git a/test/extensions/filters/http/ext_proc/BUILD b/test/extensions/filters/http/ext_proc/BUILD index 247a3979fb76..8a77756a3aab 100644 --- a/test/extensions/filters/http/ext_proc/BUILD +++ b/test/extensions/filters/http/ext_proc/BUILD @@ -38,6 +38,7 @@ envoy_extension_cc_test( "//envoy/network:filter_interface", "//source/common/http:context_lib", "//source/common/network:address_lib", + "//source/common/protobuf", "//source/common/stats:isolated_store_lib", "//source/extensions/filters/http/ext_proc", "//test/common/http:common_lib", diff --git a/test/extensions/filters/http/ext_proc/config_test.cc b/test/extensions/filters/http/ext_proc/config_test.cc index bb87b9fb6545..525c278f3b23 100644 --- a/test/extensions/filters/http/ext_proc/config_test.cc +++ b/test/extensions/filters/http/ext_proc/config_test.cc @@ -30,6 +30,8 @@ TEST(HttpExtProcConfigTest, CorrectConfig) { response_body_mode: buffered request_trailer_mode: skip response_trailer_mode: send + filter_metadata: + hello: "world" )EOF"; ExternalProcessingFilterConfig factory; diff --git a/test/extensions/filters/http/ext_proc/filter_test.cc b/test/extensions/filters/http/ext_proc/filter_test.cc index aec63f731000..45990a18e3cb 100644 --- a/test/extensions/filters/http/ext_proc/filter_test.cc +++ b/test/extensions/filters/http/ext_proc/filter_test.cc @@ -1,5 +1,6 @@ #include +#include "envoy/config/core/v3/base.pb.h" #include "envoy/config/core/v3/grpc_service.pb.h" #include "envoy/http/filter.h" #include "envoy/network/connection.h" @@ -9,6 +10,7 @@ #include "source/common/http/conn_manager_impl.h" #include "source/common/http/context_impl.h" #include "source/common/network/address_impl.h" +#include "source/common/protobuf/protobuf.h" #include "source/common/stats/isolated_store_impl.h" #include "source/extensions/filters/http/ext_proc/ext_proc.h" @@ -64,6 +66,7 @@ using testing::Unused; using namespace std::chrono_literals; static const uint32_t BufferSize = 100000; +static const std::string filter_config_name = "scooby.dooby.doo"; // These tests are all unit tests that directly drive an instance of the // ext_proc filter and verify the behavior using mocks. @@ -91,6 +94,7 @@ class HttpFilterTest : public testing::Test { timers_.push_back(timer); return timer; })); + EXPECT_CALL(decoder_callbacks_, filterConfigName()).WillRepeatedly(Return(filter_config_name)); envoy::extensions::filters::http::ext_proc::v3::ExternalProcessor proto_config{}; if (!yaml.empty()) { @@ -274,7 +278,7 @@ class HttpFilterTest : public testing::Test { stream_info_.filterState() ->getDataReadOnly< Envoy::Extensions::HttpFilters::ExternalProcessing::ExtProcLoggingInfo>( - Envoy::Extensions::HttpFilters::ExternalProcessing::ExtProcLoggingInfoName) + filter_config_name) ->grpcCalls(traffic_direction); int calls_count = std::count_if( grpc_calls.begin(), grpc_calls.end(), @@ -282,6 +286,17 @@ class HttpFilterTest : public testing::Test { EXPECT_EQ(calls_count, expected_calls_count); } + // The metadata configured as part of ext_proc filter should be in the filter state. + void expectMetadataInFilterState(const Envoy::ProtobufWkt::Struct& expected_metadata) { + const Envoy::ProtobufWkt::Struct& loggedMetadata = + stream_info_.filterState() + ->getDataReadOnly< + Envoy::Extensions::HttpFilters::ExternalProcessing::ExtProcLoggingInfo>( + filter_config_name) + ->filterMetadata(); + EXPECT_THAT(loggedMetadata, ProtoEq(expected_metadata)); + } + absl::optional final_expected_grpc_service_; std::unique_ptr client_; ExternalProcessorCallbacks* stream_callbacks_ = nullptr; @@ -310,6 +325,8 @@ TEST_F(HttpFilterTest, SimplestPost) { envoy_grpc: cluster_name: "ext_proc_server" failure_mode_allow: true + filter_metadata: + scooby: "doo" )EOF"); EXPECT_TRUE(config_->failureModeAllow()); @@ -365,6 +382,10 @@ TEST_F(HttpFilterTest, SimplestPost) { EXPECT_EQ(1, config_->stats().streams_closed_.value()); expectGrpcCalls(envoy::config::core::v3::TrafficDirection::INBOUND, Grpc::Status::Ok, 1); expectGrpcCalls(envoy::config::core::v3::TrafficDirection::OUTBOUND, Grpc::Status::Ok, 1); + + Envoy::ProtobufWkt::Struct filter_metadata; + (*filter_metadata.mutable_fields())["scooby"].set_string_value("doo"); + expectMetadataInFilterState(filter_metadata); } // Using the default configuration, test the filter with a processor that @@ -510,6 +531,7 @@ TEST_F(HttpFilterTest, PostAndRespondImmediately) { EXPECT_EQ(1, config_->stats().streams_closed_.value()); expectGrpcCalls(envoy::config::core::v3::TrafficDirection::INBOUND, Grpc::Status::Ok, 1); expectGrpcCalls(envoy::config::core::v3::TrafficDirection::OUTBOUND, Grpc::Status::Ok, 0); + expectMetadataInFilterState(Envoy::ProtobufWkt::Struct()); } // Using the default configuration, test the filter with a processor that diff --git a/test/extensions/filters/http/fault/config_test.cc b/test/extensions/filters/http/fault/config_test.cc index 0dcef3419f74..b445c36b43ae 100644 --- a/test/extensions/filters/http/fault/config_test.cc +++ b/test/extensions/filters/http/fault/config_test.cc @@ -28,6 +28,8 @@ TEST(FaultFilterConfigTest, ValidateFail) { TEST(FaultFilterConfigTest, FaultFilterCorrectJson) { const std::string yaml_string = R"EOF( + filter_metadata: + hello: "world" delay: percentage: numerator: 100 diff --git a/test/extensions/filters/http/fault/fault_filter_test.cc b/test/extensions/filters/http/fault/fault_filter_test.cc index 813734b1329f..2a8cac10b808 100644 --- a/test/extensions/filters/http/fault/fault_filter_test.cc +++ b/test/extensions/filters/http/fault/fault_filter_test.cc @@ -62,6 +62,8 @@ class FaultFilterTest : public testing::Test { numerator: 100 denominator: HUNDRED fixed_delay: 5s + filter_metadata: + hello: "world" )EOF"; const std::string fixed_delay_only_disable_stats_yaml = R"EOF( @@ -92,9 +94,13 @@ class FaultFilterTest : public testing::Test { numerator: 100 denominator: HUNDRED http_status: 503 + filter_metadata: + hello: "world" )EOF"; const std::string header_abort_only_yaml = R"EOF( + filter_metadata: + hello: "world" abort: header_abort: {} percentage: @@ -136,6 +142,8 @@ class FaultFilterTest : public testing::Test { filter_ = std::make_unique(config_); filter_->setDecoderFilterCallbacks(decoder_filter_callbacks_); filter_->setEncoderFilterCallbacks(encoder_filter_callbacks_); + ON_CALL(decoder_filter_callbacks_, filterConfigName) + .WillByDefault(Return("envoy.filters.http.fault")); EXPECT_CALL(decoder_filter_callbacks_.dispatcher_, pushTrackedObject(_)).Times(AnyNumber()); EXPECT_CALL(decoder_filter_callbacks_.dispatcher_, popTrackedObject(_)).Times(AnyNumber()); } @@ -230,12 +238,7 @@ TEST(FaultFilterBadConfigTest, MissingDelayDuration) { } TEST_F(FaultFilterTest, AbortWithHttpStatus) { - envoy::extensions::filters::http::fault::v3::HTTPFault fault; - fault.mutable_abort()->mutable_percentage()->set_numerator(100); - fault.mutable_abort()->mutable_percentage()->set_denominator( - envoy::type::v3::FractionalPercent::HUNDRED); - fault.mutable_abort()->set_http_status(429); - setUpTest(fault); + setUpTest(abort_only_yaml); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.max_active_faults", std::numeric_limits::max())) @@ -285,6 +288,12 @@ TEST_F(FaultFilterTest, HeaderAbortWithHttpStatus) { request_headers_.addCopy("x-envoy-fault-abort-request", "429"); + envoy::config::core::v3::Metadata dynamic_metadata; + envoy::config::core::v3::Metadata expected_metadata; + auto& filter_metadata = *expected_metadata.mutable_filter_metadata(); + (*filter_metadata["envoy.filters.http.fault"].mutable_fields())["hello"].set_string_value( + "world"); + EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); @@ -303,6 +312,8 @@ TEST_F(FaultFilterTest, HeaderAbortWithHttpStatus) { EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 429)) .WillOnce(Return(429)); + EXPECT_CALL(decoder_filter_callbacks_.stream_info_, dynamicMetadata()) + .WillOnce(ReturnRef(dynamic_metadata)); Http::TestResponseHeaderMapImpl response_headers{ {":status", "429"}, {"content-length", "18"}, {"content-type", "text/plain"}}; @@ -326,6 +337,7 @@ TEST_F(FaultFilterTest, HeaderAbortWithHttpStatus) { EXPECT_EQ(1UL, config_->stats().aborts_injected_.value()); EXPECT_EQ(0UL, config_->stats().active_faults_.value()); EXPECT_EQ("fault_filter_abort", decoder_filter_callbacks_.details()); + EXPECT_THAT(dynamic_metadata, ProtoEq(expected_metadata)); } TEST_F(FaultFilterTest, AbortWithGrpcStatus) { @@ -501,6 +513,7 @@ TEST_F(FaultFilterTest, FixedDelayZeroDuration) { EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(_)).Times(0); + EXPECT_CALL(decoder_filter_callbacks_.stream_info_, dynamicMetadata()).Times(0); EXPECT_CALL(decoder_filter_callbacks_, continueDecoding()).Times(0); // Expect filter to continue execution when delay is 0ms @@ -529,7 +542,7 @@ TEST_F(FaultFilterTest, Overflow) { EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(0)); - + EXPECT_CALL(decoder_filter_callbacks_.stream_info_, dynamicMetadata()).Times(0); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers_, true)); EXPECT_EQ(0UL, config_->stats().active_faults_.value()); @@ -598,6 +611,12 @@ TEST_F(FaultFilterTest, FixedDelayDeprecatedPercentAndNonZeroDuration) { TEST_F(FaultFilterTest, ConsecutiveDelayFaults) { setUpTest(fixed_delay_only_yaml); + envoy::config::core::v3::Metadata dynamic_metadata; + envoy::config::core::v3::Metadata expected_metadata; + auto& filter_metadata = *expected_metadata.mutable_filter_metadata(); + (*filter_metadata["envoy.filters.http.fault"].mutable_fields())["hello"].set_string_value( + "world"); + // Set the max number of faults to 1. EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.max_active_faults", std::numeric_limits::max())) @@ -622,6 +641,9 @@ TEST_F(FaultFilterTest, ConsecutiveDelayFaults) { EXPECT_CALL(decoder_filter_callbacks_.stream_info_, setResponseFlag(StreamInfo::ResponseFlag::DelayInjected)) .Times(2); + EXPECT_CALL(decoder_filter_callbacks_.stream_info_, dynamicMetadata()) + .WillOnce(ReturnRef(dynamic_metadata)) + .WillOnce(ReturnRef(dynamic_metadata)); // Start request 1 with a fault delay. EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, @@ -649,6 +671,7 @@ TEST_F(FaultFilterTest, ConsecutiveDelayFaults) { // Should stop counting as active fault after delay elapsed. EXPECT_EQ(0UL, config_->stats().active_faults_.value()); EXPECT_EQ(0UL, config_->stats().aborts_injected_.value()); + EXPECT_THAT(dynamic_metadata, ProtoEq(expected_metadata)); // Prep up request 2, with setups and expectations same as request 1. setUpTest(fixed_delay_only_yaml); @@ -667,6 +690,7 @@ TEST_F(FaultFilterTest, ConsecutiveDelayFaults) { // Have the fault delay of request 2 kick in, which should be delayed with success. timer_->invokeCallback(); + EXPECT_THAT(dynamic_metadata, ProtoEq(expected_metadata)); filter_->onDestroy(); EXPECT_EQ(2UL, config_->stats().delays_injected_.value()); @@ -775,6 +799,15 @@ TEST_F(FaultFilterTest, DelayForDownstreamClusterDisableTracing) { TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) { setUpTest(fixed_delay_and_abort_yaml); + envoy::config::core::v3::Metadata dynamic_metadata; + ON_CALL(decoder_filter_callbacks_.stream_info_, dynamicMetadata()) + .WillByDefault(ReturnRef(dynamic_metadata)); + + envoy::config::core::v3::Metadata expected_metadata; + auto& filter_metadata = *expected_metadata.mutable_filter_metadata(); + (*filter_metadata["envoy.filters.http.fault"].mutable_fields())["hello"].set_string_value( + "world"); + EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.max_active_faults", std::numeric_limits::max())) .WillOnce(Return(std::numeric_limits::max())); @@ -829,6 +862,7 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) { EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data_, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_->decodeTrailers(request_trailers_)); EXPECT_EQ(1UL, config_->stats().active_faults_.value()); + EXPECT_THAT(dynamic_metadata, ProtoEq(expected_metadata)); filter_->onDestroy(); EXPECT_EQ(1UL, config_->stats().delays_injected_.value()); @@ -1358,8 +1392,13 @@ TEST_F(FaultFilterRateLimitTest, DelayWithResponseRateLimitEnabled) { } TEST_F(FaultFilterRateLimitTest, ResponseRateLimitEnabled) { - setupRateLimitTest(true); + // Set metadata in fault. Ensure that it does not get reflected in stream info. + envoy::extensions::filters::http::fault::v3::HTTPFault fault; + (*fault.mutable_filter_metadata()->mutable_fields())["hello"].set_string_value("world"); + + setupRateLimitTest(fault); + EXPECT_CALL(decoder_filter_callbacks_.stream_info_, dynamicMetadata()).Times(0); ON_CALL(encoder_filter_callbacks_, encoderBufferLimit()).WillByDefault(Return(1100)); Event::MockTimer* token_timer = new NiceMock(&decoder_filter_callbacks_.dispatcher_); diff --git a/test/mocks/http/mocks.h b/test/mocks/http/mocks.h index c6d5f7f3e412..d05224a06b04 100644 --- a/test/mocks/http/mocks.h +++ b/test/mocks/http/mocks.h @@ -267,6 +267,7 @@ class MockStreamDecoderFilterCallbacks : public StreamDecoderFilterCallbacks, MOCK_METHOD(Http1StreamEncoderOptionsOptRef, http1StreamEncoderOptions, ()); MOCK_METHOD(OptRef, downstreamCallbacks, ()); MOCK_METHOD(OptRef, upstreamCallbacks, ()); + MOCK_METHOD(absl::string_view, filterConfigName, (), (const override)); // Http::StreamDecoderFilterCallbacks // NOLINTNEXTLINE(readability-identifier-naming) @@ -358,6 +359,7 @@ class MockStreamEncoderFilterCallbacks : public StreamEncoderFilterCallbacks, MOCK_METHOD(Http1StreamEncoderOptionsOptRef, http1StreamEncoderOptions, ()); MOCK_METHOD(OptRef, downstreamCallbacks, ()); MOCK_METHOD(OptRef, upstreamCallbacks, ()); + MOCK_METHOD(absl::string_view, filterConfigName, (), (const override)); // Http::StreamEncoderFilterCallbacks MOCK_METHOD(void, addEncodedData, (Buffer::Instance & data, bool streaming)); From 548412cc44c53570bf0a9290f00419b6f70eb400 Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 22 May 2023 07:55:15 +0100 Subject: [PATCH 028/228] ci: Use bazel.yml for docs publishing (#27514) Signed-off-by: Ryan Northey --- .azure-pipelines/stage/publish.yml | 164 ++++++++++++++--------------- 1 file changed, 78 insertions(+), 86 deletions(-) diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml index 444e5db454d0..bd74cb6424c7 100644 --- a/.azure-pipelines/stage/publish.yml +++ b/.azure-pipelines/stage/publish.yml @@ -226,8 +226,83 @@ jobs: set -e rm -rf $(Build.StagingDirectory)/.gnupg +- job: docs + displayName: Publish docs + dependsOn: [] + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocs }}, 'true')) + pool: + vmImage: "ubuntu-20.04" + steps: + - template: ../bazel.yml + parameters: + ciTarget: docs + cacheVersion: $(cacheKeyBazel) + publishEnvoy: false + publishTestResults: false + stepsPost: + + - script: | + ci/run_envoy_docker.sh 'ci/do_ci.sh dockerhub-publish' + condition: | + and(not(canceled()), + eq(${{ parameters.publishDockerhub }}, 'true')) + displayName: "Publish Dockerhub description and README" + env: + ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) + ENVOY_RBE: "1" + BAZEL_BUILD_EXTRA_OPTIONS: "--config=remote-ci --jobs=$(RbeJobs)" + BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com + BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance + GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} + GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} + DOCKERHUB_USERNAME: ${{ parameters.authDockerUser }} + DOCKERHUB_PASSWORD: ${{ parameters.authDockerPassword }} + + # Trigger Netlify rebuild of latest docs + - script: | + ci/run_envoy_docker.sh 'ci/do_ci.sh docs-upload' + displayName: "Upload Docs to GCS" + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocsLatest }}, 'true')) + env: + ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) + ENVOY_RBE: "1" + BAZEL_BUILD_EXTRA_OPTIONS: "--config=remote-ci --jobs=$(RbeJobs)" + BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com + BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance + GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} + GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} + - script: ci/run_envoy_docker.sh 'ci/do_ci.sh docs-publish-latest' + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocsLatest }}, 'true')) + displayName: "Publish latest docs" + workingDirectory: $(Build.SourcesDirectory) + env: + NETLIFY_TRIGGER_URL: ${{ parameters.authNetlifyURL }} + + # Publish docs to the website + - task: InstallSSHKey@0 + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocsRelease }}, 'true')) + inputs: + hostName: $(authGithubSSHKeyPublic) + sshPublicKey: "${{ parameters.authSSHDocsKeyPublic }}" + sshPassphrase: "${{ parameters.authSSHKeyPassphrase }}" + sshKeySecureFile: "${{ parameters.authSSHDocsKey }}" + - script: docs/publish.sh + condition: | + and(not(canceled()), + eq(${{ parameters.publishDocsRelease }}, 'true')) + displayName: "Publish release docs" + workingDirectory: $(Build.SourcesDirectory) + - job: success - dependsOn: ["docker", "package_x64", "package_arm64"] + dependsOn: ["docker", "package_x64", "package_arm64", "docs"] displayName: Success (linux artefacts) pool: vmImage: "ubuntu-20.04" @@ -239,96 +314,13 @@ jobs: and( in(dependencies.docker.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), in(dependencies.package_x64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), - in(dependencies.package_arm64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')) + in(dependencies.package_arm64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), + in(dependencies.docs.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')) steps: - checkout: none - bash: | echo "building publishable assets complete" -- job: docs - displayName: Publish docs - dependsOn: ["success"] - condition: | - and(not(canceled()), - eq(${{ parameters.publishDocs }}, 'true')) - pool: - vmImage: "ubuntu-20.04" - steps: - - task: Cache@2 - inputs: - key: 'docs | $(cacheKeyBazelFiles)' - path: $(Build.StagingDirectory)/repository_cache - continueOnError: true - - - script: ci/run_envoy_docker.sh 'ci/do_ci.sh docs' - workingDirectory: $(Build.SourcesDirectory) - env: - ENVOY_RBE: "true" - BAZEL_BUILD_EXTRA_OPTIONS: "--config=remote-ci --jobs=$(RbeJobs)" - AZP_BRANCH: $(Build.SourceBranch) - ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) - BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com - BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance - GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} - displayName: "Generate docs" - - - script: | - ci/run_envoy_docker.sh 'ci/do_ci.sh dockerhub-publish' - condition: | - and(not(canceled()), - eq(${{ parameters.publishDockerhub }}, 'true')) - displayName: "Publish Dockerhub description and README" - env: - ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) - ENVOY_RBE: "1" - BAZEL_BUILD_EXTRA_OPTIONS: "--config=remote-ci --jobs=$(RbeJobs)" - BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com - BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance - GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} - GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} - DOCKERHUB_USERNAME: ${{ parameters.authDockerUser }} - DOCKERHUB_PASSWORD: ${{ parameters.authDockerPassword }} - - - script: | - ci/run_envoy_docker.sh 'ci/do_ci.sh docs-upload' - displayName: "Upload Docs to GCS" - env: - ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) - ENVOY_RBE: "1" - BAZEL_BUILD_EXTRA_OPTIONS: "--config=remote-ci --jobs=$(RbeJobs)" - BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com - BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance - GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} - GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} - condition: eq(variables['isMain'], 'true') - - # Trigger Netlify rebuild of latest docs - - script: ci/run_envoy_docker.sh 'ci/do_ci.sh docs-publish-latest' - condition: | - and(not(canceled()), - eq(${{ parameters.publishDocsLatest }}, 'true')) - displayName: "Publish latest docs" - workingDirectory: $(Build.SourcesDirectory) - env: - NETLIFY_TRIGGER_URL: ${{ parameters.authNetlifyURL }} - - # Publish docs to the website - - task: InstallSSHKey@0 - condition: | - and(not(canceled()), - eq(${{ parameters.publishDocsRelease }}, 'true')) - inputs: - hostName: $(authGithubSSHKeyPublic) - sshPublicKey: "${{ parameters.authSSHDocsKeyPublic }}" - sshPassphrase: "${{ parameters.authSSHKeyPassphrase }}" - sshKeySecureFile: "${{ parameters.authSSHDocsKey }}" - - script: docs/publish.sh - condition: | - and(not(canceled()), - eq(${{ parameters.publishDocsRelease }}, 'true')) - displayName: "Publish release docs" - workingDirectory: $(Build.SourcesDirectory) - - job: github displayName: Publish release tag dependsOn: ["docs"] From 6de1595999806897913ac77b45781b251208007a Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Mon, 22 May 2023 15:42:50 +0800 Subject: [PATCH 029/228] hyperscan: skip compilation on unused libs (#27534) Signed-off-by: Xie Zhihao --- bazel/foreign_cc/hyperscan.patch | 56 +++++++++++++++++-- .../matching/input_matchers/source/BUILD | 2 + 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/bazel/foreign_cc/hyperscan.patch b/bazel/foreign_cc/hyperscan.patch index 95007a0d3e9b..b8d1179f7103 100644 --- a/bazel/foreign_cc/hyperscan.patch +++ b/bazel/foreign_cc/hyperscan.patch @@ -1,9 +1,20 @@ -# No compilation for binaries +# No compilation for unused binaries and libs. diff --git a/CMakeLists.txt b/CMakeLists.txt -index 8bc6077..2ec9a11 100644 +index 7757916..6241f45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -482,9 +482,9 @@ if (CORRECT_PCRE_VERSION AND PCRE_BUILD_SOURCE AND BUILD_STATIC_LIBS) +@@ -477,8 +477,8 @@ else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + endif() + +-add_subdirectory(util) +-add_subdirectory(doc/dev-reference) ++# add_subdirectory(util) ++# add_subdirectory(doc/dev-reference) + + if (NOT WIN32) + # PCRE check, we have a fixed requirement for PCRE to use Chimera +@@ -496,9 +496,9 @@ if (CORRECT_PCRE_VERSION AND PCRE_BUILD_SOURCE AND BUILD_STATIC_LIBS) set(BUILD_CHIMERA TRUE) endif() @@ -15,7 +26,7 @@ index 8bc6077..2ec9a11 100644 endif() if (EXISTS ${CMAKE_SOURCE_DIR}/chimera/CMakeLists.txt AND BUILD_CHIMERA) add_subdirectory(chimera) -@@ -534,9 +534,9 @@ if (CORRECT_PCRE_VERSION AND PCRE_BUILD_SOURCE AND BUILD_STATIC_LIBS) +@@ -548,9 +548,9 @@ if (CORRECT_PCRE_VERSION AND PCRE_BUILD_SOURCE AND BUILD_STATIC_LIBS) set(BUILD_CHIMERA TRUE) endif() @@ -27,7 +38,42 @@ index 8bc6077..2ec9a11 100644 endif() if (EXISTS ${CMAKE_SOURCE_DIR}/chimera/CMakeLists.txt AND BUILD_CHIMERA) add_subdirectory(chimera) -# Workaround for uninitialized use +@@ -1194,8 +1194,8 @@ if (NOT FAT_RUNTIME) + if (BUILD_STATIC_LIBS) + add_library(hs_exec OBJECT ${hs_exec_SRCS}) + +- add_library(hs_runtime STATIC src/hs_version.c src/hs_valid_platform.c $) +- set_target_properties(hs_runtime PROPERTIES LINKER_LANGUAGE C) ++ # add_library(hs_runtime STATIC src/hs_version.c src/hs_valid_platform.c $) ++ # set_target_properties(hs_runtime PROPERTIES LINKER_LANGUAGE C) + + add_library(hs_compile OBJECT ${hs_compile_SRCS}) + +@@ -1271,10 +1271,10 @@ else (FAT_RUNTIME) + # hs_version.c is added explicitly to avoid some build systems that refuse to + # create a lib without any src (I'm looking at you Xcode) + +- add_library(hs_runtime STATIC src/hs_version.c +- $ +- ${RUNTIME_LIBS}) +- set_target_properties(hs_runtime PROPERTIES LINKER_LANGUAGE C) ++ # add_library(hs_runtime STATIC src/hs_version.c ++ # $ ++ # ${RUNTIME_LIBS}) ++ # set_target_properties(hs_runtime PROPERTIES LINKER_LANGUAGE C) + add_library(hs_compile OBJECT ${hs_compile_SRCS}) + + # we want the static lib for testing +@@ -1342,7 +1342,7 @@ else (FAT_RUNTIME) + endif (NOT FAT_RUNTIME) + + if (NOT BUILD_SHARED_LIBS) +- install(TARGETS hs_runtime DESTINATION ${CMAKE_INSTALL_LIBDIR}) ++ # install(TARGETS hs_runtime DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + + if (BUILD_STATIC_AND_SHARED OR BUILD_SHARED_LIBS) +# Workaround for uninitialized use. diff --git a/src/fdr/teddy_runtime_common.h b/src/fdr/teddy_runtime_common.h index b76800e..6e587c2 100644 --- a/src/fdr/teddy_runtime_common.h diff --git a/contrib/hyperscan/matching/input_matchers/source/BUILD b/contrib/hyperscan/matching/input_matchers/source/BUILD index 37f66ae582d2..5342badb28d1 100644 --- a/contrib/hyperscan/matching/input_matchers/source/BUILD +++ b/contrib/hyperscan/matching/input_matchers/source/BUILD @@ -26,10 +26,12 @@ envoy_cmake( "BUILD_AVX512": "on", "BUILD_AVX512VBMI": "on", "BUILD_EXAMPLES": "off", + "CMAKE_BUILD_TYPE": "Release", "CMAKE_INSTALL_LIBDIR": "lib", "FAT_RUNTIME": "on", "RAGEL": "$EXT_BUILD_DEPS/ragel/bin/ragel", }, + default_cache_entries = {}, lib_source = "@io_hyperscan//:all", out_static_libs = ["libhs.a"], tags = ["skip_on_windows"], From 3f1e91e3f96b143263b0ae2fa8cc73fdb551baad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 07:56:46 +0000 Subject: [PATCH 030/228] build(deps): bump envoy-base-utils from 0.4.7 to 0.4.10 in /tools/base (#27537) Bumps [envoy-base-utils](https://github.com/envoyproxy/toolshed) from 0.4.7 to 0.4.10. - [Release notes](https://github.com/envoyproxy/toolshed/releases) - [Commits](https://github.com/envoyproxy/toolshed/commits) --- updated-dependencies: - dependency-name: envoy-base-utils dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 4025f63386ce..5d6ffba67662 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -25,9 +25,9 @@ aio-api-bazel==0.0.2 \ --hash=sha256:56e36463d236e477b7e282f2d870185a0b978b50e2c3803c1ebf8b8ac4b18f5b \ --hash=sha256:d3f563b7698e874437d80538a89dd4d79bc37de2e850c846330ae456e3f21dcc # via -r requirements.in -aio-api-github==0.2.0 \ - --hash=sha256:09e7425b5e1eb46118ed2442c2d2d830eba6e2b6ae6c01ec1c6329ec900735c8 \ - --hash=sha256:d2d42d8c834baf4740d036fe37ef7dd66abe33f9c51d1ee1daa601185ec98b64 +aio-api-github==0.2.2 \ + --hash=sha256:507971a3a90155066a072d24fc40b3890f69b2f671a42c6325370a48cbbd0e06 \ + --hash=sha256:5e67bb397362ad0ccfd6b6680c94a995fdc8fb8cd795b5074dd29c5f875a9d62 # via # envoy-base-utils # envoy-dependency-check @@ -420,9 +420,9 @@ docutils==0.19 \ # via # envoy-docs-sphinx-runner # sphinx -envoy-base-utils==0.4.7 \ - --hash=sha256:1726809d5edbed6093c0fd779fe189d6ddc0491f2bfddf84b929deb0795292f0 \ - --hash=sha256:af918b0d9db86c1e907d93df7996b036e5bfc212fe7e491daa793dba5795c7e4 +envoy-base-utils==0.4.10 \ + --hash=sha256:1cfccb54a3831c5b5a833efdad67752c1ae0a8708532712842726de42c0c413a \ + --hash=sha256:9567d1317a9ed7e97730a664e3105d8a6d46a4fa9e5cc7256951f5564783d8ae # via # -r requirements.in # envoy-code-check From 70879eaa00d976ee91b87f5a14edafa80e0cdb0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 09:02:11 +0100 Subject: [PATCH 031/228] build(deps): bump setuptools from 67.7.2 to 67.8.0 in /tools/base (#27536) Bumps [setuptools](https://github.com/pypa/setuptools) from 67.7.2 to 67.8.0. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v67.7.2...v67.8.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 5d6ffba67662..ee3068fd0a65 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1523,9 +1523,9 @@ zstandard==0.21.0 \ # via envoy-base-utils # The following packages are considered to be unsafe in a requirements file: -setuptools==67.7.2 \ - --hash=sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b \ - --hash=sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990 +setuptools==67.8.0 \ + --hash=sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f \ + --hash=sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102 # via # -r requirements.in # sphinxcontrib-jquery From 9db3616fafd7ff593338c2c751daf471b911c0d3 Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 22 May 2023 12:33:00 +0100 Subject: [PATCH 032/228] deps: Bump `prometheus_metrics_model` -> 0.4.0 (#27481) Signed-off-by: Ryan Northey --- api/bazel/repository_locations.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index f6fd434d84ab..45015ca109f1 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -92,11 +92,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Prometheus client model", project_desc = "Data model artifacts for Prometheus", project_url = "https://github.com/prometheus/client_model", - version = "147c58e9608a4f9628b53b6cc863325ca746f63a", - sha256 = "f7da30879dcdfae367fa65af1969945c3148cfbfc462b30b7d36f17134675047", - release_date = "2021-06-07", + version = "0.4.0", + sha256 = "82fc41d9481476a778b120d4553e9e4edf06cc4efd52ee09ba000933d3a2a53d", + release_date = "2023-05-03", strip_prefix = "client_model-{version}", - urls = ["https://github.com/prometheus/client_model/archive/{version}.tar.gz"], + urls = ["https://github.com/prometheus/client_model/archive/v{version}.tar.gz"], use_category = ["api"], license = "Apache-2.0", license_url = "https://github.com/prometheus/client_model/blob/{version}/LICENSE", From cf9950bae4c9e5195c0419d8dab08ef085c0c78b Mon Sep 17 00:00:00 2001 From: Raven Black Date: Mon, 22 May 2023 05:50:11 -0700 Subject: [PATCH 033/228] Fix file_system_buffer flake (#27519) Signed-off-by: Raven Black --- .../filters/http/file_system_buffer/filter.cc | 14 +++++++------- .../filters/http/file_system_buffer/filter.h | 9 +++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/source/extensions/filters/http/file_system_buffer/filter.cc b/source/extensions/filters/http/file_system_buffer/filter.cc index c3270085ce27..c88198ad9173 100644 --- a/source/extensions/filters/http/file_system_buffer/filter.cc +++ b/source/extensions/filters/http/file_system_buffer/filter.cc @@ -228,6 +228,7 @@ void FileSystemBufferFilter::setEncoderFilterCallbacks( } void FileSystemBufferFilter::onDestroy() { + *is_destroyed_ = true; if (cancel_in_flight_async_action_) { cancel_in_flight_async_action_(); } @@ -400,11 +401,10 @@ bool FileSystemBufferFilter::maybeStorage(BufferedStreamState& state, // was deleted before the callback, not just do nothing. cancel_in_flight_async_action_ = config_->asyncFileManager().createAnonymousFile( config_->storageBufferPath(), - [this, me = std::weak_ptr(shared_from_this()), - dispatcher = &request_callbacks_->dispatcher(), + [this, is_destroyed = is_destroyed_, dispatcher = &request_callbacks_->dispatcher(), &state](absl::StatusOr file_handle) { - dispatcher->post([this, me = std::move(me), &state, file_handle]() { - if (!me.lock()) { + dispatcher->post([this, is_destroyed, &state, file_handle]() { + if (*is_destroyed) { // If we opened a file but the filter went away in the meantime, close the file // to avoid leaving a dangling file handle. if (file_handle.ok()) { @@ -456,10 +456,10 @@ std::function FileSystemBufferFilter::getOnFileActionComplet } std::function)> FileSystemBufferFilter::getSafeDispatch() { - return [me = std::weak_ptr(shared_from_this()), + return [is_destroyed = is_destroyed_, dispatcher = &request_callbacks_->dispatcher()](std::function callback) { - dispatcher->post([me = std::move(me), callback = std::move(callback)]() { - if (me.lock()) { + dispatcher->post([is_destroyed, callback = std::move(callback)]() { + if (!*is_destroyed) { callback(); } }); diff --git a/source/extensions/filters/http/file_system_buffer/filter.h b/source/extensions/filters/http/file_system_buffer/filter.h index a6a611ed9ede..02dfd1b1e101 100644 --- a/source/extensions/filters/http/file_system_buffer/filter.h +++ b/source/extensions/filters/http/file_system_buffer/filter.h @@ -41,8 +41,7 @@ struct BufferedStreamState { class FileSystemBufferFilter : public Http::StreamFilter, public Http::DownstreamWatermarkCallbacks, - public Logger::Loggable, - public std::enable_shared_from_this { + public Logger::Loggable { public: explicit FileSystemBufferFilter(std::shared_ptr base_config); @@ -67,6 +66,12 @@ class FileSystemBufferFilter : public Http::StreamFilter, void onDestroy() override; private: + // This is captured so that callbacks can alter their behavior (and avoid nullptr) + // if the filter has been destroyed since the callback was queued. + // We use this rather than shared_from_this because onDestroy happens potentially + // significantly earlier than the destructor, and we want to abort callbacks after + // onDestroy. + std::shared_ptr is_destroyed_ = std::make_shared(false); // Merges any per-route config with the default config. Returns false if the config lacked // a file manager. bool initPerRouteConfig(); From 9c6930fe04a46f8ba485c922cecaaaa0bc76b55c Mon Sep 17 00:00:00 2001 From: pianiststickman <34144687+pianiststickman@users.noreply.github.com> Date: Mon, 22 May 2023 10:03:07 -0400 Subject: [PATCH 034/228] socket: user space io handle invokes drain trackers immediately upon write (#27499) * Fix use-after-free in user space IO handle where a drain callback may refer to a freed object (i.e. the connection on the other side of the internal listener, which may already have died). The solution employed herein is to call and clear the drain trackers on write(), since - as far as the handle being written to is concerned - we don't care about the write buffer as soon as it has been written to the peer's IO handle. Signed-off-by: Eugene Chan --- .../network/test/postgres_decoder_test.cc | 1 + envoy/buffer/buffer.h | 12 ++++++++++++ source/common/buffer/buffer_impl.cc | 10 ++++++++++ source/common/buffer/buffer_impl.h | 1 + source/common/buffer/watermark_buffer.cc | 6 ++++++ source/common/buffer/watermark_buffer.h | 1 + .../io_socket/user_space/io_handle_impl.cc | 2 +- test/common/buffer/buffer_fuzz.cc | 4 +++- .../io_socket/user_space/io_handle_impl_test.cc | 17 +++++++++++++++++ test/mocks/buffer/mocks.h | 2 ++ 10 files changed, 54 insertions(+), 2 deletions(-) diff --git a/contrib/postgres_proxy/filters/network/test/postgres_decoder_test.cc b/contrib/postgres_proxy/filters/network/test/postgres_decoder_test.cc index 5700839e915b..988779c1338c 100644 --- a/contrib/postgres_proxy/filters/network/test/postgres_decoder_test.cc +++ b/contrib/postgres_proxy/filters/network/test/postgres_decoder_test.cc @@ -691,6 +691,7 @@ class FakeBuffer : public Buffer::Instance { MOCK_METHOD(void*, linearize, (uint32_t), (override)); MOCK_METHOD(void, move, (Instance&), (override)); MOCK_METHOD(void, move, (Instance&, uint64_t), (override)); + MOCK_METHOD(void, move, (Instance&, uint64_t, bool), (override)); MOCK_METHOD(Buffer::Reservation, reserveForRead, (), (override)); MOCK_METHOD(Buffer::ReservationSingleSlice, reserveSingleSlice, (uint64_t, bool), (override)); MOCK_METHOD(void, commit, diff --git a/envoy/buffer/buffer.h b/envoy/buffer/buffer.h index b5233746e364..b94fef17fe50 100644 --- a/envoy/buffer/buffer.h +++ b/envoy/buffer/buffer.h @@ -276,6 +276,18 @@ class Instance { */ virtual void move(Instance& rhs, uint64_t length) PURE; + /** + * Move a portion of a buffer into this buffer. If reset_drain_trackers_and_accounting is true, + * then any drain trackers on the source buffer are also called and cleared so that the + * connection originating the source buffer (e.g. an internal listener connection) may be deleted + * without causing a use-after-free. + * @param rhs supplies the buffer to move. + * @param length supplies the amount of data to move. + * @param reset_drain_trackers_and_accounting whether the drain trackers on the source buffers + * should be cleared, so that the source buffer is deletable. + */ + virtual void move(Instance& rhs, uint64_t length, bool reset_drain_trackers_and_accounting) PURE; + /** * Reserve space in the buffer for reading into. The amount of space reserved is determined * based on buffer settings and performance considerations. diff --git a/source/common/buffer/buffer_impl.cc b/source/common/buffer/buffer_impl.cc index 5744c4ef4696..fc62e061303c 100644 --- a/source/common/buffer/buffer_impl.cc +++ b/source/common/buffer/buffer_impl.cc @@ -325,6 +325,10 @@ void OwnedImpl::move(Instance& rhs) { } void OwnedImpl::move(Instance& rhs, uint64_t length) { + move(rhs, length, /*reset_drain_trackers_and_accounting=*/false); +} + +void OwnedImpl::move(Instance& rhs, uint64_t length, bool reset_drain_trackers_and_accounting) { ASSERT(&rhs != this); // See move() above for why we do the static cast. OwnedImpl& other = static_cast(rhs); @@ -340,6 +344,12 @@ void OwnedImpl::move(Instance& rhs, uint64_t length) { other.slices_.front().drain(copy_size); other.length_ -= copy_size; } else { + if (reset_drain_trackers_and_accounting) { + // The other slice is owned by a user-space IO handle and its drain trackers may refer to a + // connection that can die (and be freed) at any time. Call and clear the drain trackers to + // avoid potential use-after-free. + other.slices_.front().callAndClearDrainTrackersAndCharges(); + } coalesceOrAddSlice(std::move(other.slices_.front())); other.slices_.pop_front(); other.length_ -= slice_size; diff --git a/source/common/buffer/buffer_impl.h b/source/common/buffer/buffer_impl.h index 301f78e071d8..058657dc5abd 100644 --- a/source/common/buffer/buffer_impl.h +++ b/source/common/buffer/buffer_impl.h @@ -669,6 +669,7 @@ class OwnedImpl : public LibEventInstance { void* linearize(uint32_t size) override; void move(Instance& rhs) override; void move(Instance& rhs, uint64_t length) override; + void move(Instance& rhs, uint64_t length, bool reset_drain_trackers_and_accounting) override; Reservation reserveForRead() override; ReservationSingleSlice reserveSingleSlice(uint64_t length, bool separate_slice = false) override; ssize_t search(const void* data, uint64_t size, size_t start, size_t length) const override; diff --git a/source/common/buffer/watermark_buffer.cc b/source/common/buffer/watermark_buffer.cc index 3292d6c08f14..f7e3297baebc 100644 --- a/source/common/buffer/watermark_buffer.cc +++ b/source/common/buffer/watermark_buffer.cc @@ -67,6 +67,12 @@ void WatermarkBuffer::move(Instance& rhs, uint64_t length) { checkHighAndOverflowWatermarks(); } +void WatermarkBuffer::move(Instance& rhs, uint64_t length, + bool reset_drain_trackers_and_accounting) { + OwnedImpl::move(rhs, length, reset_drain_trackers_and_accounting); + checkHighAndOverflowWatermarks(); +} + SliceDataPtr WatermarkBuffer::extractMutableFrontSlice() { auto result = OwnedImpl::extractMutableFrontSlice(); checkLowWatermark(); diff --git a/source/common/buffer/watermark_buffer.h b/source/common/buffer/watermark_buffer.h index c9efe00b201f..c9de30551a4c 100644 --- a/source/common/buffer/watermark_buffer.h +++ b/source/common/buffer/watermark_buffer.h @@ -38,6 +38,7 @@ class WatermarkBuffer : public OwnedImpl { void drain(uint64_t size) override; void move(Instance& rhs) override; void move(Instance& rhs, uint64_t length) override; + void move(Instance& rhs, uint64_t length, bool reset_drain_trackers_and_accounting) override; SliceDataPtr extractMutableFrontSlice() override; Reservation reserveForRead() override; void postProcess() override { checkLowWatermark(); } diff --git a/source/extensions/io_socket/user_space/io_handle_impl.cc b/source/extensions/io_socket/user_space/io_handle_impl.cc index 959ab9735d81..8795512de3ff 100644 --- a/source/extensions/io_socket/user_space/io_handle_impl.cc +++ b/source/extensions/io_socket/user_space/io_handle_impl.cc @@ -43,7 +43,7 @@ uint64_t moveUpTo(Buffer::Instance& dst, Buffer::Instance& src, uint64_t max_len } } uint64_t res = std::min(max_length, src.length()); - dst.move(src, res); + dst.move(src, res, /*reset_drain_trackers_and_accounting=*/true); return res; } } // namespace diff --git a/test/common/buffer/buffer_fuzz.cc b/test/common/buffer/buffer_fuzz.cc index ce9ffc64cbbb..53d9aebe7f44 100644 --- a/test/common/buffer/buffer_fuzz.cc +++ b/test/common/buffer/buffer_fuzz.cc @@ -156,7 +156,9 @@ class StringBuffer : public Buffer::Instance { void move(Buffer::Instance& rhs) override { move(rhs, rhs.length()); } - void move(Buffer::Instance& rhs, uint64_t length) override { + void move(Buffer::Instance& rhs, uint64_t length) override { move(rhs, length, false); } + + void move(Buffer::Instance& rhs, uint64_t length, bool) override { StringBuffer& src = dynamic_cast(rhs); add(src.start(), length); src.start_ += length; diff --git a/test/extensions/io_socket/user_space/io_handle_impl_test.cc b/test/extensions/io_socket/user_space/io_handle_impl_test.cc index 01d441f0f778..de81cb2a4d32 100644 --- a/test/extensions/io_socket/user_space/io_handle_impl_test.cc +++ b/test/extensions/io_socket/user_space/io_handle_impl_test.cc @@ -184,6 +184,23 @@ TEST_F(IoHandleImplTest, ReadContent) { ASSERT_EQ(0, io_handle_->getWriteBuffer()->length()); } +TEST_F(IoHandleImplTest, WriteClearsDrainTrackers) { + Buffer::OwnedImpl buf_to_write("abcdefg"); + { + bool called = false; + // This drain tracker should be called as soon as the write happens; not on read. + buf_to_write.addDrainTracker([&called]() { called = true; }); + io_handle_peer_->write(buf_to_write); + EXPECT_TRUE(called); + } + // Now the drain tracker refers to a stack variable that no longer exists. If the drain tracker + // is called subsequently, this will fail in ASan. + Buffer::OwnedImpl buf; + auto result = io_handle_->read(buf, 10); + ASSERT_TRUE(result.ok()); + ASSERT_EQ(7, result.return_value_); +} + // Test read throttling on watermark buffer. TEST_F(IoHandleImplTest, ReadThrottling) { { diff --git a/test/mocks/buffer/mocks.h b/test/mocks/buffer/mocks.h index 20adb026f6e5..768decce37ce 100644 --- a/test/mocks/buffer/mocks.h +++ b/test/mocks/buffer/mocks.h @@ -24,6 +24,8 @@ template class MockBufferBase : public BaseClass { MOCK_METHOD(void, move, (Buffer::Instance & rhs)); MOCK_METHOD(void, move, (Buffer::Instance & rhs, uint64_t length)); + MOCK_METHOD(void, move, + (Buffer::Instance & rhs, uint64_t length, bool reset_drain_trackers_and_accounting)); MOCK_METHOD(void, drain, (uint64_t size)); void baseMove(Buffer::Instance& rhs) { BaseClass::move(rhs); } From 9d9f6afa56286a13d415ea2f1c582d367d9fc3fb Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 22 May 2023 16:26:02 +0100 Subject: [PATCH 035/228] ci/mobile: Improve `swift_async_await` timeout (#27483) Signed-off-by: Ryan Northey --- .github/workflows/mobile-ios_build.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mobile-ios_build.yml b/.github/workflows/mobile-ios_build.yml index dc824daea5dc..fd3601c1cc9b 100644 --- a/.github/workflows/mobile-ios_build.yml +++ b/.github/workflows/mobile-ios_build.yml @@ -189,7 +189,7 @@ jobs: name: swift_async_await needs: iosbuild runs-on: macos-12 - timeout-minutes: 120 + timeout-minutes: 50 steps: - uses: actions/checkout@v3 with: @@ -226,7 +226,23 @@ jobs: --config=ios \ $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //examples/swift/async_await:app &> /tmp/envoy.log & - - run: sed '/\[2\] Uploaded 7 MB of data/q' <(touch /tmp/envoy.log && tail -F /tmp/envoy.log) + - run: | + checklogs () { + sed '/\[2\] Uploaded 7 MB of data/q' <(touch /tmp/envoy.log && tail -F /tmp/envoy.log) + } + export -f checklogs + # TODO(phlax): figure if this needs this long + timeout 5m bash -c checklogs || { + retcode=$? + if [[ "$retcode" != 124 ]]; then + echo "Command failed" >&2 + elif grep -q "Upload failed" /tmp/envoy.log; then + echo "Upload failed" >&2 + else + echo "Upload timed out" >&2 + fi + exit 1 + } if: steps.should_run.outputs.run_ci_job == 'true' name: 'Check upload succeeded' - run: cat /tmp/envoy.log From 00402e2d11faa830811e0fb5f941240dd8e80116 Mon Sep 17 00:00:00 2001 From: Jarno Rajahalme Date: Mon, 22 May 2023 19:42:51 +0300 Subject: [PATCH 036/228] router: Do not set SNI or SAN due to auto_sni or auto_san if already set (#25800) Signed-off-by: Jarno Rajahalme --- api/envoy/config/core/v3/protocol.proto | 3 ++ changelogs/current.yaml | 4 ++ source/common/router/router.cc | 8 ++- test/common/router/router_test.cc | 66 ++++++++++++++++++------- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/api/envoy/config/core/v3/protocol.proto b/api/envoy/config/core/v3/protocol.proto index 95670bb752b4..17fe88311eae 100644 --- a/api/envoy/config/core/v3/protocol.proto +++ b/api/envoy/config/core/v3/protocol.proto @@ -104,12 +104,14 @@ message UpstreamHttpProtocolOptions { // upstream connections based on the downstream HTTP host/authority header or any other arbitrary // header when :ref:`override_auto_sni_header ` // is set, as seen by the :ref:`router filter `. + // Does nothing if a filter before the http router filter sets the corresponding metadata. bool auto_sni = 1; // Automatic validate upstream presented certificate for new upstream connections based on the // downstream HTTP host/authority header or any other arbitrary header when :ref:`override_auto_sni_header ` // is set, as seen by the :ref:`router filter `. // This field is intended to be set with ``auto_sni`` field. + // Does nothing if a filter before the http router filter sets the corresponding metadata. bool auto_san_validation = 2; // An optional alternative to the host/authority header to be used for setting the SNI value. @@ -119,6 +121,7 @@ message UpstreamHttpProtocolOptions { // is not found or the value is empty, host/authority header will be used instead. // This field is intended to be set with ``auto_sni`` and/or ``auto_san_validation`` fields. // If none of these fields are set then setting this would be a no-op. + // Does nothing if a filter before the http router filter sets the corresponding metadata. string override_auto_sni_header = 3 [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; } diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 1ff740abec2e..1e8249a02621 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -60,6 +60,10 @@ minor_behavior_changes: the cookie is still accepted, but is planned to be obsoleted in the future. This behavior change can be reverted by setting ``envoy.reloadable_features.stateful_session_encode_ttl_in_cookie`` to ``false``. +- area: router + change: | + Added check for existing metadata before setting metadata due to 'auto_sni', 'auto_san_validation', or + 'override_auto_sni_header' to prevent triggering ENVOY_BUG when an earlier filter has set the metadata. - area: resource_monitors change: | Changed behavior of the fixed heap monitor to count unused mapped pages as diff --git a/source/common/router/router.cc b/source/common/router/router.cc index 9b9de47bcd24..b03ea8b89a5a 100644 --- a/source/common/router/router.cc +++ b/source/common/router/router.cc @@ -547,14 +547,18 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, // `host_` returns a string_view so doing this should be safe. absl::string_view sni_value = parsed_authority.host_; - if (should_set_sni && upstream_http_protocol_options.value().auto_sni()) { + if (should_set_sni && upstream_http_protocol_options.value().auto_sni() && + !callbacks_->streamInfo().filterState()->hasDataWithName( + Network::UpstreamServerName::key())) { callbacks_->streamInfo().filterState()->setData( Network::UpstreamServerName::key(), std::make_unique(sni_value), StreamInfo::FilterState::StateType::Mutable); } - if (upstream_http_protocol_options.value().auto_san_validation()) { + if (upstream_http_protocol_options.value().auto_san_validation() && + !callbacks_->streamInfo().filterState()->hasDataWithName( + Network::UpstreamSubjectAltNames::key())) { callbacks_->streamInfo().filterState()->setData( Network::UpstreamSubjectAltNames::key(), std::make_unique( diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc index 8291e357148e..de30e05444be 100644 --- a/test/common/router/router_test.cc +++ b/test/common/router/router_test.cc @@ -162,10 +162,15 @@ class RouterTest : public RouterTestBase { router_->onDestroy(); } + // testAutoSniOptions checks that UpstreamServerName is server_name if non-empty, + // and that the first UpstreamSubjectAltNames is alt_server_name if non-empty. + // UpstreamServerName is pre-set to pre_set_sni if non-empty. void testAutoSniOptions( absl::optional dummy_option, - Envoy::Http::TestRequestHeaderMapImpl headers, std::string server_name = "host", - bool should_validate_san = false, std::string alt_server_name = "host") { + Envoy::Http::TestRequestHeaderMapImpl headers, std::string server_name = "", + std::string alt_server_name = "", std::string pre_set_sni = "", + StreamInfo::FilterState::LifeSpan pre_set_life_span = + StreamInfo::FilterState::LifeSpan::FilterChain) { NiceMock stream_info; ON_CALL(*cm_.thread_local_cluster_.cluster_.info_, upstreamHttpProtocolOptions()) .WillByDefault(ReturnRef(dummy_option)); @@ -173,18 +178,26 @@ class RouterTest : public RouterTestBase { .WillByDefault(ReturnRef(stream_info.filterState())); EXPECT_CALL(cm_.thread_local_cluster_.conn_pool_, newStream(_, _, _)) .WillOnce(Return(&cancellable_)); - stream_info.filterState()->setData(Network::UpstreamServerName::key(), - std::make_unique("dummy"), - StreamInfo::FilterState::StateType::Mutable); + + if (!pre_set_sni.empty()) { + // Simulate a network filter setting the server name, e.g. based on SNI seen by the + // tls_inspector by using the LifeSpan::Connection + stream_info.filterState()->setData(Network::UpstreamServerName::key(), + std::make_unique(pre_set_sni), + StreamInfo::FilterState::StateType::Mutable, + pre_set_life_span); + } expectResponseTimerCreate(); HttpTestUtility::addDefaultHeaders(headers); router_->decodeHeaders(headers, true); - EXPECT_EQ(server_name, - stream_info.filterState() - ->getDataReadOnly(Network::UpstreamServerName::key()) - ->value()); - if (should_validate_san) { + if (!server_name.empty()) { + EXPECT_EQ(server_name, stream_info.filterState() + ->getDataReadOnly( + Network::UpstreamServerName::key()) + ->value()); + } + if (!alt_server_name.empty()) { EXPECT_EQ(alt_server_name, stream_info.filterState() ->getDataReadOnly( Network::UpstreamSubjectAltNames::key()) @@ -205,7 +218,24 @@ TEST_F(RouterTest, UpdateServerNameFilterStateWithoutHeaderOverride) { dummy_option.value().set_auto_sni(true); Http::TestRequestHeaderMapImpl headers{}; - testAutoSniOptions(dummy_option, headers); + testAutoSniOptions(dummy_option, headers, "host"); +} + +TEST_F(RouterTest, DontUpdateServerNameFilterStateWhenExists) { + auto dummy_option = absl::make_optional(); + dummy_option.value().set_auto_sni(true); + + Http::TestRequestHeaderMapImpl headers{}; + testAutoSniOptions(dummy_option, headers, "old-host", "", "old-host"); +} + +TEST_F(RouterTest, DontUpdateServerNameFilterStateWhenExistsConnectionLifeSpan) { + auto dummy_option = absl::make_optional(); + dummy_option.value().set_auto_sni(true); + + Http::TestRequestHeaderMapImpl headers{}; + testAutoSniOptions(dummy_option, headers, "old-host", "", "old-host", + StreamInfo::FilterState::LifeSpan::Connection); } TEST_F(RouterTest, UpdateServerNameFilterStateWithHostHeaderOverride) { @@ -214,7 +244,7 @@ TEST_F(RouterTest, UpdateServerNameFilterStateWithHostHeaderOverride) { dummy_option.value().set_override_auto_sni_header(":authority"); Http::TestRequestHeaderMapImpl headers{}; - testAutoSniOptions(dummy_option, headers); + testAutoSniOptions(dummy_option, headers, "host"); } TEST_F(RouterTest, UpdateServerNameFilterStateWithHeaderOverride) { @@ -233,7 +263,7 @@ TEST_F(RouterTest, UpdateServerNameFilterStateWithEmptyValueHeaderOverride) { dummy_option.value().set_override_auto_sni_header("x-host"); Http::TestRequestHeaderMapImpl headers{{"x-host", ""}}; - testAutoSniOptions(dummy_option, headers); + testAutoSniOptions(dummy_option, headers, "host"); } TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithoutHeaderOverride) { @@ -242,7 +272,7 @@ TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithoutHeaderOverride) { dummy_option.value().set_auto_san_validation(true); Http::TestRequestHeaderMapImpl headers{}; - testAutoSniOptions(dummy_option, headers, "host", true); + testAutoSniOptions(dummy_option, headers, "host", "host"); } TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithHostHeaderOverride) { @@ -252,7 +282,7 @@ TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithHostHeaderOverride) { dummy_option.value().set_override_auto_sni_header(":authority"); Http::TestRequestHeaderMapImpl headers{}; - testAutoSniOptions(dummy_option, headers, "host", true); + testAutoSniOptions(dummy_option, headers, "host", "host"); } TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithHeaderOverride) { @@ -263,7 +293,7 @@ TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithHeaderOverride) { const auto server_name = "foo.bar"; Http::TestRequestHeaderMapImpl headers{{"x-host", server_name}}; - testAutoSniOptions(dummy_option, headers, server_name, true, server_name); + testAutoSniOptions(dummy_option, headers, server_name, server_name); } TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithEmptyValueHeaderOverride) { @@ -273,7 +303,7 @@ TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithEmptyValueHeaderOverride) dummy_option.value().set_override_auto_sni_header("x-host"); Http::TestRequestHeaderMapImpl headers{{"x-host", ""}}; - testAutoSniOptions(dummy_option, headers, "host", true); + testAutoSniOptions(dummy_option, headers, "host", "host"); } TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithIpHeaderOverride) { @@ -284,7 +314,7 @@ TEST_F(RouterTest, UpdateSubjectAltNamesFilterStateWithIpHeaderOverride) { const auto server_name = "127.0.0.1"; Http::TestRequestHeaderMapImpl headers{{"x-host", server_name}}; - testAutoSniOptions(dummy_option, headers, "dummy", true, server_name); + testAutoSniOptions(dummy_option, headers, "", server_name); } TEST_F(RouterTest, RouteNotFound) { From fb61801c03c544968606e97303439ebcade240bd Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Mon, 22 May 2023 14:15:04 -0400 Subject: [PATCH 037/228] runtime: e2e testing circuit breaker controls (#27544) Signed-off-by: Alyssa Wilk --- .../circuit_breakers_integration_test.cc | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test/integration/circuit_breakers_integration_test.cc b/test/integration/circuit_breakers_integration_test.cc index 695b743362ca..b0a7b5409d39 100644 --- a/test/integration/circuit_breakers_integration_test.cc +++ b/test/integration/circuit_breakers_integration_test.cc @@ -66,5 +66,67 @@ TEST_P(CircuitBreakersIntegrationTest, CircuitBreakersWithOutlierDetection) { 0); } +TEST_P(CircuitBreakersIntegrationTest, CircuitBreakerRuntime) { + config_helper_.addRuntimeOverride("circuit_breakers.cluster_0.default.max_requests", "0"); + config_helper_.addRuntimeOverride("circuit_breakers.cluster_0.default.max_retries", "1024"); + + config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + auto* static_resources = bootstrap.mutable_static_resources(); + auto* cluster = static_resources->mutable_clusters(0); + + auto* outlier_detection = cluster->mutable_outlier_detection(); + outlier_detection->mutable_consecutive_gateway_failure()->set_value(1); + outlier_detection->mutable_consecutive_5xx()->set_value(1); + outlier_detection->mutable_consecutive_local_origin_failure()->set_value(1); + + outlier_detection->mutable_enforcing_consecutive_gateway_failure()->set_value(100); + outlier_detection->mutable_enforcing_consecutive_5xx()->set_value(100); + outlier_detection->mutable_enforcing_consecutive_local_origin_failure()->set_value(100); + + outlier_detection->set_split_external_local_origin_errors(true); + + outlier_detection->mutable_max_ejection_percent()->set_value(100); + outlier_detection->mutable_interval()->set_nanos(1); + outlier_detection->mutable_base_ejection_time()->set_seconds(3600); + outlier_detection->mutable_max_ejection_time()->set_seconds(3600); + }); + + initialize(); + + codec_client_ = makeHttpConnection(lookupPort("http")); + + auto response = codec_client_->makeRequestWithBody(default_request_headers_, 1024); + + test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_active", 0); + test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_pending_active", 0); + + ASSERT_TRUE(response->waitForEndStream()); + + EXPECT_EQ("503", response->headers().getStatusValue()); + test_server_->waitForCounterGe("cluster.cluster_0.upstream_rq_503", 1); + + EXPECT_EQ(test_server_->counter("cluster.cluster_0.upstream_rq_pending_overflow")->value(), 1); + + EXPECT_EQ(test_server_->counter("cluster.cluster_0.outlier_detection.ejections_enforced_total") + ->value(), + 0); +#ifdef ENVOY_ADMIN_FUNCTIONALITY + auto codec_client2 = makeHttpConnection(lookupPort("admin")); + default_request_headers_.setPath("/runtime"); + response = codec_client2->makeHeaderOnlyRequest(default_request_headers_); + ASSERT_TRUE(response->waitForEndStream()); + EXPECT_EQ("200", response->headers().getStatusValue()); + codec_client2->close(); + + const std::string expected_json1 = R"EOF( + "circuit_breakers.cluster_0.default.max_retries": { +)EOF"; + EXPECT_TRUE(absl::StrContains(response->body(), expected_json1)); + + const std::string expected_json2 = R"EOF("final_value": "1024")EOF"; + EXPECT_TRUE(absl::StrContains(response->body(), expected_json2)); +#endif +} + } // namespace } // namespace Envoy From 29b62b8013587bdeb0849d97a4bd0bd555ec50e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 08:51:36 +0100 Subject: [PATCH 038/228] build(deps): bump requests from 2.25.1 to 2.31.0 in /.github/actions/pr_notifier (#27552) build(deps): bump requests in /.github/actions/pr_notifier Bumps [requests](https://github.com/psf/requests) from 2.25.1 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.25.1...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/pr_notifier/requirements.txt | 85 ++++++++++++++++++-- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/.github/actions/pr_notifier/requirements.txt b/.github/actions/pr_notifier/requirements.txt index 1f2fb83fc37f..f241eeaa3fc0 100644 --- a/.github/actions/pr_notifier/requirements.txt +++ b/.github/actions/pr_notifier/requirements.txt @@ -61,9 +61,82 @@ cffi==1.14.5 \ # via # cryptography # pynacl -chardet==4.0.0 \ - --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ - --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 +charset-normalizer==3.1.0 \ + --hash=sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6 \ + --hash=sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1 \ + --hash=sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e \ + --hash=sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373 \ + --hash=sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62 \ + --hash=sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230 \ + --hash=sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be \ + --hash=sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c \ + --hash=sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0 \ + --hash=sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448 \ + --hash=sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f \ + --hash=sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649 \ + --hash=sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d \ + --hash=sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0 \ + --hash=sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706 \ + --hash=sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a \ + --hash=sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59 \ + --hash=sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23 \ + --hash=sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5 \ + --hash=sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb \ + --hash=sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e \ + --hash=sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e \ + --hash=sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c \ + --hash=sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28 \ + --hash=sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d \ + --hash=sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41 \ + --hash=sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974 \ + --hash=sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce \ + --hash=sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f \ + --hash=sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1 \ + --hash=sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d \ + --hash=sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8 \ + --hash=sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017 \ + --hash=sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31 \ + --hash=sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7 \ + --hash=sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8 \ + --hash=sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e \ + --hash=sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14 \ + --hash=sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd \ + --hash=sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d \ + --hash=sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795 \ + --hash=sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b \ + --hash=sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b \ + --hash=sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b \ + --hash=sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203 \ + --hash=sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f \ + --hash=sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19 \ + --hash=sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1 \ + --hash=sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a \ + --hash=sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac \ + --hash=sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9 \ + --hash=sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0 \ + --hash=sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137 \ + --hash=sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f \ + --hash=sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6 \ + --hash=sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5 \ + --hash=sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909 \ + --hash=sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f \ + --hash=sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0 \ + --hash=sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324 \ + --hash=sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755 \ + --hash=sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb \ + --hash=sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854 \ + --hash=sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c \ + --hash=sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60 \ + --hash=sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84 \ + --hash=sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0 \ + --hash=sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b \ + --hash=sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1 \ + --hash=sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531 \ + --hash=sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1 \ + --hash=sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11 \ + --hash=sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326 \ + --hash=sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df \ + --hash=sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab # via requests cryptography==39.0.2 \ --hash=sha256:103e8f7155f3ce2ffa0049fe60169878d47a4364b277906386f8de21c9234aa1 \ @@ -130,9 +203,9 @@ pynacl==1.4.0 \ --hash=sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff \ --hash=sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80 # via pygithub -requests==2.25.1 \ - --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ - --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 # via pygithub six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ From 7dec65ff72c78e3cd3e4b57d5deef214c76c61cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 09:09:04 +0100 Subject: [PATCH 039/228] build(deps): bump grpcio-tools from 1.54.2 to 1.55.0 in /examples/grpc-bridge/client (#27558) build(deps): bump grpcio-tools in /examples/grpc-bridge/client Bumps [grpcio-tools](https://github.com/grpc/grpc) from 1.54.2 to 1.55.0. - [Release notes](https://github.com/grpc/grpc/releases) - [Changelog](https://github.com/grpc/grpc/blob/master/doc/grpc_release_schedule.md) - [Commits](https://github.com/grpc/grpc/compare/v1.54.2...v1.55.0) --- updated-dependencies: - dependency-name: grpcio-tools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/grpc-bridge/client/requirements.txt | 184 +++++++++---------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/examples/grpc-bridge/client/requirements.txt b/examples/grpc-bridge/client/requirements.txt index 4f4af0641998..4550459a94de 100644 --- a/examples/grpc-bridge/client/requirements.txt +++ b/examples/grpc-bridge/client/requirements.txt @@ -12,101 +12,101 @@ charset-normalizer==2.0.6 \ --hash=sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6 \ --hash=sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f # via requests -grpcio==1.54.2 \ - --hash=sha256:0212e2f7fdf7592e4b9d365087da30cb4d71e16a6f213120c89b4f8fb35a3ab3 \ - --hash=sha256:09d4bfd84686cd36fd11fd45a0732c7628308d094b14d28ea74a81db0bce2ed3 \ - --hash=sha256:1e623e0cf99a0ac114f091b3083a1848dbc64b0b99e181473b5a4a68d4f6f821 \ - --hash=sha256:2288d76e4d4aa7ef3fe7a73c1c470b66ea68e7969930e746a8cd8eca6ef2a2ea \ - --hash=sha256:2296356b5c9605b73ed6a52660b538787094dae13786ba53080595d52df13a98 \ - --hash=sha256:2a1e601ee31ef30a9e2c601d0867e236ac54c922d32ed9f727b70dd5d82600d5 \ - --hash=sha256:2be88c081e33f20630ac3343d8ad9f1125f32987968e9c8c75c051c9800896e8 \ - --hash=sha256:33d40954199bddbb6a78f8f6f2b2082660f381cd2583ec860a6c2fa7c8400c08 \ - --hash=sha256:40e1cbf69d6741b40f750f3cccc64326f927ac6145a9914d33879e586002350c \ - --hash=sha256:46a057329938b08e5f0e12ea3d7aed3ecb20a0c34c4a324ef34e00cecdb88a12 \ - --hash=sha256:4864f99aac207e3e45c5e26c6cbb0ad82917869abc2f156283be86c05286485c \ - --hash=sha256:4c44e1a765b31e175c391f22e8fc73b2a2ece0e5e6ff042743d8109b5d2eff9f \ - --hash=sha256:4cb283f630624ebb16c834e5ac3d7880831b07cbe76cb08ab7a271eeaeb8943e \ - --hash=sha256:5008964885e8d23313c8e5ea0d44433be9bfd7e24482574e8cc43c02c02fc796 \ - --hash=sha256:50a9f075eeda5097aa9a182bb3877fe1272875e45370368ac0ee16ab9e22d019 \ - --hash=sha256:51630c92591d6d3fe488a7c706bd30a61594d144bac7dee20c8e1ce78294f474 \ - --hash=sha256:5cc928cfe6c360c1df636cf7991ab96f059666ac7b40b75a769410cc6217df9c \ - --hash=sha256:61f7203e2767800edee7a1e1040aaaf124a35ce0c7fe0883965c6b762defe598 \ - --hash=sha256:66233ccd2a9371158d96e05d082043d47dadb18cbb294dc5accfdafc2e6b02a7 \ - --hash=sha256:70fcac7b94f4c904152809a050164650ac81c08e62c27aa9f156ac518029ebbe \ - --hash=sha256:714242ad0afa63a2e6dabd522ae22e1d76e07060b5af2ddda5474ba4f14c2c94 \ - --hash=sha256:782f4f8662a2157c4190d0f99eaaebc602899e84fb1e562a944e5025929e351c \ - --hash=sha256:7fc2b4edb938c8faa4b3c3ea90ca0dd89b7565a049e8e4e11b77e60e4ed2cc05 \ - --hash=sha256:881d058c5ccbea7cc2c92085a11947b572498a27ef37d3eef4887f499054dca8 \ - --hash=sha256:89dde0ac72a858a44a2feb8e43dc68c0c66f7857a23f806e81e1b7cc7044c9cf \ - --hash=sha256:8cdbcbd687e576d48f7886157c95052825ca9948c0ed2afdc0134305067be88b \ - --hash=sha256:8d6192c37a30a115f4663592861f50e130caed33efc4eec24d92ec881c92d771 \ - --hash=sha256:96a41817d2c763b1d0b32675abeb9179aa2371c72aefdf74b2d2b99a1b92417b \ - --hash=sha256:9bdbb7624d65dc0ed2ed8e954e79ab1724526f09b1efa88dcd9a1815bf28be5f \ - --hash=sha256:9bf88004fe086c786dc56ef8dd6cb49c026833fdd6f42cb853008bce3f907148 \ - --hash=sha256:a08920fa1a97d4b8ee5db2f31195de4a9def1a91bc003544eb3c9e6b8977960a \ - --hash=sha256:a2f5a1f1080ccdc7cbaf1171b2cf384d852496fe81ddedeb882d42b85727f610 \ - --hash=sha256:b04202453941a63b36876a7172b45366dc0cde10d5fd7855c0f4a4e673c0357a \ - --hash=sha256:b38b3de8cff5bc70f8f9c615f51b48eff7313fc9aca354f09f81b73036e7ddfa \ - --hash=sha256:b52d00d1793d290c81ad6a27058f5224a7d5f527867e5b580742e1bd211afeee \ - --hash=sha256:b74ae837368cfffeb3f6b498688a123e6b960951be4dec0e869de77e7fa0439e \ - --hash=sha256:be48496b0e00460717225e7680de57c38be1d8629dc09dadcd1b3389d70d942b \ - --hash=sha256:c0e3155fc5335ec7b3b70f15230234e529ca3607b20a562b6c75fb1b1218874c \ - --hash=sha256:c2392f5b5d84b71d853918687d806c1aa4308109e5ca158a16e16a6be71041eb \ - --hash=sha256:c72956972e4b508dd39fdc7646637a791a9665b478e768ffa5f4fe42123d5de1 \ - --hash=sha256:dc80c9c6b608bf98066a038e0172013a49cfa9a08d53335aefefda2c64fc68f4 \ - --hash=sha256:e416c8baf925b5a1aff31f7f5aecc0060b25d50cce3a5a7255dc5cf2f1d4e5eb \ - --hash=sha256:f8da84bbc61a4e92af54dc96344f328e5822d574f767e9b08e1602bb5ddc254a \ - --hash=sha256:f900ed4ad7a0f1f05d35f955e0943944d5a75f607a836958c6b8ab2a81730ef2 \ - --hash=sha256:fd6c6c29717724acf9fc1847c4515d57e4dc12762452457b9cb37461f30a81bb +grpcio==1.55.0 \ + --hash=sha256:054b7164b25712ec71339e139875a66708a2ab09be36ac75e73b2d337ab2dc1b \ + --hash=sha256:0d3d5c644d523dee82ffcc44ad50cd66e3bf66e7fa60ad3cdb1eb868228e4ab0 \ + --hash=sha256:1041cad23f00943d8889ad15427d87bbdacbbe2df5cec951c314f2f3967d4691 \ + --hash=sha256:10af4774da9c0665a1bf519333694ac40d72d83cb514534b99db0a5e3d5c3593 \ + --hash=sha256:1173a05117798aca4834d3edd504e6adc25ae9967df0f44b91a612884fb2707a \ + --hash=sha256:157f5615c7b5d0968727472f6394dee01555ef4246d2f2cfb6555be857936d74 \ + --hash=sha256:1982c99c7091d1b7e3e78b1173097f705feef233e253a27e99746b11815ac897 \ + --hash=sha256:2663741acc117370fd53336267cfb24c965e9d3ea1e4933a3e4411712d3091fb \ + --hash=sha256:29ab0e879b1585be41cfbb02faed67913700ced8015da4763f1f0bdd7dfb4ab7 \ + --hash=sha256:2d25d7fcb528a40578b3d0428d401745fd5c0eeeda81f35ce2f40a10d79afd19 \ + --hash=sha256:322d4ebc37cbc8d8596b1da6055e3e81e8cfd36816ab4b285c1163c3042e6067 \ + --hash=sha256:3ab9bf80c19c91847f45ff32af94c85d282545a62db39d797838244d57831d78 \ + --hash=sha256:4370d2cca37301bcc69453d3dd3c1576d06d6b3e337bfec55b3aab2fe106b25c \ + --hash=sha256:48f6088d898e1e987d761d58dc4cd724e7457a7a86d11561fa95c3b826d025dc \ + --hash=sha256:51b7a27a129f743d68394f94029f88ef3da090fc13776b9dfa3c79c5f4b30525 \ + --hash=sha256:56631cc0bdf86d15ea1599b9697ace65e6b52c6b136d3666bf7769d3d6d087a8 \ + --hash=sha256:60efab181c32e029e0960f238508396dd001ba2064168f8148e6356db093967c \ + --hash=sha256:67c4fda71f92225c5e74fa15bffa6be022c07111f674fe1f234c1ef4c1bb7927 \ + --hash=sha256:6b8dbb151b116825c10f01e5b7b75e14edd0e60736a65311d0d98a4cd0489303 \ + --hash=sha256:70de2b73cf22241173cb21d308786ba4ea443e4c88441a2ce445829aa638dda8 \ + --hash=sha256:74780f570c76feb8e62a8c019b495fea435b60218682fce513ff2c71262c346c \ + --hash=sha256:7b38e028a7bbc97a9ae5e418712452f298618b9d0493390770bf2de785251ae7 \ + --hash=sha256:7b8665da31b5bd701b338a581de7b9631d50b4b7ee67125c2d1dc2228cc119d8 \ + --hash=sha256:7c00263d792a244bef67a8d3b357ccbcdae6341c5961dbee494d8f967f9aee69 \ + --hash=sha256:7c32f87bec58a8a0d4f4d5387bd61a383bd32b2caffb2de3cd579e47490b7e19 \ + --hash=sha256:89107071b5f14af6bbb855183d338a0fa94136bbeb3989c9773c6184e51a95e9 \ + --hash=sha256:8a910fa9b95a286f4bc1879dcf8d5ccb95b5e33bb63323fc4414d157f23afef1 \ + --hash=sha256:8b440ccc434c1ad5874465bfae40c0a27f562ae5f7c5b468b6689bc55e8bf1c1 \ + --hash=sha256:8bd4f4932ef63ed32a725065aebb8585e4118a523d923db896e85c09429a36e6 \ + --hash=sha256:9a11b1dd4b1572e85fba5911309c15980a1ff77c555fad0ecdbe3711ef741908 \ + --hash=sha256:a202dcf0c512292fd7a2154e4044c70400212eaa726685ebf8af105e25693c5a \ + --hash=sha256:a82283d6e0403d3e2e7eebb99cb0d2783e20b6791c8c94bd8d4a4233b58b1ea0 \ + --hash=sha256:ab784204d9923368e0e5877d7795584b9606a51b128ee199ad8b5888d0c66592 \ + --hash=sha256:b1e2b705d524e780998218cf429d30b6ffc54cb6e54812c9597bc5df12dbcb5b \ + --hash=sha256:b2a3b837d5837b9069783026b57aa0ff12e34d3218fdeda3f9c06d3950266d8e \ + --hash=sha256:ba32a8e9bc3eecc6bab6824b905f04c3fdc31659c3e6e06841b774e7cb4410af \ + --hash=sha256:c33dbeecc14f1a413e8af8ae1208cb383b063fa2ff2e1f309b4d3d7739b0927e \ + --hash=sha256:c97cfae0b7a17dc1a0a3e4333f4f46daa114d85f950a67f39cc141b5425182e4 \ + --hash=sha256:ce82d06cdfb8a9292fb857f00bee11a2430e4ac2742e07b46c1a3072d683256a \ + --hash=sha256:d0209fb3cb55c5288a1dec72dcaae2c1b501edceca10d22c0f0baa5e60e2b22c \ + --hash=sha256:d396ec4d520b58f43142958cff071e5ad1c50ac87d29d086a9c6a990a09ea536 \ + --hash=sha256:dad999423b33ad5409e986587593b6062a8260b74ae8fc8162ce231c6b7a929e \ + --hash=sha256:dd15027a171ff93c97f9c704fa120bc5d0691dc7e71ae450e2ecade1a2799b53 \ + --hash=sha256:ee0de9cb6813704969e53743e0969fd95225ff24bd686c89ed12a18147f6566c \ + --hash=sha256:fe78365c64b2c7470d31c4941e10c6654042bcbb53897b9b1e2c96d6d0da9ef9 # via # -r requirements.in # grpcio-tools -grpcio-tools==1.54.2 \ - --hash=sha256:0239b929eb8b3b30b2397eef3b9abb245087754d77c3721e3be43c44796de87d \ - --hash=sha256:0ab1b323905d449298523db5d34fa5bf5fffd645bd872b25598e2f8a01f0ea39 \ - --hash=sha256:0de05c7698c655e9a240dc34ae91d6017b93143ac89e5b20046d7ca3bd09c27c \ - --hash=sha256:0f952c8a5c47e9204fe8959f7e9add149e660f6579d67cf65024c32736d34caf \ - --hash=sha256:10dd41862f579d185c60f629b5ee89103e216f63b576079d258d974d980bad87 \ - --hash=sha256:11939c9a8a39bd4815c7e88cb2fee48e1948775b59dbb06de8fcae5991e84f9e \ - --hash=sha256:129de5579f95d6a55dde185f188b4cbe19d1e2f1471425431d9930c31d300d70 \ - --hash=sha256:1b8ee3099c51ce987fa8a08e6b93fc342b10228415dd96b5c0caa0387f636a6f \ - --hash=sha256:21b1467e31e44429d2a78b50135c9cdbd4b8f6d3b5cd548bc98985d3bdc352d0 \ - --hash=sha256:21b9d2dee80f3f77e4097252e7f0db89772335a7300b72ab3d2e5c280872b1db \ - --hash=sha256:27671c68c7e0e3c5ff9967f5500799f65a04e7b153b8ce10243c87c43199039d \ - --hash=sha256:2b96f5f17d3156058be247fd25b062b4768138665694c00b056659618b8fb418 \ - --hash=sha256:30a49b8b168aced2a4ff40959e6c4383ad6cfd7a20839a47a215e9837eb722dc \ - --hash=sha256:3237149beec39e897fd62cef4aa1e1cd9422d7a95661d24bd0a79200b167e730 \ - --hash=sha256:37393ef90674964175923afe3859fc5a208e1ece565f642b4f76a8c0224a0993 \ - --hash=sha256:39fd530cfdf58dc05125775cc233b05554d553d27478f14ae5fd8a6306f0cb28 \ - --hash=sha256:3bb9ec4aea0f2b3006fb002fa59e5c10f92b48fc374619fbffd14d2b0e388c3e \ - --hash=sha256:49c2846dcc4803476e839d8bd4db8845e928f19130e0ea86121f2d1f43d2b452 \ - --hash=sha256:4abfc1892380abe6cef381eab86f9350cbd703bfe5d834095aa66fd91c886b6d \ - --hash=sha256:4f285f8ef3de422717a36bd372239ae778b8cc112ce780ca3c7fe266dadc49fb \ - --hash=sha256:503ef1351c62fb1d6747eaf74932b609d8fdd4345b3591ef910adef8fa9969d0 \ - --hash=sha256:5ef30c2dbc63c1e0a462423ca4f95001814d26ef4fe66208e53fcf220ea3b717 \ - --hash=sha256:6037f123905dc0141f7c8383ca616ef0195e79cd3b4d82faaee789d4045e891b \ - --hash=sha256:72d15de4c4b6a764a76c4ae69d99c35f7a0751223688c3f7e62dfa95eb4f61be \ - --hash=sha256:7b24fbab9e7598518ce4549e066df00aab79c2bf9bedcdde23fb5ef6a3cf532f \ - --hash=sha256:7baa210c20f71a242d9ae0e02734628f6948e8bee3bf538647894af427d28800 \ - --hash=sha256:7d7e6e8d62967b3f037f952620cb7381cc39a4bd31790c75fcfba56cc975d70b \ - --hash=sha256:7f4624ef2e76a3a5313c4e61a81be38bcc16b59a68a85d30758b84cd2102b161 \ - --hash=sha256:8742122782953d2fd038f0a199f047a24e941cc9718b1aac90876dbdb7167739 \ - --hash=sha256:8e4531267736d88fde1022b36dd42ed8163e3575bcbd12bfed96662872aa93fe \ - --hash=sha256:8e4c5a48f7b2e8798ce381498ee7b9a83c65b87ae66ee5022387394e5eb51771 \ - --hash=sha256:9acf443dcf6f68fbea3b7fb519e1716e014db1a561939f5aecc4abda74e4015d \ - --hash=sha256:a0b7049814442f918b522d66b1d015286afbeb9e6d141af54bbfafe31710a3c8 \ - --hash=sha256:a3ce0b98fb581c471424d2cda45120f57658ed97677c6fec4d6decf5d7c1b976 \ - --hash=sha256:b80585e06c4f0082327eb5c9ad96fbdb2b0e7c14971ea5099fe78c22f4608451 \ - --hash=sha256:b82ca472db9c914c44e39a41e9e8bd3ed724523dd7aff5ce37592b8d16920ed9 \ - --hash=sha256:c4128c01cd6f5ea8f7c2db405dbfd8582cd967d36e6fa0952565436633b0e591 \ - --hash=sha256:d512de051342a576bb89777476d13c5266d9334cf4badb6468aed9dc8f5bdec1 \ - --hash=sha256:df079479fb1b9e488334312e35ebbf30cbf5ecad6c56599f1a961800b33ab7c1 \ - --hash=sha256:e11c2c2aee53f340992e8e4d6a59172cbbbd0193f1351de98c4f810a5041d5ca \ - --hash=sha256:e3d0e5188ff8dbaddac2ee44731d36f09c4eccd3eac7328e547862c44f75cacd \ - --hash=sha256:e543f457935ba7b763b121f1bf893974393b4d30065042f947f85a8d81081b80 \ - --hash=sha256:e5c7292dd899ad8fa09a2be96719648cee37b17909fe8c12007e3bff58ebee61 \ - --hash=sha256:f39d8e8806b8857fb473ca6a9c7bd800b0673dfdb7283ff569af0345a222f32c \ - --hash=sha256:f6787d07fdab31a32c433c1ba34883dea6559d8a3fbe08fb93d834ca34136b71 +grpcio-tools==1.55.0 \ + --hash=sha256:053bbdfb74f76511db47e1e18a1962432468ae9f356cc00f15d1f1353eaf32a1 \ + --hash=sha256:07c23ed940e046c9dd471bc870eb5db4d93e518f90011cf9aebf8bfda6cd68a5 \ + --hash=sha256:0dead7fb37bfe7c7eb8294143015645297f4affa683783b8bbf2cd4d7f7036d4 \ + --hash=sha256:2ba87592f2cd689e127cd4fce76ec23b19562e230fa41ea089af8b15120aea78 \ + --hash=sha256:2eacb0b1e8e5cfd0b40e12e62bd5adebbbae8c73cdf6e04fad9ddd37e32d98a4 \ + --hash=sha256:350303ef3a2b25ed1b90e42764923e40b664d9f10840f7a0f06117c4dc414aff \ + --hash=sha256:36745762689df18f83273a9a004848897793f63a10a30acd18acb2d170c663a9 \ + --hash=sha256:3724e48c3db499b2d212c5a89d7cc4b49ccd476dc26bf8a9b855d59b6cc00796 \ + --hash=sha256:41005002cbfa0ad39972486bde8116b2a042804119e5b998086a4dc26e625d6a \ + --hash=sha256:416a8b61ed4223715755b4519858419e1f4653d64572a28029f2ac63e677e3d2 \ + --hash=sha256:4580df5a9867f7bcbb828a5485c030ca232c1578e615caf751333c7a7980d838 \ + --hash=sha256:4a41130c97775bb0dfaf87e34b492f2eca448d02d213410005544c534f3f7c26 \ + --hash=sha256:4a6db1494955d2a5531575b5fcdc08094ea4a331a94b9cdf864d78e801c5fa23 \ + --hash=sha256:4dea66623548b52429fb03495f2c76f4c993bf9a56267c6b3d0fb62573dd52c2 \ + --hash=sha256:51a1ccab6f67edd1a3768a75ac495907fe0cd6d6617af2f9f2033400b5858a11 \ + --hash=sha256:52e34e9b6496f4c1e3289ada7bc41d759e4a8ec5f2679e187067cab8532ffbf4 \ + --hash=sha256:632364ffbd4fb0338cb03c590a2ddc258d9cd59bff0bf4199c02e3e581f802d7 \ + --hash=sha256:734ede84d613b044f72e7d9c190bd2388ebb83e85bcd3aa75afa9f30c096dbc7 \ + --hash=sha256:73ef9e0e0ee8ab055a621e7b42e5fb32753b0b6607900887dba6d55df5947be8 \ + --hash=sha256:7f084cd619cf66d8620a99f8586018f19b918ffb2ddb92d3e5943a06038bead8 \ + --hash=sha256:87152893c7c3bef58a6a9b548db290aa318cc314c700ae7d7f2970aa567f875e \ + --hash=sha256:87dbc98528f88faa3f8f56a47d41dc6fda382928abbdb5537b5444eb8bb1ac1b \ + --hash=sha256:89f6ed47415a22568bbf4a62336bfde7cafb53492a5a9f33a22243411b00f443 \ + --hash=sha256:8e59fd4a58688117cb5128d7785909d45a6e5f8212efeb65b6fd74bb9b8b9512 \ + --hash=sha256:9395c4fdee6b22137e878ebd461444854a3cd9c6c260c43f4a4c4a4023700129 \ + --hash=sha256:946266cbd639847548c9f97e38da0682746c2eadea790ceb4320b1f85387bd6d \ + --hash=sha256:95428be2db12412ff23f0969386fc51d2aa6de38a57cc54c57363352f1d7a832 \ + --hash=sha256:98ff3129ff7134a95f4d2857663625771f6838ac44b7799c34259b7ea87ebe5c \ + --hash=sha256:9933a1f18f780c42214b126ef27e273b54c9c28de3fae5b1887b413ceb374c4c \ + --hash=sha256:a61567f27661ab9327dc060615dc22d2bde80c56731f1e856008f1fd8ee83311 \ + --hash=sha256:ab64f9d6f5e3636ae6298e2d795225daa83aacb057105943728ed50a8a582237 \ + --hash=sha256:b00a67a1230968c1a0424915922d17983d824ed45e8db06f9f17be6d5571faee \ + --hash=sha256:b131b2bbf25198d9e508dfa588cb215580629b514e293d5609eeee98c8941dbc \ + --hash=sha256:b197de69ca0431b718ffa47b32a733703fa5503da49f49dd315c866842b6cfbd \ + --hash=sha256:b674de79571357c5381bc5fa12e3b89fefef74c164ab9077ed22158c3529aa8e \ + --hash=sha256:bc23034b1959d6cda27347b2207fee0fb0fb0aff242da228a6b7c1a18fce4116 \ + --hash=sha256:bcf5e1858137cbe13ef10a7931a7edc745c77f8b39f032f52072443f0dd681e1 \ + --hash=sha256:c3c7b7eb89f963b87922ecc0c0ab2485fff05997ada66dffd53597b507a83bc8 \ + --hash=sha256:c7a18bd5f994b7911d3e70e0abb05bea9f1b084a1725d404a8e231bf9727613b \ + --hash=sha256:cfc82c11ce51de6ed5836fbafbc188d9eac0737abc116978f151c40271783817 \ + --hash=sha256:d796f5d7cea260ef2afed12d13ec34b13e09dd74d7f292d7428c506fa8c17a74 \ + --hash=sha256:e76f35e5e65600a75c3547855e8c9ab935c55c473f5409e7746cca8f1f7c8f4a \ + --hash=sha256:f87d99aa3826aa20c3b89493984cf278f4c9d20b3418534a46239c804fee506c \ + --hash=sha256:f900bce944b5777effecb9078e5fd3a224e42b1ca33c7546c3d043f9ef9eb4e8 \ + --hash=sha256:fbbe2bee4af93c03ba064d40199dbf38067d2aa6ae98dfa0687a08ee980ebfd5 # via -r requirements.in idna==3.2 \ --hash=sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a \ From 575f6967087cb181b5368bfd1549952b758b02cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 09:09:47 +0100 Subject: [PATCH 040/228] build(deps): bump postgres from `8d45935` to `b115fe7` in /examples/shared/postgres (#27559) build(deps): bump postgres in /examples/shared/postgres Bumps postgres from `8d45935` to `b115fe7`. --- updated-dependencies: - dependency-name: postgres dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/postgres/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/postgres/Dockerfile b/examples/shared/postgres/Dockerfile index a4ab85b4bc82..84b2d96a722c 100644 --- a/examples/shared/postgres/Dockerfile +++ b/examples/shared/postgres/Dockerfile @@ -1,3 +1,3 @@ -FROM postgres:latest@sha256:8d45935fb783e72c871072e9eb72ee8c817a9eaf25c405b0e62526b14191368d +FROM postgres:latest@sha256:b115fe7743919fff0b96f19405ed350017ef9333b3760fc0cc885713eb07f565 COPY docker-healthcheck.sh /usr/local/bin/ HEALTHCHECK CMD ["docker-healthcheck.sh"] From 599f675495c054ad5c2e983e268e368c9871ba19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 09:11:36 +0100 Subject: [PATCH 041/228] build(deps): bump redis from `ea30bef` to `47e4e43` in /examples/redis (#27560) Bumps redis from `ea30bef` to `47e4e43`. --- updated-dependencies: - dependency-name: redis dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/redis/Dockerfile-redis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/redis/Dockerfile-redis b/examples/redis/Dockerfile-redis index f5847517ea98..e05ddfb56f9f 100644 --- a/examples/redis/Dockerfile-redis +++ b/examples/redis/Dockerfile-redis @@ -1 +1 @@ -FROM redis@sha256:ea30bef6a1424d032295b90db20a869fc8db76331091543b7a80175cede7d887 +FROM redis@sha256:47e4e4395af10811cfd893e3e2dcfdf13cf45b0d4feeeafc92842d6902656ede From fe92962b45df3c4346382adf1439713a869ea1bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 09:15:45 +0100 Subject: [PATCH 042/228] build(deps): bump nginx from `480868e` to `a2f6ffd` in /examples/local_ratelimit (#27561) build(deps): bump nginx in /examples/local_ratelimit Bumps nginx from `480868e` to `a2f6ffd`. --- updated-dependencies: - dependency-name: nginx dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/local_ratelimit/Dockerfile-nginx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/local_ratelimit/Dockerfile-nginx b/examples/local_ratelimit/Dockerfile-nginx index 46b5fa67f3a1..d48af7252182 100644 --- a/examples/local_ratelimit/Dockerfile-nginx +++ b/examples/local_ratelimit/Dockerfile-nginx @@ -1 +1 @@ -FROM nginx@sha256:480868e8c8c797794257e2abd88d0f9a8809b2fe956cbfbc05dcc0bca1f7cd43 +FROM nginx@sha256:a2f6ffddd272625464710d6189f1bf5d02e068392facae344762a512209e74d5 From 6550e3c4361a28a1eac5055db3e5db329026171c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 09:16:46 +0100 Subject: [PATCH 043/228] build(deps): bump debian from `f4da3f9` to `7606bef` in /examples/shared/websocket (#27563) build(deps): bump debian in /examples/shared/websocket Bumps debian from `f4da3f9` to `7606bef`. --- updated-dependencies: - dependency-name: debian dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/websocket/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/websocket/Dockerfile b/examples/shared/websocket/Dockerfile index e070c5148ea0..3e047c58941f 100644 --- a/examples/shared/websocket/Dockerfile +++ b/examples/shared/websocket/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bullseye-slim@sha256:f4da3f9b18fc242b739807a0fb3e77747f644f2fb3f67f4403fafce2286b431a as websocket-base +FROM debian:bullseye-slim@sha256:7606bef5684b393434f06a50a3d1a09808fee5a0240d37da5d181b1b121e7637 as websocket-base ENV DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ From 49dccb3acd48a5efee3f74c5551d4fdc7bb92b63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 09:21:07 +0100 Subject: [PATCH 044/228] build(deps): bump python from `551c952` to `6c0b067` in /examples/shared/python (#27564) build(deps): bump python in /examples/shared/python Bumps python from `551c952` to `6c0b067`. --- updated-dependencies: - dependency-name: python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/python/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/python/Dockerfile b/examples/shared/python/Dockerfile index cc94f641fbff..8a87913da3aa 100644 --- a/examples/shared/python/Dockerfile +++ b/examples/shared/python/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11.3-slim-bullseye@sha256:551c9529e77896518ac5693d7e98ee5e12051d625de450ac2a68da1eae15ec87 as python-base +FROM python:3.11.3-slim-bullseye@sha256:6c0b067294c78ee6538cc9d6163fd1653797d0f4fd567e55703a5365c7757138 as python-base RUN rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache ARG PYTHON_REQUIREMENTS_FILE=aiohttp/requirements.txt From ff1546da85f89bf7d0bd75467a5deafda58c799e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 09:21:37 +0100 Subject: [PATCH 045/228] build(deps): bump node from `5138ded` to `95a950e` in /examples/shared/node (#27565) build(deps): bump node in /examples/shared/node Bumps node from `5138ded` to `95a950e`. --- updated-dependencies: - dependency-name: node dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/node/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/node/Dockerfile b/examples/shared/node/Dockerfile index 7cd02355882d..9ef656782642 100644 --- a/examples/shared/node/Dockerfile +++ b/examples/shared/node/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.2-bullseye-slim@sha256:5138ded35380c7e55b7898a5c3666009334aa4af416571060d37347242e1812f as node-base +FROM node:20.2-bullseye-slim@sha256:95a950ec61796f4c00f6b208cb51000b8bd127ee53b0c1c52f2539a5ab66f8ef as node-base FROM node-base as node-http-auth From c0dce839eda044eaccf219896809a0d8bbd1bb53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 10:19:09 +0100 Subject: [PATCH 046/228] build(deps): bump requests from 2.30.0 to 2.31.0 in /mobile/docs (#27554) Bumps [requests](https://github.com/psf/requests) from 2.30.0 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.30.0...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- mobile/docs/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mobile/docs/requirements.txt b/mobile/docs/requirements.txt index 4118d6bee302..a5feef288926 100644 --- a/mobile/docs/requirements.txt +++ b/mobile/docs/requirements.txt @@ -158,9 +158,9 @@ pyparsing==3.0.9 \ pytz==2023.3 \ --hash=sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588 \ --hash=sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb -requests==2.30.0 \ - --hash=sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294 \ - --hash=sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4 +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 six==1.16.0 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 From 04c42f8ce23880aaed99956caf00853aa7b8199e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 11:20:12 +0100 Subject: [PATCH 047/228] build(deps): bump requests from 2.30.0 to 2.31.0 in /tools/base (#27566) Bumps [requests](https://github.com/psf/requests) from 2.30.0 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.30.0...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index ee3068fd0a65..69409c5bac86 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1147,9 +1147,9 @@ pyyaml==6.0 \ # aio-core # envoy-base-utils # yamllint -requests==2.30.0 \ - --hash=sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294 \ - --hash=sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4 +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 # via # google-api-core # google-auth From 72c2ec85ecb1e0dc5e71badd8a921304cfcda2ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 11:20:51 +0100 Subject: [PATCH 048/228] build(deps): bump debian from `f4da3f9` to `7606bef` in /examples/shared/golang (#27562) build(deps): bump debian in /examples/shared/golang Bumps debian from `f4da3f9` to `7606bef`. --- updated-dependencies: - dependency-name: debian dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/golang/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/golang/Dockerfile b/examples/shared/golang/Dockerfile index feaafc04b9b4..c439916f78ea 100644 --- a/examples/shared/golang/Dockerfile +++ b/examples/shared/golang/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bullseye-slim@sha256:f4da3f9b18fc242b739807a0fb3e77747f644f2fb3f67f4403fafce2286b431a as os-base +FROM debian:bullseye-slim@sha256:7606bef5684b393434f06a50a3d1a09808fee5a0240d37da5d181b1b121e7637 as os-base RUN rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache From a23fa16e0dd7085cb5acd899fe1bc5ece182a399 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 11:22:19 +0100 Subject: [PATCH 049/228] build(deps): bump requests from 2.30.0 to 2.31.0 in /examples/grpc-bridge/client (#27555) build(deps): bump requests in /examples/grpc-bridge/client Bumps [requests](https://github.com/psf/requests) from 2.30.0 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.30.0...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/grpc-bridge/client/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/grpc-bridge/client/requirements.txt b/examples/grpc-bridge/client/requirements.txt index 4550459a94de..41ca3dbc8d03 100644 --- a/examples/grpc-bridge/client/requirements.txt +++ b/examples/grpc-bridge/client/requirements.txt @@ -129,9 +129,9 @@ protobuf==4.23.1 \ # via # -r requirements.in # grpcio-tools -requests==2.30.0 \ - --hash=sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294 \ - --hash=sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4 +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 # via -r requirements.in urllib3==1.26.7 \ --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ From b201b68e8cff31b9e85c1bb47cf84d24a9d2ab25 Mon Sep 17 00:00:00 2001 From: "Dr. Andre Vehreschild" <101638173+vehre-x41@users.noreply.github.com> Date: Tue, 23 May 2023 15:21:45 +0200 Subject: [PATCH 050/228] [fuzz] Only add filters that are allowlisted (#27373) Signed-off-by: Andre Vehreschild Co-authored-by: Ryan Northey --- source/docs/network_filter_fuzzing.md | 58 ++++++------------- source/extensions/all_extensions.bzl | 12 +--- .../filters/network/common/fuzz/BUILD | 37 +++++++++--- .../common/fuzz/uber_per_readfilter.cc | 27 ++------- .../common/fuzz/uber_per_writefilter.cc | 20 ++----- tools/base/requirements.in | 2 +- tools/base/requirements.txt | 6 +- 7 files changed, 64 insertions(+), 98 deletions(-) diff --git a/source/docs/network_filter_fuzzing.md b/source/docs/network_filter_fuzzing.md index f23354423bcd..590b4a94cd87 100644 --- a/source/docs/network_filter_fuzzing.md +++ b/source/docs/network_filter_fuzzing.md @@ -1,55 +1,31 @@ # Generic network-level filter fuzzers overview -Network filters need to be fuzzed. Filters come in two flavors, each with their own fuzzer. Read filters should be added into the [Generic ReadFilter Fuzzer](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/network_readfilter_fuzz_test.cc). Write Filters should added into the [Generic WriteFilter Fuzzer](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/network_writefilter_fuzz_test.cc). Some filters are both raed and write filters: They should be added into both fuzzers. +Network filters need to be fuzzed. Filters come in two flavors, each with their own fuzzer. Read filters should be added into the [Generic ReadFilter Fuzzer](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/network_readfilter_fuzz_test.cc). Write Filters should added into the [Generic WriteFilter Fuzzer](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/network_writefilter_fuzz_test.cc). Some filters are both read and write filters: They should be added into both fuzzers. Before adding the new filter into the fuzzers, please make sure the filter is designed to accept untrusted inputs, or ready to be hardened to accept untrusted inputs. # Add a new ReadFilter into Generic Readfilter Fuzzer -## Step1. Make sure the filter can be linked into the fuzzer -There are two ways to link it into the fuzzer. -* [Recommended] In the file [extensions_build_config.bzl](https://github.com/envoyproxy/envoy/blob/main/source/extensions/extensions_build_config.bzl), the name of the filter should have a prefix `envoy.filters.network`. If it has such a prefix, the filter will be automatically linked into Generic ReadFilter Fuzzer. -* [Not recommended]If for some reasons the filter's name doesn't have such a prefix, the config of the filter must be added into the `deps` field of `network_readfilter_fuzz_test` module in the file [BUILD](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/BUILD). -### Step2. Add the filter name into supported_filter_names -In [uber_per_readfilter.cc](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/uber_per_readfilter.cc), add the filter name into the vector `supported_filter_names` in method `UberFilterFuzzer::filterNames()`. +Only one step is needed to add a new filter to the fuzzer: +* In the file [BUILD](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/BUILD) the name of the filter has to be added to the `READFILTER_FUZZ_FILTERS` list. The fuzz test will figure the available filters from the factories. ``` -const std::vector supported_filter_names = { -... -NetworkFilterNames::get().ExtAuthorization, NetworkFilterNames::get().TheNewFilterCreatedByYou, -... -}; +READFILTER_FUZZ_FILTERS = [ + "envoy.filters.network.client_ssl_auth", + "envoy.filters.network.ext_authz", + "envoy.filters.network.envoy_mobile_http_connection_manager", + # A dedicated http_connection_manager fuzzer can be found in + # test/common/http/conn_manager_impl_fuzz_test.cc + "envoy.filters.network.http_connection_manager", + "envoy.filters.network.local_ratelimit", + "envoy.filters.network.rbac", + # TODO(asraa): Remove when fuzzer sets up connections for TcpProxy properly. + # "envoy.filters.network.tcp_proxy", + "the_new_filter_created_by_you", // <---Add the filter name here +] ``` # Add a new WriteFilter into Generic Writefilter Fuzzer -## Step 1. Make sure the filter can be linked into the fuzzer -For WriteFilter, the config of the filter must be added into the `deps` field of `network_writefilter_fuzz_test` module in the file [BUILD](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/BUILD). -``` -envoy_cc_fuzz_test( - name = "network_writefilter_fuzz_test", - srcs = ["network_writefilter_fuzz_test.cc"], - corpus = "network_writefilter_corpus", - # All Envoy network filters must be linked to the test in order for the fuzzer to pick - # these up via the NamedNetworkFilterConfigFactory. - deps = [ - ":uber_writefilter_lib", - "//source/common/config:utility_lib", - "//source/extensions/filters/network/mongo_proxy:config", - "//contrib/mysql_proxy/filters/network/source:config", - "//source/extensions/filters/network/zookeeper_proxy:config", - "//source/extensions/filters/network/the_new_filter_created_by_you:config", // <---Add the filter config module here - "//test/config:utility_lib", - ], -) -``` -## Step 2. Add the filter name into supported_filter_names -In [uber_per_writefilter.cc](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc), add the filter name into the vector `supported_filter_names` in method `UberWriteFilterFuzzer::filterNames()`. -``` -const std::vector supported_filter_names = { - ... - NetworkFilterNames::get().ExtAuthorization, NetworkFilterNames::get().TheNewFilterCreatedByYou, - ... - }; -``` +For WriteFilter, the name of the filter must be added into the `WRITEFILTER_FUZZ_FILTERS` list of the file [BUILD](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/BUILD). # Add test cases into corpus Good test cases can provide good examples for fuzzers to find more paths in the code, increase the coverage and help find bugs more efficiently. diff --git a/source/extensions/all_extensions.bzl b/source/extensions/all_extensions.bzl index c2c39bc3d6d4..1a18c2cf44e1 100644 --- a/source/extensions/all_extensions.bzl +++ b/source/extensions/all_extensions.bzl @@ -50,14 +50,8 @@ def envoy_all_http_filters(): return {_selected_extension_target(v): True for k, v in all_extensions.items() if (k.startswith(_http_filter_prefix) or k.startswith(_upstream_http_filter_prefix))}.keys() -# All network-layer filters are extensions with names that have the following prefix. -_network_filter_prefix = "envoy.filters.network" - -# All thrift filters are extensions with names that have the following prefix. -_thrift_filter_prefix = "envoy.filters.thrift" - -# Return all network-layer filter extensions to be compiled into network-layer filter generic fuzzer. -def envoy_all_network_filters(): +# Return 'selected' network-layer filter extensions to be compiled into network-layer filter generic fuzzer. +def envoy_filters_from_selected(selected): all_extensions = dicts.add(_required_extensions, EXTENSIONS) - return [_selected_extension_target(v) for k, v in all_extensions.items() if (k.startswith(_network_filter_prefix) or k.startswith(_thrift_filter_prefix))] + return [_selected_extension_target(v) for k, v in all_extensions.items() if (k in selected)] diff --git a/test/extensions/filters/network/common/fuzz/BUILD b/test/extensions/filters/network/common/fuzz/BUILD index 7197944a15b2..6778bee09fd0 100644 --- a/test/extensions/filters/network/common/fuzz/BUILD +++ b/test/extensions/filters/network/common/fuzz/BUILD @@ -7,7 +7,7 @@ load( ) load( "//source/extensions:all_extensions.bzl", - "envoy_all_network_filters", + "envoy_filters_from_selected", ) licenses(["notice"]) # Apache 2 @@ -36,6 +36,22 @@ envoy_proto_library( ], ) +# The filters to be fuzzed by the network_readfilter_fuzz_test. Prefer to add only stable filters, +# that do not have a dedicated fuzzer to them. +READFILTER_FUZZ_FILTERS = [ + "envoy.filters.network.client_ssl_auth", + "envoy.filters.network.ext_authz", + "envoy.filters.network.envoy_mobile_http_connection_manager", + # A dedicated http_connection_manager fuzzer can be found in + # test/common/http/conn_manager_impl_fuzz_test.cc + "envoy.filters.network.http_connection_manager", + "envoy.filters.network.local_ratelimit", + "envoy.filters.network.ratelimit", + "envoy.filters.network.rbac", + # TODO(asraa): Remove when fuzzer sets up connections for TcpProxy properly. + # "envoy.filters.network.tcp_proxy", +] + envoy_cc_test_library( name = "vig_anymap_ext_lib", srcs = ["validated_input_generator_any_map_extensions.cc"], @@ -85,17 +101,26 @@ envoy_cc_fuzz_test( srcs = ["network_readfilter_fuzz_test.cc"], corpus = "network_readfilter_corpus", dictionaries = ["network_readfilter_fuzz_test.dict"], - # All Envoy network filters must be linked to the test in order for the fuzzer to pick - # these up via the NamedNetworkFilterConfigFactory. deps = [ ":uber_readfilter_lib", ":vig_anymap_ext_lib", "//source/common/config:utility_lib", "//test/config:utility_lib", "//test/test_common:test_runtime_lib", - ] + envoy_all_network_filters(), + ] + envoy_filters_from_selected(READFILTER_FUZZ_FILTERS), ) +# The filters to be fuzzed by the network_writefilter_fuzz_test. Prefer to add only stable filters, +# that do not have a dedicated fuzzer to them. +WRITEFILTER_FUZZ_FILTERS = [ + "envoy.filters.network.zookeeper_proxy", + "envoy.filters.network.kafka_broker", + "envoy.filters.network.mongo_proxy", + "envoy.filters.network.mysql_proxy", + # TODO(jianwendong) Add "NetworkFilterNames::get().Postgres" after it + # supports untrusted data. +] + envoy_cc_test_library( name = "uber_writefilter_lib", srcs = [ @@ -123,8 +148,6 @@ envoy_cc_fuzz_test( ":uber_writefilter_lib", ":vig_anymap_ext_lib", "//source/common/config:utility_lib", - "//source/extensions/filters/network/mongo_proxy:config", - "//source/extensions/filters/network/zookeeper_proxy:config", "//test/config:utility_lib", - ], + ] + envoy_filters_from_selected(WRITEFILTER_FUZZ_FILTERS), ) diff --git a/test/extensions/filters/network/common/fuzz/uber_per_readfilter.cc b/test/extensions/filters/network/common/fuzz/uber_per_readfilter.cc index 0b52349bda91..f697e8964060 100644 --- a/test/extensions/filters/network/common/fuzz/uber_per_readfilter.cc +++ b/test/extensions/filters/network/common/fuzz/uber_per_readfilter.cc @@ -21,28 +21,11 @@ std::vector UberFilterFuzzer::filterNames() { // traffic. static std::vector filter_names; if (filter_names.empty()) { - const auto factories = Registry::FactoryRegistry< - Server::Configuration::NamedNetworkFilterConfigFactory>::factories(); - const std::vector supported_filter_names = { - NetworkFilterNames::get().ClientSslAuth, NetworkFilterNames::get().ExtAuthorization, - NetworkFilterNames::get().EnvoyMobileHttpConnectionManager, - // A dedicated http_connection_manager fuzzer can be found in - // test/common/http/conn_manager_impl_fuzz_test.cc - NetworkFilterNames::get().HttpConnectionManager, NetworkFilterNames::get().LocalRateLimit, - NetworkFilterNames::get().RateLimit, NetworkFilterNames::get().Rbac, - // TODO(asraa): Remove when fuzzer sets up connections for TcpProxy properly. - // NetworkFilterNames::get().TcpProxy, - }; - // Check whether each filter is loaded into Envoy. - // Some customers build Envoy without some filters. When they run fuzzing, the use of a filter - // that does not exist will cause fatal errors. - for (auto& filter_name : supported_filter_names) { - if (factories.contains(filter_name)) { - filter_names.push_back(filter_name); - } else { - ENVOY_LOG_MISC(debug, "Filter name not found in the factory: {}", filter_name); - } - } + // Only use the names of the filters that are compiled into envoy. The build system takes care + // about reducing these to the allowed set. + // See test/extensions/filters/network/common/fuzz/BUILD for more information. + filter_names = Registry::FactoryRegistry< + Server::Configuration::NamedNetworkFilterConfigFactory>::registeredNames(); } return filter_names; } diff --git a/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc b/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc index 24babee1697d..696935566fb4 100644 --- a/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc +++ b/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc @@ -10,21 +10,11 @@ std::vector UberWriteFilterFuzzer::filterNames() { // Will extend to cover other network filters one by one. static std::vector filter_names; if (filter_names.empty()) { - const auto factories = Registry::FactoryRegistry< - Server::Configuration::NamedNetworkFilterConfigFactory>::factories(); - const std::vector supported_filter_names = { - NetworkFilterNames::get().ZooKeeperProxy, NetworkFilterNames::get().KafkaBroker, - NetworkFilterNames::get().MongoProxy, NetworkFilterNames::get().MySQLProxy - // TODO(jianwendong) Add "NetworkFilterNames::get().Postgres" after it supports untrusted - // data. - }; - for (auto& filter_name : supported_filter_names) { - if (factories.contains(filter_name)) { - filter_names.push_back(filter_name); - } else { - ENVOY_LOG_MISC(debug, "Filter name not found in the factory: {}", filter_name); - } - } + // Only use the names of the filters that are compiled into envoy. The build system takes care + // about reducing these to the allowed set. + // See test/extensions/filters/network/common/fuzz/BUILD for more information. + filter_names = Registry::FactoryRegistry< + Server::Configuration::NamedNetworkFilterConfigFactory>::registeredNames(); } return filter_names; } diff --git a/tools/base/requirements.in b/tools/base/requirements.in index b10adff378ce..68c563b40516 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -6,7 +6,7 @@ colorama coloredlogs dependatool>=0.2.2 envoy.base.utils>=0.4.7 -envoy.code.check>=0.4.1 +envoy.code.check>=0.5.0 envoy.dependency.check>=0.1.7 envoy.distribution.release>=0.0.9 envoy.distribution.repo>=0.0.8 diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 69409c5bac86..8ad6e2ebff2d 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -434,9 +434,9 @@ envoy-base-utils==0.4.10 \ # envoy-docs-sphinx-runner # envoy-github-release # envoy-gpg-sign -envoy-code-check==0.4.1 \ - --hash=sha256:3b4d3c9f8f80d47edd0bedd4df2bc7f8a90fcb37cf4142f4882703f4141a1b01 \ - --hash=sha256:a3806deee1565d80488e3c7758e54b9a19025fbe4e91378969f6be342f083eda +envoy-code-check==0.5.0 \ + --hash=sha256:326ad3f188705fe7d0652bc707f7bc5eac190ff5c68d21f2fc5ebebc3b100e45 \ + --hash=sha256:46314932f38cab7caf02ff0da1d7a961f94b4ceedb11e19d0552c36481a041e6 # via -r requirements.in envoy-dependency-check==0.1.8 \ --hash=sha256:ac9820e446bb44e05121e5c93c210f40ca37076580b0d082da2c63e7784c338a \ From fc5361a35bcfeeae8603e5d3957fefddf9d68a4d Mon Sep 17 00:00:00 2001 From: danzh Date: Tue, 23 May 2023 09:45:26 -0400 Subject: [PATCH 051/228] test: fix flaky test DownstreamProtocolIntegrationTest.HandleDownstreamSocketFail (#27546) The test manually introduces EBADF error on the connection between Envoy and the test client. However, the IoHandleMatcher doesn't distinguish UDP socket from TCP. If the upstream HTTP/3 connection gets the same port number as downstream TCP connection, the EBADF error will be applied to the wrong connection. Enforce IoHandleMatcher to match socket type. Risk Level: low, test only Testing: existing tests Docs Changes: N/A Release Notes: N/A Partially Fix #27490 Signed-off-by: Dan Zhang --- .../buffer_accounting_integration_test.cc | 3 ++- test/integration/filters/test_socket_interface.h | 10 +++++++++- test/integration/http2_flood_integration_test.cc | 4 +++- test/integration/multiplexed_integration_test.cc | 8 +++++++- test/integration/protocol_integration_test.cc | 8 ++++++-- test/integration/shadow_policy_integration_test.cc | 3 ++- test/integration/socket_interface_swap.cc | 3 ++- test/integration/socket_interface_swap.h | 12 ++++++++---- 8 files changed, 39 insertions(+), 12 deletions(-) diff --git a/test/integration/buffer_accounting_integration_test.cc b/test/integration/buffer_accounting_integration_test.cc index 98034bee1639..f9fe4ff3b8f6 100644 --- a/test/integration/buffer_accounting_integration_test.cc +++ b/test/integration/buffer_accounting_integration_test.cc @@ -120,7 +120,8 @@ class Http2BufferWatermarksTest } Http2BufferWatermarksTest() - : HttpIntegrationTest( + : SocketInterfaceSwap(Network::Socket::Type::Stream), + HttpIntegrationTest( std::get<0>(GetParam()).downstream_protocol, std::get<0>(GetParam()).version, ConfigHelper::httpProxyConfig( /*downstream_is_quic=*/std::get<0>(GetParam()).downstream_protocol == diff --git a/test/integration/filters/test_socket_interface.h b/test/integration/filters/test_socket_interface.h index af28e319ce04..6ecdf2122667 100644 --- a/test/integration/filters/test_socket_interface.h +++ b/test/integration/filters/test_socket_interface.h @@ -30,7 +30,12 @@ class TestIoSocketHandle : public Test::IoSocketHandlePlatformImpl { TestIoSocketHandle(WriteOverrideProc write_override_proc, os_fd_t fd = INVALID_SOCKET, bool socket_v6only = false, absl::optional domain = absl::nullopt) : Test::IoSocketHandlePlatformImpl(fd, socket_v6only, domain), - write_override_(write_override_proc) {} + write_override_(write_override_proc) { + int type; + socklen_t length = sizeof(int); + EXPECT_EQ(0, getOption(SOL_SOCKET, SO_TYPE, &type, &length).return_value_); + socket_type_ = type == SOCK_STREAM ? Socket::Type::Stream : Socket::Type::Datagram; + } void initializeFileEvent(Event::Dispatcher& dispatcher, Event::FileReadyCb cb, Event::FileTriggerType trigger, uint32_t events) override { @@ -59,6 +64,8 @@ class TestIoSocketHandle : public Test::IoSocketHandlePlatformImpl { return Test::IoSocketHandlePlatformImpl::peerAddress(); } + Socket::Type getSocketType() const { return socket_type_; } + private: IoHandlePtr accept(struct sockaddr* addr, socklen_t* addrlen) override; Api::IoCallUint64Result writev(const Buffer::RawSlice* slices, uint64_t num_slice) override; @@ -72,6 +79,7 @@ class TestIoSocketHandle : public Test::IoSocketHandlePlatformImpl { const WriteOverrideProc write_override_; absl::Mutex mutex_; Event::Dispatcher* dispatcher_ ABSL_GUARDED_BY(mutex_) = nullptr; + Socket::Type socket_type_; }; /** diff --git a/test/integration/http2_flood_integration_test.cc b/test/integration/http2_flood_integration_test.cc index c7f0d2fb148f..6a08c69b12a8 100644 --- a/test/integration/http2_flood_integration_test.cc +++ b/test/integration/http2_flood_integration_test.cc @@ -56,7 +56,9 @@ class Http2FloodMitigationTest public testing::TestWithParam>, public Http2RawFrameIntegrationTest { public: - Http2FloodMitigationTest() : Http2RawFrameIntegrationTest(std::get<0>(GetParam())) { + Http2FloodMitigationTest() + : SocketInterfaceSwap(Network::Socket::Type::Stream), + Http2RawFrameIntegrationTest(std::get<0>(GetParam())) { // This test tracks the number of buffers created, and the tag extraction check uses some // buffers, so disable it in this test. skip_tag_extraction_rule_check_ = true; diff --git a/test/integration/multiplexed_integration_test.cc b/test/integration/multiplexed_integration_test.cc index 1a78f0273f18..190e57065d1c 100644 --- a/test/integration/multiplexed_integration_test.cc +++ b/test/integration/multiplexed_integration_test.cc @@ -2406,7 +2406,13 @@ TEST_P(MultiplexedIntegrationTest, ConnectionPoolPerDownstream) { // Ordering of inheritance is important here, SocketInterfaceSwap must be // destroyed after HttpProtocolIntegrationTest. class SocketSwappableMultiplexedIntegrationTest : public SocketInterfaceSwap, - public HttpProtocolIntegrationTest {}; + public HttpProtocolIntegrationTest { +public: + SocketSwappableMultiplexedIntegrationTest() + : SocketInterfaceSwap(GetParam().downstream_protocol == Http::CodecType::HTTP3 + ? Network::Socket::Type::Datagram + : Network::Socket::Type::Stream) {} +}; INSTANTIATE_TEST_SUITE_P(IpVersions, SocketSwappableMultiplexedIntegrationTest, testing::ValuesIn(HttpProtocolIntegrationTest::getProtocolTestParams( diff --git a/test/integration/protocol_integration_test.cc b/test/integration/protocol_integration_test.cc index edf0d14ed38b..2b1bb3f77b63 100644 --- a/test/integration/protocol_integration_test.cc +++ b/test/integration/protocol_integration_test.cc @@ -4286,7 +4286,9 @@ TEST_P(DownstreamProtocolIntegrationTest, HandleDownstreamSocketFail) { NoUdpGso reject_gso_; TestThreadsafeSingletonInjector os_calls{&reject_gso_}; ASSERT(!Api::OsSysCallsSingleton::get().supportsUdpGso()); - SocketInterfaceSwap socket_swap; + SocketInterfaceSwap socket_swap(downstreamProtocol() == Http::CodecType::HTTP3 + ? Network::Socket::Type::Datagram + : Network::Socket::Type::Stream); initialize(); codec_client_ = makeHttpConnection(lookupPort("http")); @@ -4320,7 +4322,9 @@ TEST_P(DownstreamProtocolIntegrationTest, HandleDownstreamSocketFail) { } TEST_P(ProtocolIntegrationTest, HandleUpstreamSocketFail) { - SocketInterfaceSwap socket_swap; + SocketInterfaceSwap socket_swap(upstreamProtocol() == Http::CodecType::HTTP3 + ? Network::Socket::Type::Datagram + : Network::Socket::Type::Stream); useAccessLog("%RESPONSE_CODE_DETAILS%"); initialize(); diff --git a/test/integration/shadow_policy_integration_test.cc b/test/integration/shadow_policy_integration_test.cc index 190bff3858dc..4f4c1b8855d7 100644 --- a/test/integration/shadow_policy_integration_test.cc +++ b/test/integration/shadow_policy_integration_test.cc @@ -19,7 +19,8 @@ class ShadowPolicyIntegrationTest public SocketInterfaceSwap { public: ShadowPolicyIntegrationTest() - : HttpIntegrationTest(Http::CodecType::HTTP2, std::get<0>(GetParam())) { + : HttpIntegrationTest(Http::CodecType::HTTP2, std::get<0>(GetParam())), + SocketInterfaceSwap(Network::Socket::Type::Stream) { scoped_runtime_.mergeValues( {{"envoy.reloadable_features.streaming_shadow", streaming_shadow_ ? "true" : "false"}}); setUpstreamProtocol(Http::CodecType::HTTP2); diff --git a/test/integration/socket_interface_swap.cc b/test/integration/socket_interface_swap.cc index f2b716127d48..608a90363440 100644 --- a/test/integration/socket_interface_swap.cc +++ b/test/integration/socket_interface_swap.cc @@ -4,7 +4,8 @@ namespace Envoy { void preserveIoError(Api::IoError*) {} -SocketInterfaceSwap::SocketInterfaceSwap() { +SocketInterfaceSwap::SocketInterfaceSwap(Network::Socket::Type socket_type) + : write_matcher_(std::make_shared(socket_type)) { Envoy::Network::SocketInterfaceSingleton::clear(); test_socket_interface_loader_ = std::make_unique( std::make_unique( diff --git a/test/integration/socket_interface_swap.h b/test/integration/socket_interface_swap.h index 676b8989453e..f5f3b168ef68 100644 --- a/test/integration/socket_interface_swap.h +++ b/test/integration/socket_interface_swap.h @@ -14,10 +14,13 @@ class SocketInterfaceSwap { // Object of this class hold the state determining the IoHandle which // should return the supplied return from the `writev` or `sendmsg` calls. struct IoHandleMatcher { + explicit IoHandleMatcher(Network::Socket::Type type) : socket_type_(type) {} + Network::IoSocketError* returnOverride(Envoy::Network::TestIoSocketHandle* io_handle) { absl::MutexLock lock(&mutex_); - if (error_ && (io_handle->localAddress()->ip()->port() == src_port_ || - (dst_port_ && io_handle->peerAddress()->ip()->port() == dst_port_))) { + if (socket_type_ == io_handle->getSocketType() && error_ && + (io_handle->localAddress()->ip()->port() == src_port_ || + (dst_port_ && io_handle->peerAddress()->ip()->port() == dst_port_))) { ASSERT(matched_iohandle_ == nullptr || matched_iohandle_ == io_handle, "Matched multiple io_handles, expected at most one to match."); matched_iohandle_ = io_handle; @@ -59,9 +62,10 @@ class SocketInterfaceSwap { uint32_t dst_port_ ABSL_GUARDED_BY(mutex_) = 0; Network::IoSocketError* error_ ABSL_GUARDED_BY(mutex_) = nullptr; Network::TestIoSocketHandle* matched_iohandle_{}; + Network::Socket::Type socket_type_; }; - SocketInterfaceSwap(); + explicit SocketInterfaceSwap(Network::Socket::Type socket_type); ~SocketInterfaceSwap() { test_socket_interface_loader_.reset(); @@ -70,7 +74,7 @@ class SocketInterfaceSwap { Envoy::Network::SocketInterface* const previous_socket_interface_{ Envoy::Network::SocketInterfaceSingleton::getExisting()}; - std::shared_ptr write_matcher_{std::make_shared()}; + std::shared_ptr write_matcher_; std::unique_ptr test_socket_interface_loader_; }; From 0b7a589a51a396372fb1e234ca24acfc74e8e97b Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Tue, 23 May 2023 10:19:42 -0400 Subject: [PATCH 052/228] Adding allow_mode_override API in ext_proc filter config. (#27542) * Adding allow_mode_override API in ext_proc filter config. Signed-off-by: Yanjun Xiang --- .../extensions/filters/http/ext_proc/v3/ext_proc.proto | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index dce9b24cfd74..02fa12d7455c 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -101,7 +101,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // ` object in a namespace matching the filter // name. // -// [#next-free-field: 14] +// [#next-free-field: 15] message ExternalProcessor { // Configuration for the gRPC service that the filter will communicate with. // The filter supports both the "Envoy" and "Google" gRPC clients. @@ -196,6 +196,14 @@ message ExternalProcessor { // will be added to StreamInfo's filter state under the namespace corresponding to the // ext_proc filter name. google.protobuf.Struct filter_metadata = 13; + + // [#not-implemented-hide:] + // If ``allow_mode_override`` is set to true, the filter config :ref:`processing_mode + // ` + // can be overridden by the response message from the external processing server + // :ref:`mode_override `. + // If not set, ``mode_override`` API in the response message will be ignored. + bool allow_mode_override = 14; } // The HeaderForwardingRules structure specifies what headers are From 6ea3cf4625d550d74b2a506e28162e95489b6ea0 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 23 May 2023 12:59:09 -0400 Subject: [PATCH 053/228] dns: changing cache keys to include port to avoid issues (#27407) adding port to DNS cache key so that you can have a DFP filter which points to both secure and insecure clusters. Previously, this would result in failed connection attempts as the created and inserted hosts would share a key (hostname no port) but have incompatible addresses (addresses with ports) Risk Level: medium Testing: unit, integration Release Notes: inline Fixes #27331 Signed-off-by: Alyssa Wilk --- .github/workflows/mobile-coverage.yml | 2 +- changelogs/current.yaml | 5 + .../kotlin/integration/MixedSchemeTest.kt | 101 ++++++++ source/common/http/header_utility.cc | 13 + source/common/http/header_utility.h | 5 + source/common/runtime/runtime_features.cc | 1 + .../clusters/dynamic_forward_proxy/cluster.cc | 33 ++- .../common/dynamic_forward_proxy/dns_cache.h | 20 ++ .../dynamic_forward_proxy/dns_cache_impl.cc | 6 +- .../network/sni_dynamic_forward_proxy/BUILD | 1 + .../sni_dynamic_forward_proxy/proxy_filter.cc | 7 + test/common/http/header_utility_test.cc | 20 ++ .../dynamic_forward_proxy/cluster_test.cc | 88 ++++--- .../dns_cache_impl_test.cc | 238 ++++++++++-------- .../proxy_filter_integration_test.cc | 42 +++- 15 files changed, 425 insertions(+), 157 deletions(-) create mode 100644 mobile/test/kotlin/integration/MixedSchemeTest.kt diff --git a/.github/workflows/mobile-coverage.yml b/.github/workflows/mobile-coverage.yml index e6068b9c2510..cdb1cf2a9853 100644 --- a/.github/workflows/mobile-coverage.yml +++ b/.github/workflows/mobile-coverage.yml @@ -38,7 +38,7 @@ jobs: cd mobile && BAZEL_BUILD_OPTION_LIST="--config=remote-ci-linux-coverage" \ PATH=/opt/llvm/bin:${PATH} \ COVERAGE_THRESHOLD=76 \ - ../test/run_envoy_bazel_coverage.sh //test/common/... + ../test/run_envoy_bazel_coverage.sh //test/common/... //test/cc/... - name: 'Package coverage' if: steps.should_run.outputs.run_ci_job == 'true' run: | diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 1e8249a02621..c73629831412 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -33,6 +33,11 @@ minor_behavior_changes: behavior can be reverted by setting runtime flag ``envoy.reloadable_features.http1_allow_codec_error_response_after_1xx_headers`` to false. +- area: dns + change: | + Changing the DNS cache to use host:port as the cache key rather than host. This allows a + downstream DFP filter to serve both secure and insecure clusters. This behavioral change + can be reverted by setting runtime flag ``envoy.reloadable_features.dfp_mixed_scheme`` to false. - area: uhv change: | Preserve case of %-encoded triplets in the default header validator. This behavior can be reverted by setting runtime flag diff --git a/mobile/test/kotlin/integration/MixedSchemeTest.kt b/mobile/test/kotlin/integration/MixedSchemeTest.kt new file mode 100644 index 000000000000..ec054681e1c4 --- /dev/null +++ b/mobile/test/kotlin/integration/MixedSchemeTest.kt @@ -0,0 +1,101 @@ +package test.kotlin.integration + +import io.envoyproxy.envoymobile.LogLevel +import io.envoyproxy.envoymobile.Standard +import io.envoyproxy.envoymobile.EngineBuilder +import io.envoyproxy.envoymobile.RequestHeadersBuilder +import io.envoyproxy.envoymobile.RequestMethod +import io.envoyproxy.envoymobile.engine.JniLibrary +import java.nio.ByteBuffer +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.fail +import org.junit.Test + +private const val testResponseFilterType = "type.googleapis.com/envoymobile.extensions.filters.http.test_remote_response.TestRemoteResponse" + +class ReceiveDataTest { + + init { + JniLibrary.loadTestLibrary() + } + + @Test + fun `response headers and response data call onResponseHeaders and onResponseData`() { + + val engine = EngineBuilder(Standard()) + .addLogLevel(LogLevel.TRACE) + .build() + val client = engine.streamClient() + + // httpi + val headersExpectation2 = CountDownLatch(1) + val dataExpectation2 = CountDownLatch(1) + + var status2: Int? = null + + val requestHeaders2 = RequestHeadersBuilder( + method = RequestMethod.GET, + scheme = "http", + authority = "example.com", + path = "/" + ) + .build() + + client.newStreamPrototype() + .setOnResponseHeaders { responseHeaders, _, _ -> + status2 = responseHeaders.httpStatus + headersExpectation2.countDown() + } + .setOnResponseData { data, _, _ -> + dataExpectation2.countDown() + } + .setOnError { _, _ -> + fail("Unexpected error") + } + .start() + .sendHeaders(requestHeaders2, true) + + headersExpectation2.await(10, TimeUnit.SECONDS) + dataExpectation2.await(10, TimeUnit.SECONDS) + + assertThat(headersExpectation2.count).isEqualTo(0) + assertThat(dataExpectation2.count).isEqualTo(0) + + // https + val requestHeaders = RequestHeadersBuilder( + method = RequestMethod.GET, + scheme = "https", + authority = "example.com", + path = "/" + ) + .build() + + val headersExpectation = CountDownLatch(1) + val dataExpectation = CountDownLatch(1) + + var status: Int? = null + client.newStreamPrototype() + .setOnResponseHeaders { responseHeaders, _, _ -> + status = responseHeaders.httpStatus + headersExpectation.countDown() + } + .setOnResponseData { data, _, _ -> + dataExpectation.countDown() + } + .setOnError { _, _ -> fail("Unexpected error") } + .start() + .sendHeaders(requestHeaders, true) + + headersExpectation.await(10, TimeUnit.SECONDS) + dataExpectation.await(10, TimeUnit.SECONDS) + engine.terminate() + + assertThat(headersExpectation.count).isEqualTo(0) + assertThat(dataExpectation.count).isEqualTo(0) + + assertThat(status).isEqualTo(200) + assertThat(status2).isEqualTo(200) + } +} diff --git a/source/common/http/header_utility.cc b/source/common/http/header_utility.cc index 23b87471061f..71f1942eb788 100644 --- a/source/common/http/header_utility.cc +++ b/source/common/http/header_utility.cc @@ -301,6 +301,19 @@ void HeaderUtility::stripTrailingHostDot(RequestHeaderMap& headers) { } } +bool HeaderUtility::hostHasPort(absl::string_view original_host) { + const absl::string_view::size_type port_start = getPortStart(original_host); + const absl::string_view port_str = original_host.substr(port_start + 1); + if (port_start == absl::string_view::npos) { + return false; + } + uint32_t port = 0; + if (!absl::SimpleAtoi(port_str, &port)) { + return false; + } + return true; +} + absl::optional HeaderUtility::stripPortFromHost(RequestHeaderMap& headers, absl::optional listener_port) { const absl::string_view original_host = headers.getHostValue(); diff --git a/source/common/http/header_utility.h b/source/common/http/header_utility.h index 8ce7b2724c8f..bd63fe4c0bbe 100644 --- a/source/common/http/header_utility.h +++ b/source/common/http/header_utility.h @@ -215,6 +215,11 @@ class HeaderUtility { */ static void stripTrailingHostDot(RequestHeaderMap& headers); + /** + * @return bool true if the provided host has a port, false otherwise. + */ + static bool hostHasPort(absl::string_view host); + /** * @brief Remove the port part from host/authority header if it is equal to provided port. * @return absl::optional containing the port, if removed, else absl::nullopt. diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 7d860806d6ab..360998402fa3 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -34,6 +34,7 @@ RUNTIME_GUARD(envoy_reloadable_features_append_query_parameters_path_rewriter); RUNTIME_GUARD(envoy_reloadable_features_append_xfh_idempotent); RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle); RUNTIME_GUARD(envoy_reloadable_features_count_unused_mapped_pages_as_free); +RUNTIME_GUARD(envoy_reloadable_features_dfp_mixed_scheme); RUNTIME_GUARD(envoy_reloadable_features_enable_aws_credentials_file); RUNTIME_GUARD(envoy_reloadable_features_enable_compression_bomb_protection); RUNTIME_GUARD(envoy_reloadable_features_enable_intermediate_ca); diff --git a/source/extensions/clusters/dynamic_forward_proxy/cluster.cc b/source/extensions/clusters/dynamic_forward_proxy/cluster.cc index 3d400213b7c4..ace4989c478c 100644 --- a/source/extensions/clusters/dynamic_forward_proxy/cluster.cc +++ b/source/extensions/clusters/dynamic_forward_proxy/cluster.cc @@ -6,6 +6,7 @@ #include "envoy/extensions/clusters/dynamic_forward_proxy/v3/cluster.pb.h" #include "envoy/extensions/clusters/dynamic_forward_proxy/v3/cluster.pb.validate.h" #include "envoy/router/string_accessor.h" +#include "envoy/stream_info/uint32_accessor.h" #include "source/common/http/utility.h" #include "source/common/network/transport_socket_options_impl.h" @@ -322,15 +323,39 @@ Cluster::LoadBalancer::chooseHost(Upstream::LoadBalancerContext* context) { .getDataReadOnly("envoy.upstream.dynamic_host"); } - absl::string_view host; + absl::string_view raw_host; if (dynamic_host_filter_state) { - host = dynamic_host_filter_state->asString(); + raw_host = dynamic_host_filter_state->asString(); } else if (context->downstreamHeaders()) { - host = context->downstreamHeaders()->getHostValue(); + raw_host = context->downstreamHeaders()->getHostValue(); } else if (context->downstreamConnection()) { - host = context->downstreamConnection()->requestedServerName(); + raw_host = context->downstreamConnection()->requestedServerName(); } + // For host lookup, we need to make sure to match the host of any DNS cache + // insert. Two code points currently do DNS cache insert: the http DFP filter, + // which inserts for HTTP traffic, and sets port based on the cluster's + // security level, and the SNI DFP network filter which sets port based on + // stream metadata, or configuration (which is then added as stream metadata). + const bool is_secure = cluster_.info() + ->transportSocketMatcher() + .resolve(nullptr) + .factory_.implementsSecureTransport(); + uint32_t port = is_secure ? 443 : 80; + if (context->downstreamConnection()) { + const StreamInfo::UInt32Accessor* dynamic_port_filter_state = + context->downstreamConnection() + ->streamInfo() + .filterState() + .getDataReadOnly("envoy.upstream.dynamic_port"); + if (dynamic_port_filter_state != nullptr && dynamic_port_filter_state->value() > 0 && + dynamic_port_filter_state->value() <= 65535) { + port = dynamic_port_filter_state->value(); + } + } + + std::string host = Common::DynamicForwardProxy::DnsHostInfo::normalizeHostForDfp(raw_host, port); + if (host.empty()) { return nullptr; } diff --git a/source/extensions/common/dynamic_forward_proxy/dns_cache.h b/source/extensions/common/dynamic_forward_proxy/dns_cache.h index d48d24c9f5c6..89670576681a 100644 --- a/source/extensions/common/dynamic_forward_proxy/dns_cache.h +++ b/source/extensions/common/dynamic_forward_proxy/dns_cache.h @@ -7,6 +7,9 @@ #include "envoy/thread_local/thread_local.h" #include "envoy/upstream/resource_manager.h" +#include "source/common/http/header_utility.h" +#include "source/common/runtime/runtime_features.h" + namespace Envoy { namespace Extensions { namespace Common { @@ -17,6 +20,23 @@ namespace DynamicForwardProxy { */ class DnsHostInfo { public: + // DFP hosts are created after a DNS lookup for a domain name (e.g. foo.com) but are created + // with an IP address and port to resolve to. To prevent bugs where we insert say foo.com + // (default port 80) then later look up foo.com (default port 443) and get IP addresses with + // port 80, we "fully qualify" hostnames with the port. + // + // This normalizes hostnames, respecting the port if it exists, and adding the default port + // if there is no port. + static std::string normalizeHostForDfp(absl::string_view host, uint16_t default_port) { + if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.dfp_mixed_scheme")) { + return std::string(host); + } + if (Http::HeaderUtility::hostHasPort(host)) { + return std::string(host); + } + return absl::StrCat(host, ":", default_port); + } + virtual ~DnsHostInfo() = default; /** diff --git a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc index ccded48194f3..56c99b48b4ec 100644 --- a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc +++ b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc @@ -83,8 +83,10 @@ DnsCacheStats DnsCacheImpl::generateDnsCacheStats(Stats::Scope& scope) { } DnsCacheImpl::LoadDnsCacheEntryResult -DnsCacheImpl::loadDnsCacheEntry(absl::string_view host, uint16_t default_port, bool is_proxy_lookup, - LoadDnsCacheEntryCallbacks& callbacks) { +DnsCacheImpl::loadDnsCacheEntry(absl::string_view raw_host, uint16_t default_port, + bool is_proxy_lookup, LoadDnsCacheEntryCallbacks& callbacks) { + std::string host = DnsHostInfo::normalizeHostForDfp(raw_host, default_port); + ENVOY_LOG(debug, "thread local lookup for host '{}' {}", host, is_proxy_lookup ? "proxy mode " : ""); ThreadLocalHostInfo& tls_host_info = *tls_slot_; diff --git a/source/extensions/filters/network/sni_dynamic_forward_proxy/BUILD b/source/extensions/filters/network/sni_dynamic_forward_proxy/BUILD index 424c985cb9d9..1f523fd0e360 100644 --- a/source/extensions/filters/network/sni_dynamic_forward_proxy/BUILD +++ b/source/extensions/filters/network/sni_dynamic_forward_proxy/BUILD @@ -20,6 +20,7 @@ envoy_cc_library( "//envoy/stream_info:uint32_accessor_interface", "//source/common/common:assert_lib", "//source/common/common:minimal_logger_lib", + "//source/common/stream_info:uint32_accessor_lib", "//source/common/tcp_proxy", "//source/extensions/common/dynamic_forward_proxy:dns_cache_interface", "@envoy_api//envoy/extensions/filters/network/sni_dynamic_forward_proxy/v3:pkg_cc_proto", diff --git a/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc b/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc index d4790943f9ae..7481f6e767d6 100644 --- a/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc +++ b/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc @@ -7,6 +7,7 @@ #include "envoy/upstream/thread_local_cluster.h" #include "source/common/common/assert.h" +#include "source/common/stream_info/uint32_accessor_impl.h" #include "source/common/tcp_proxy/tcp_proxy.h" namespace Envoy { @@ -67,6 +68,12 @@ Network::FilterStatus ProxyFilter::onNewConnection() { port = dynamic_port_filter_state->value(); } else { port = config_->port(); + if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.dfp_mixed_scheme")) { + read_callbacks_->connection().streamInfo().filterState()->setData( + "envoy.upstream.dynamic_port", std::make_shared(port), + StreamInfo::FilterState::StateType::Mutable, + StreamInfo::FilterState::LifeSpan::Connection); + } } auto result = config_->cache().loadDnsCacheEntry(host, port, false, *this); diff --git a/test/common/http/header_utility_test.cc b/test/common/http/header_utility_test.cc index b67c1da9e286..f8ad125c256f 100644 --- a/test/common/http/header_utility_test.cc +++ b/test/common/http/header_utility_test.cc @@ -56,6 +56,26 @@ TEST_F(HeaderUtilityTest, HasHost) { } } +TEST_F(HeaderUtilityTest, HostHasPort) { + const std::vector> host_headers{ + {"localhost", false}, // w/o port part + {"localhost:443", true}, // name w/ port + {"", false}, // empty + {":443", true}, // just port + {"192.168.1.1", false}, // ipv4 + {"192.168.1.1:443", true}, // ipv4 w/ port + {"[fc00::1]:443", true}, // ipv6 w/ port + {"[fc00::1]", false}, // ipv6 + {":", false}, // malformed string #1 + {"]:", false}, // malformed string #2 + {":abc", false}, // malformed string #3 + }; + + for (const auto& host_pair : host_headers) { + EXPECT_EQ(host_pair.second, HeaderUtility::hostHasPort(host_pair.first)); + } +} + // Port's part from host header get removed TEST_F(HeaderUtilityTest, RemovePortsFromHost) { const std::vector> host_headers{ diff --git a/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc b/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc index 55495f4175f3..472a301e0860 100644 --- a/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc +++ b/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc @@ -225,69 +225,93 @@ TEST_F(ClusterTest, CreateSubClusterConfig) { EXPECT_EQ(false, sub_cluster_pair.second.has_value()); } +TEST_F(ClusterTest, InvalidSubClusterConfig) { + const std::string bad_sub_cluster_yaml_config = R"EOF( +name: name +connect_timeout: 0.25s +cluster_type: + name: dynamic_forward_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig + sub_clusters_config: + max_sub_clusters: 1024 + lb_policy: CLUSTER_PROVIDED +)EOF"; + + EXPECT_THROW(initialize(bad_sub_cluster_yaml_config, false), EnvoyException); +} + // Basic flow of the cluster including adding hosts and removing them. TEST_F(ClusterTest, BasicFlow) { initialize(default_yaml_config_, false); - makeTestHost("host1", "1.2.3.4"); + makeTestHost("host1:0", "1.2.3.4"); InSequence s; + EXPECT_EQ(nullptr, lb_->chooseHost(setHostAndReturnContext(""))); + // Verify no host LB cases. EXPECT_EQ(nullptr, lb_->chooseHost(setHostAndReturnContext("foo"))); EXPECT_EQ(nullptr, lb_->peekAnotherHost(setHostAndReturnContext("foo"))); // LB will immediately resolve host1. EXPECT_CALL(*this, onMemberUpdateCb(SizeIs(1), SizeIs(0))); - update_callbacks_->onDnsHostAddOrUpdate("host1", host_map_["host1"]); + update_callbacks_->onDnsHostAddOrUpdate("host1:0", host_map_["host1:0"]); EXPECT_EQ(1UL, cluster_->prioritySet().hostSetsPerPriority()[0]->hosts().size()); EXPECT_EQ("1.2.3.4:0", cluster_->prioritySet().hostSetsPerPriority()[0]->hosts()[0]->address()->asString()); - EXPECT_CALL(*host_map_["host1"], touch()); - EXPECT_EQ("1.2.3.4:0", lb_->chooseHost(setHostAndReturnContext("host1"))->address()->asString()); + EXPECT_CALL(*host_map_["host1:0"], touch()); + EXPECT_EQ("1.2.3.4:0", + lb_->chooseHost(setHostAndReturnContext("host1:0"))->address()->asString()); // After changing the address, LB will immediately resolve the new address with a refresh. - updateTestHostAddress("host1", "2.3.4.5"); - update_callbacks_->onDnsHostAddOrUpdate("host1", host_map_["host1"]); + updateTestHostAddress("host1:0", "2.3.4.5"); + update_callbacks_->onDnsHostAddOrUpdate("host1:0", host_map_["host1:0"]); EXPECT_EQ(1UL, cluster_->prioritySet().hostSetsPerPriority()[0]->hosts().size()); EXPECT_EQ("2.3.4.5:0", cluster_->prioritySet().hostSetsPerPriority()[0]->hosts()[0]->address()->asString()); - EXPECT_CALL(*host_map_["host1"], touch()); - EXPECT_EQ("2.3.4.5:0", lb_->chooseHost(setHostAndReturnContext("host1"))->address()->asString()); + EXPECT_CALL(*host_map_["host1:0"], touch()); + EXPECT_EQ("2.3.4.5:0", + lb_->chooseHost(setHostAndReturnContext("host1:0"))->address()->asString()); // Remove the host, LB will immediately fail to find the host in the map. EXPECT_CALL(*this, onMemberUpdateCb(SizeIs(0), SizeIs(1))); - update_callbacks_->onDnsHostRemove("host1"); + update_callbacks_->onDnsHostRemove("host1:0"); EXPECT_EQ(0UL, cluster_->prioritySet().hostSetsPerPriority()[0]->hosts().size()); - EXPECT_EQ(nullptr, lb_->chooseHost(setHostAndReturnContext("host1"))); + EXPECT_EQ(nullptr, lb_->chooseHost(setHostAndReturnContext("host1:0"))); } // Outlier detection TEST_F(ClusterTest, OutlierDetection) { initialize(default_yaml_config_, false); - makeTestHost("host1", "1.2.3.4"); - makeTestHost("host2", "5.6.7.8"); + makeTestHost("host1:0", "1.2.3.4"); + makeTestHost("host2:0", "5.6.7.8"); InSequence s; EXPECT_CALL(*this, onMemberUpdateCb(SizeIs(1), SizeIs(0))); - update_callbacks_->onDnsHostAddOrUpdate("host1", host_map_["host1"]); - EXPECT_CALL(*host_map_["host1"], touch()); - EXPECT_EQ("1.2.3.4:0", lb_->chooseHost(setHostAndReturnContext("host1"))->address()->asString()); + update_callbacks_->onDnsHostAddOrUpdate("host1:0", host_map_["host1:0"]); + EXPECT_CALL(*host_map_["host1:0"], touch()); + EXPECT_EQ("1.2.3.4:0", + lb_->chooseHost(setHostAndReturnContext("host1:0"))->address()->asString()); EXPECT_CALL(*this, onMemberUpdateCb(SizeIs(1), SizeIs(0))); - update_callbacks_->onDnsHostAddOrUpdate("host2", host_map_["host2"]); - EXPECT_CALL(*host_map_["host2"], touch()); - EXPECT_EQ("5.6.7.8:0", lb_->chooseHost(setHostAndReturnContext("host2"))->address()->asString()); + update_callbacks_->onDnsHostAddOrUpdate("host2:0", host_map_["host2:0"]); + EXPECT_CALL(*host_map_["host2:0"], touch()); + EXPECT_EQ("5.6.7.8:0", + lb_->chooseHost(setHostAndReturnContext("host2:0"))->address()->asString()); // Fail outlier check for host1 - setOutlierFailed("host1"); - EXPECT_EQ(nullptr, lb_->chooseHost(setHostAndReturnContext("host1"))); - // "host2" should not be affected - EXPECT_CALL(*host_map_["host2"], touch()); - EXPECT_EQ("5.6.7.8:0", lb_->chooseHost(setHostAndReturnContext("host2"))->address()->asString()); + setOutlierFailed("host1:0"); + EXPECT_EQ(nullptr, lb_->chooseHost(setHostAndReturnContext("host1:0"))); + // "host2:0" should not be affected + EXPECT_CALL(*host_map_["host2:0"], touch()); + EXPECT_EQ("5.6.7.8:0", + lb_->chooseHost(setHostAndReturnContext("host2:0"))->address()->asString()); // Clear outlier check failure for host1, it should be available again - clearOutlierFailed("host1"); - EXPECT_CALL(*host_map_["host1"], touch()); - EXPECT_EQ("1.2.3.4:0", lb_->chooseHost(setHostAndReturnContext("host1"))->address()->asString()); + clearOutlierFailed("host1:0"); + EXPECT_CALL(*host_map_["host1:0"], touch()); + EXPECT_EQ("1.2.3.4:0", + lb_->chooseHost(setHostAndReturnContext("host1:0"))->address()->asString()); } // Various invalid LB context permutations in case the cluster is used outside of HTTP. @@ -300,19 +324,19 @@ TEST_F(ClusterTest, InvalidLbContext) { TEST_F(ClusterTest, FilterStateHostOverride) { initialize(default_yaml_config_, false); - makeTestHost("host1", "1.2.3.4"); + makeTestHost("host1:0", "1.2.3.4"); EXPECT_CALL(*this, onMemberUpdateCb(SizeIs(1), SizeIs(0))); - update_callbacks_->onDnsHostAddOrUpdate("host1", host_map_["host1"]); - EXPECT_CALL(*host_map_["host1"], touch()); + update_callbacks_->onDnsHostAddOrUpdate("host1:0", host_map_["host1:0"]); + EXPECT_CALL(*host_map_["host1:0"], touch()); EXPECT_EQ("1.2.3.4:0", - lb_->chooseHost(setFilterStateHostAndReturnContext("host1"))->address()->asString()); + lb_->chooseHost(setFilterStateHostAndReturnContext("host1:0"))->address()->asString()); } // Verify cluster attaches to a populated cache. TEST_F(ClusterTest, PopulatedCache) { - makeTestHost("host1", "1.2.3.4"); - makeTestHost("host2", "1.2.3.5"); + makeTestHost("host1:0", "1.2.3.4"); + makeTestHost("host2:0", "1.2.3.5"); initialize(default_yaml_config_, false); EXPECT_EQ(2UL, cluster_->prioritySet().hostSetsPerPriority()[0]->hosts().size()); } diff --git a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc index 5fba329071a9..b33e2ed770b4 100644 --- a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc +++ b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc @@ -126,18 +126,18 @@ void verifyCaresDnsConfigAndUnpack( TEST_F(DnsCacheImplTest, PreresolveSuccess) { Network::DnsResolver::ResolveCb resolve_cb; - std::string hostname = "bar.baz.com"; - EXPECT_CALL(*resolver_, resolve(hostname, _, _)) + std::string hostname = "bar.baz.com:443"; + EXPECT_CALL(*resolver_, resolve("bar.baz.com", _, _)) .WillOnce(DoAll(SaveArg<2>(&resolve_cb), Return(&resolver_->active_query_))); - EXPECT_CALL( - update_callbacks_, - onDnsHostAddOrUpdate("bar.baz.com", DnsHostInfoEquals("10.0.0.1:443", "bar.baz.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("bar.baz.com", + onDnsHostAddOrUpdate("bar.baz.com:443", + DnsHostInfoEquals("10.0.0.1:443", "bar.baz.com", false))); + EXPECT_CALL(update_callbacks_, + onDnsResolutionComplete("bar.baz.com:443", DnsHostInfoEquals("10.0.0.1:443", "bar.baz.com", false), Network::DnsResolver::ResolutionStatus::Success)); - initialize({"bar.baz.com"} /* preresolve_hostnames */); + initialize({"bar.baz.com:443"} /* preresolve_hostnames */); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({"10.0.0.1"})); @@ -145,7 +145,7 @@ TEST_F(DnsCacheImplTest, PreresolveSuccess) { 1 /* added */, 0 /* removed */, 1 /* num hosts */); MockLoadDnsCacheEntryCallbacks callbacks; - auto result = dns_cache_->loadDnsCacheEntry("bar.baz.com", 80, false, callbacks); + auto result = dns_cache_->loadDnsCacheEntry("bar.baz.com", 443, false, callbacks); EXPECT_EQ(DnsCache::LoadDnsCacheEntryStatus::InCache, result.status_); EXPECT_EQ(result.handle_, nullptr); EXPECT_NE(absl::nullopt, result.host_info_); @@ -178,12 +178,14 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { 1 /* added */, 0 /* removed */, 1 /* num hosts */); EXPECT_CALL(*timeout_timer, disableTimer()); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -204,7 +206,8 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { // Address does not change. EXPECT_CALL(*timeout_timer, disableTimer()); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -224,10 +227,12 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { // Address does change. EXPECT_CALL(*timeout_timer, disableTimer()); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false))); - EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -295,11 +300,11 @@ TEST_F(DnsCacheImplTest, Ipv4Address) { EXPECT_CALL(*timeout_timer, disableTimer()); EXPECT_CALL( update_callbacks_, - onDnsHostAddOrUpdate("127.0.0.1", DnsHostInfoEquals("127.0.0.1:80", "127.0.0.1", true))); + onDnsHostAddOrUpdate("127.0.0.1:80", DnsHostInfoEquals("127.0.0.1:80", "127.0.0.1", true))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("127.0.0.1:80", "127.0.0.1", true))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("127.0.0.1", + onDnsResolutionComplete("127.0.0.1:80", DnsHostInfoEquals("127.0.0.1:80", "127.0.0.1", true), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); @@ -358,10 +363,10 @@ TEST_F(DnsCacheImplTest, Ipv6Address) { EXPECT_CALL(*timeout_timer, disableTimer()); EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("[::1]", DnsHostInfoEquals("[::1]:80", "::1", true))); + onDnsHostAddOrUpdate("[::1]:80", DnsHostInfoEquals("[::1]:80", "::1", true))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("[::1]:80", "::1", true))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("[::1]", DnsHostInfoEquals("[::1]:80", "::1", true), + onDnsResolutionComplete("[::1]:80", DnsHostInfoEquals("[::1]:80", "::1", true), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -418,12 +423,14 @@ TEST_F(DnsCacheImplTest, TTL) { 1 /* added */, 0 /* removed */, 1 /* num hosts */); EXPECT_CALL(*timeout_timer, disableTimer()); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(6000), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -443,7 +450,8 @@ TEST_F(DnsCacheImplTest, TTL) { EXPECT_CALL(*timeout_timer, disableTimer()); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(6000), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -454,7 +462,7 @@ TEST_F(DnsCacheImplTest, TTL) { // Re-resolve with ~1m passed. This is not realistic as we would have re-resolved many times // during this period but it's good enough for the test. simTime().advanceTimeWait(std::chrono::seconds(60000)); - EXPECT_CALL(update_callbacks_, onDnsHostRemove("foo.com")); + EXPECT_CALL(update_callbacks_, onDnsHostRemove("foo.com:80")); resolve_timer->invokeCallback(); checkStats(2 /* attempt */, 2 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 1 /* removed */, 0 /* num hosts */); @@ -492,12 +500,14 @@ TEST_F(DnsCacheImplTest, TTLWithMinRefreshRate) { EXPECT_EQ(absl::nullopt, result.host_info_); EXPECT_CALL(*timeout_timer, disableTimer()); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(45000), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -525,12 +535,14 @@ TEST_F(DnsCacheImplTest, TTLWithCustomParameters) { EXPECT_EQ(absl::nullopt, result.host_info_); EXPECT_CALL(*timeout_timer, disableTimer()); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -544,7 +556,8 @@ TEST_F(DnsCacheImplTest, TTLWithCustomParameters) { resolve_timer->invokeCallback(); EXPECT_CALL(*timeout_timer, disableTimer()); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -552,7 +565,7 @@ TEST_F(DnsCacheImplTest, TTLWithCustomParameters) { // Re-resolve with ~30s passed. TTL should expire. simTime().advanceTimeWait(std::chrono::milliseconds(30001)); - EXPECT_CALL(update_callbacks_, onDnsHostRemove("foo.com")); + EXPECT_CALL(update_callbacks_, onDnsHostRemove("foo.com:80")); resolve_timer->invokeCallback(); } @@ -584,11 +597,11 @@ TEST_F(DnsCacheImplTest, InlineResolve) { EXPECT_CALL(*timeout_timer, disableTimer()); EXPECT_CALL( update_callbacks_, - onDnsHostAddOrUpdate("localhost", DnsHostInfoEquals("127.0.0.1:80", "localhost", false))); + onDnsHostAddOrUpdate("localhost:80", DnsHostInfoEquals("127.0.0.1:80", "localhost", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("127.0.0.1:80", "localhost", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("localhost", + onDnsResolutionComplete("localhost:80", DnsHostInfoEquals("127.0.0.1:80", "localhost", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); @@ -619,7 +632,7 @@ TEST_F(DnsCacheImplTest, ResolveTimeout) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate(_, _)).Times(0); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoAddressIsNull(), + onDnsResolutionComplete("foo.com:80", DnsHostInfoAddressIsNull(), Network::DnsResolver::ResolutionStatus::Failure)); // The resolve timeout will be the default TTL as there was no specific TTL // overriding. @@ -654,7 +667,7 @@ TEST_F(DnsCacheImplTest, ResolveFailure) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate(_, _)).Times(0); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoAddressIsNull(), + onDnsResolutionComplete("foo.com:80", DnsHostInfoAddressIsNull(), Network::DnsResolver::ResolutionStatus::Failure)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(configured_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Failure, TestUtility::makeDnsResponse({})); @@ -706,7 +719,7 @@ TEST_F(DnsCacheImplTest, ResolveFailureWithFailureRefreshRate) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate(_, _)).Times(0); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoAddressIsNull(), + onDnsResolutionComplete("foo.com:80", DnsHostInfoAddressIsNull(), Network::DnsResolver::ResolutionStatus::Failure)); ON_CALL(context_.api_.random_, random()).WillByDefault(Return(8000)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(1000), _)); @@ -756,7 +769,7 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithEmptyResult) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate(_, _)).Times(0); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoAddressIsNull(), + onDnsResolutionComplete("foo.com:80", DnsHostInfoAddressIsNull(), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(configured_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({})); @@ -797,10 +810,12 @@ TEST_F(DnsCacheImplTest, CancelResolve) { EXPECT_EQ(absl::nullopt, result.host_info_); result.handle_.reset(); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); - EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({"10.0.0.1"})); @@ -827,14 +842,16 @@ TEST_F(DnsCacheImplTest, MultipleResolveSameHost) { EXPECT_NE(result2.handle_, nullptr); EXPECT_EQ(absl::nullopt, result2.host_info_); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks2, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks1, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({"10.0.0.1"})); @@ -865,22 +882,26 @@ TEST_F(DnsCacheImplTest, MultipleResolveDifferentHost) { EXPECT_EQ(absl::nullopt, result2.host_info_); EXPECT_EQ(dns_cache_->getHost("bar.com"), absl::nullopt); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("bar.com", DnsHostInfoEquals("10.0.0.1:443", "bar.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("bar.com:443", DnsHostInfoEquals("10.0.0.1:443", "bar.com", false))); EXPECT_CALL(callbacks2, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:443", "bar.com", false))); - EXPECT_CALL(update_callbacks_, onDnsResolutionComplete( - "bar.com", DnsHostInfoEquals("10.0.0.1:443", "bar.com", false), - Network::DnsResolver::ResolutionStatus::Success)); + EXPECT_CALL(update_callbacks_, + onDnsResolutionComplete("bar.com:443", + DnsHostInfoEquals("10.0.0.1:443", "bar.com", false), + Network::DnsResolver::ResolutionStatus::Success)); resolve_cb2(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({"10.0.0.1"})); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false))); EXPECT_CALL(callbacks1, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.2:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); resolve_cb1(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({"10.0.0.2"})); @@ -889,14 +910,14 @@ TEST_F(DnsCacheImplTest, MultipleResolveDifferentHost) { dns_cache_->iterateHostMap( [&](absl::string_view host, const DnsHostInfoSharedPtr& info) { hosts.emplace(host, info); }); EXPECT_EQ(2, hosts.size()); - EXPECT_THAT(hosts["bar.com"], DnsHostInfoEquals("10.0.0.1:443", "bar.com", false)); - EXPECT_THAT(hosts["foo.com"], DnsHostInfoEquals("10.0.0.2:80", "foo.com", false)); + EXPECT_THAT(hosts["bar.com:443"], DnsHostInfoEquals("10.0.0.1:443", "bar.com", false)); + EXPECT_THAT(hosts["foo.com:80"], DnsHostInfoEquals("10.0.0.2:80", "foo.com", false)); - EXPECT_TRUE(dns_cache_->getHost("bar.com").has_value()); - EXPECT_THAT(dns_cache_->getHost("bar.com").value(), + EXPECT_TRUE(dns_cache_->getHost("bar.com:443").has_value()); + EXPECT_THAT(dns_cache_->getHost("bar.com:443").value(), DnsHostInfoEquals("10.0.0.1:443", "bar.com", false)); - EXPECT_TRUE(dns_cache_->getHost("foo.com").has_value()); - EXPECT_THAT(dns_cache_->getHost("foo.com").value(), + EXPECT_TRUE(dns_cache_->getHost("foo.com:80").has_value()); + EXPECT_THAT(dns_cache_->getHost("foo.com:80").value(), DnsHostInfoEquals("10.0.0.2:80", "foo.com", false)); EXPECT_EQ(dns_cache_->getHost("baz.com"), absl::nullopt); } @@ -915,12 +936,14 @@ TEST_F(DnsCacheImplTest, CacheHit) { EXPECT_NE(result.handle_, nullptr); EXPECT_EQ(absl::nullopt, result.host_info_); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({"10.0.0.1"})); @@ -946,44 +969,24 @@ TEST_F(DnsCacheImplTest, CacheHitWithDifferentDefaultPort) { EXPECT_NE(result.handle_, nullptr); EXPECT_EQ(absl::nullopt, result.host_info_); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({"10.0.0.1"})); - // Using the same DNS cache, resolve the same host but different default port 443, - // Envoy returns LoadDnsCacheEntryStatus::InCache since the DNS cache - // key is the host string, which does not include the port number. - // This means if HTTP and HTTPS traffic are destined to DFP clusters using same DNS - // cache table, it will cause traffic forwarding issues. - result = dns_cache_->loadDnsCacheEntry("foo.com", 443, false, callbacks); - EXPECT_EQ(DnsCache::LoadDnsCacheEntryStatus::InCache, result.status_); - - // The way to resolve this is to config a different dns_cache_config name for HTTP and - // HTTPS DFP clusters. Then they will not conflict. - envoy::extensions::common::dynamic_forward_proxy::v3::DnsCacheConfig config_https; - // Set the dns_cache_config name to "bar" to make the HTTPS cache entries - // stored and looked up in a separate DNS cache table. - config_https.set_name("bar"); - config_https.set_dns_lookup_family(envoy::config::cluster::v3::Cluster::V4_ONLY); - std::unique_ptr dns_cache_https; - dns_cache_https = std::make_unique(context_, config_https); - MockUpdateCallbacks update_callbacks_https; - DnsCache::AddUpdateCallbacksHandlePtr update_callbacks_handle_https; - update_callbacks_handle_https = dns_cache_https->addUpdateCallbacks(update_callbacks_https); - MockLoadDnsCacheEntryCallbacks callbacks_https; - Network::DnsResolver::ResolveCb resolve_cb_https; + // Using the same DNS cache, resolve the same host but different default port 443 + // This currently will re-resolve as we don't have an optimization to look up + // cache entries with different ports. EXPECT_CALL(*resolver_, resolve("foo.com", _, _)) - .WillOnce(DoAll(SaveArg<2>(&resolve_cb_https), Return(&resolver_->active_query_))); - // So, now to resolve the same host and port 443 in DNS cache table "bar", it doesn't find - // an existing entry and returns LoadDnsCacheEntryStatus::Loading as expected. - auto result_https = dns_cache_https->loadDnsCacheEntry("foo.com", 80, false, callbacks_https); - EXPECT_EQ(DnsCache::LoadDnsCacheEntryStatus::Loading, result_https.status_); + .WillOnce(DoAll(SaveArg<2>(&resolve_cb), Return(&resolver_->active_query_))); + result = dns_cache_->loadDnsCacheEntry("foo.com", 443, false, callbacks); } // Make sure we destroy active queries if the cache goes away. @@ -1022,7 +1025,7 @@ TEST_F(DnsCacheImplTest, InvalidPort) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate(_, _)).Times(0); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoAddressIsNull())); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com:abc", DnsHostInfoAddressIsNull(), + onDnsResolutionComplete("foo.com:abc:80", DnsHostInfoAddressIsNull(), Network::DnsResolver::ResolutionStatus::Success)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, TestUtility::makeDnsResponse({})); } @@ -1381,13 +1384,15 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { EXPECT_CALL(*timeout_timer, disableTimer()); // Make sure the store gets the first insert. - EXPECT_CALL(*store, addOrUpdate("foo.com", "10.0.0.1:80|6|0", kNoTtl)); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); + EXPECT_CALL(*store, addOrUpdate("foo.com:80", "10.0.0.1:80|6|0", kNoTtl)); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete(DnsHostInfoEquals("10.0.0.1:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(6000), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -1407,9 +1412,10 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { // Address does not change. EXPECT_CALL(*timeout_timer, disableTimer()); - EXPECT_CALL(*store, addOrUpdate("foo.com", "10.0.0.1:80|6|0", kNoTtl)); + EXPECT_CALL(*store, addOrUpdate("foo.com:80", "10.0.0.1:80|6|0", kNoTtl)); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.1:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -1429,11 +1435,13 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { EXPECT_CALL(*timeout_timer, disableTimer()); // Make sure the store gets the updated addresses - EXPECT_CALL(*store, addOrUpdate("foo.com", "10.0.0.2:80|6|0\n10.0.0.1:80|6|0", kNoTtl)); - EXPECT_CALL(update_callbacks_, - onDnsHostAddOrUpdate("foo.com", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false))); + EXPECT_CALL(*store, addOrUpdate("foo.com:80", "10.0.0.2:80|6|0\n10.0.0.1:80|6|0", kNoTtl)); + EXPECT_CALL( + update_callbacks_, + onDnsHostAddOrUpdate("foo.com:80", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false))); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(dns_ttl_), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -1452,9 +1460,10 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { // Address does not change. EXPECT_CALL(*timeout_timer, disableTimer()); - EXPECT_CALL(*store, addOrUpdate("foo.com", "10.0.0.2:80|40|0\n10.0.0.1:80|40|0", kNoTtl)); + EXPECT_CALL(*store, addOrUpdate("foo.com:80", "10.0.0.2:80|40|0\n10.0.0.1:80|40|0", kNoTtl)); EXPECT_CALL(update_callbacks_, - onDnsResolutionComplete("foo.com", DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), + onDnsResolutionComplete("foo.com:80", + DnsHostInfoEquals("10.0.0.2:80", "foo.com", false), Network::DnsResolver::ResolutionStatus::Success)); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(40000), _)); resolve_cb(Network::DnsResolver::ResolutionStatus::Success, @@ -1480,13 +1489,13 @@ TEST_F(DnsCacheImplTest, CacheLoad) { store = ret.get(); // Make sure there's an attempt to load from the key value store. EXPECT_CALL(*store, iterate).WillOnce(Invoke([&](KeyValueStore::ConstIterateCb fn) { - fn("foo.com", "10.0.0.2:80|40|0"); - fn("bar.com", "1.1.1.1:1|20|1\n2.2.2.2:2|30|2"); + fn("foo.com:80", "10.0.0.2:80|40|0"); + fn("bar.com:80", "1.1.1.1:1|20|1\n2.2.2.2:2|30|2"); // No port. EXPECT_LOG_CONTAINS("warning", "Unable to parse cache line '1.1.1.1|20|1'", - fn("eep.com", "1.1.1.1|20|1")); + fn("eep.com:80", "1.1.1.1|20|1")); // Won't be loaded because of prior error. - fn("eep.com", "1.1.1.1|20|1:1"); + fn("eep.com:80", "1.1.1.1|20|1:1"); })); return ret; @@ -1532,6 +1541,19 @@ TEST(DnsCacheManagerImplTest, TestLifetime) { EXPECT_TRUE(cache_manager->getCache(config1) != nullptr); } +TEST(NoramlizeHost, NormalizeHost) { + EXPECT_EQ("localhost:80", DnsHostInfo::normalizeHostForDfp("localhost:80", 80)); + EXPECT_EQ("localhost:80", DnsHostInfo::normalizeHostForDfp("localhost:80", 443)); + EXPECT_EQ("localhost:443", DnsHostInfo::normalizeHostForDfp("localhost:443", 80)); + EXPECT_EQ("localhost:443", DnsHostInfo::normalizeHostForDfp("localhost:443", 443)); + EXPECT_EQ("localhost:123", DnsHostInfo::normalizeHostForDfp("localhost:123", 80)); + EXPECT_EQ("localhost:80", DnsHostInfo::normalizeHostForDfp("localhost", 80)); + EXPECT_EQ("localhost:443", DnsHostInfo::normalizeHostForDfp("localhost", 443)); + + EXPECT_EQ("[fc00::1]:443", DnsHostInfo::normalizeHostForDfp("[fc00::1]:443", 80)); + EXPECT_EQ("[fc00::1]:80", DnsHostInfo::normalizeHostForDfp("[fc00::1]", 80)); +} + } // namespace } // namespace DynamicForwardProxy } // namespace Common diff --git a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc index 38ee775b6174..8a4885eedf14 100644 --- a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc +++ b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc @@ -222,10 +222,12 @@ name: envoy.clusters.dynamic_forward_proxy ASSERT_FALSE(response->headers().get(Http::LowerCaseString("dns_start")).empty()); ASSERT_FALSE(response->headers().get(Http::LowerCaseString("dns_end")).empty()); - const Extensions::TransportSockets::Tls::SslHandshakerImpl* ssl_socket = - dynamic_cast( - fake_upstream_connection_->connection().ssl().get()); - EXPECT_STREQ("localhost", SSL_get_servername(ssl_socket->ssl(), TLSEXT_NAMETYPE_host_name)); + if (upstream_tls_) { + const Extensions::TransportSockets::Tls::SslHandshakerImpl* ssl_socket = + dynamic_cast( + fake_upstream_connection_->connection().ssl().get()); + EXPECT_STREQ("localhost", SSL_get_servername(ssl_socket->ssl(), TLSEXT_NAMETYPE_host_name)); + } } void requestWithUnknownDomainTest(const std::string& typed_dns_resolver_config = "") { @@ -256,7 +258,7 @@ name: envoy.clusters.dynamic_forward_proxy }; int64_t getHeaderValue(const Http::ResponseHeaderMap& headers, absl::string_view name) { - EXPECT_FALSE(headers.get(Http::LowerCaseString(name)).empty()); + EXPECT_FALSE(headers.get(Http::LowerCaseString(name)).empty()) << "Mising " << name; int64_t val; if (!headers.get(Http::LowerCaseString(name)).empty() && absl::SimpleAtoi(headers.get(Http::LowerCaseString(name))[0]->value().getStringView(), @@ -268,11 +270,11 @@ int64_t getHeaderValue(const Http::ResponseHeaderMap& headers, absl::string_view void ProxyFilterIntegrationTest::testConnectionTiming(IntegrationStreamDecoderPtr& response, bool cached_dns, int64_t original_usec) { + int64_t handshake_end; int64_t dns_start = getHeaderValue(response->headers(), "dns_start"); int64_t dns_end = getHeaderValue(response->headers(), "dns_end"); int64_t connect_start = getHeaderValue(response->headers(), "upstream_connect_start"); int64_t connect_end = getHeaderValue(response->headers(), "upstream_connect_complete"); - int64_t handshake_end = getHeaderValue(response->headers(), "upstream_handshake_complete"); int64_t request_send_end = getHeaderValue(response->headers(), "request_send_end"); int64_t response_begin = getHeaderValue(response->headers(), "response_begin"); Event::DispatcherImpl dispatcher("foo", *api_, timeSystem()); @@ -284,11 +286,14 @@ void ProxyFilterIntegrationTest::testConnectionTiming(IntegrationStreamDecoderPt } else { ASSERT_LE(dns_end, connect_start); } + if (upstream_tls_) { + handshake_end = getHeaderValue(response->headers(), "upstream_handshake_complete"); + ASSERT_LE(connect_end, handshake_end); + ASSERT_LE(handshake_end, request_send_end); + ASSERT_LT(handshake_end, timeSystem().monotonicTime().time_since_epoch().count()); + } ASSERT_LE(connect_start, connect_end); - ASSERT_LE(connect_end, handshake_end); - ASSERT_LE(handshake_end, request_send_end); ASSERT_LE(request_send_end, response_begin); - ASSERT_LT(handshake_end, timeSystem().monotonicTime().time_since_epoch().count()); } class ProxyFilterWithSimtimeIntegrationTest : public Event::TestUsingSimulatedTime, @@ -305,6 +310,23 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, ProxyFilterIntegrationTest, // should hit the TLS cache. TEST_P(ProxyFilterIntegrationTest, RequestWithBody) { requestWithBodyTest(); } +TEST_P(ProxyFilterIntegrationTest, MultiPortTest) { + upstream_tls_ = false; + requestWithBodyTest(); + + // Create a second upstream, and send a request there. + // The second upstream is autonomous where the first was not so we'll only get a 200-ok if we hit + // the new port. + // this regression tests https://github.com/envoyproxy/envoy/issues/27331 + autonomous_upstream_ = true; + createUpstream(Network::Test::getCanonicalLoopbackAddress(version_), upstreamConfig()); + default_request_headers_.setHost( + fmt::format("localhost:{}", fake_upstreams_[1]->localAddress()->ip()->port())); + auto response = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + ASSERT_TRUE(response->waitForEndStream()); + EXPECT_EQ("200", response->headers().getStatusValue()); +} + // Do a sanity check using the getaddrinfo() resolver. TEST_P(ProxyFilterIntegrationTest, RequestWithBodyGetAddrInfoResolver) { // getaddrinfo() does not reliably return v6 addresses depending on the environment. For now @@ -448,7 +470,7 @@ TEST_P(ProxyFilterIntegrationTest, DNSCacheHostOverflow) { // Verify that the filter works without TLS. TEST_P(ProxyFilterIntegrationTest, UpstreamCleartext) { - upstream_tls_ = true; + upstream_tls_ = false; initializeWithArgs(); codec_client_ = makeHttpConnection(lookupPort("http")); const Http::TestRequestHeaderMapImpl request_headers{ From c99607b614ba9dcb73204c06b190bc2d43389a1d Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 23 May 2023 13:06:09 -0400 Subject: [PATCH 054/228] mobile: removing unused test filters (#27550) Signed-off-by: Alyssa Wilk --- mobile/envoy_build_config/BUILD | 2 - mobile/envoy_build_config/test_extensions.cc | 4 -- .../filters/http/test_accessor/BUILD | 44 -------------- .../filters/http/test_accessor/config.cc | 28 --------- .../filters/http/test_accessor/config.h | 36 ------------ .../filters/http/test_accessor/filter.cc | 31 ---------- .../filters/http/test_accessor/filter.h | 46 --------------- .../filters/http/test_accessor/filter.proto | 10 ---- .../extensions/filters/http/test_read/BUILD | 42 -------------- .../filters/http/test_read/config.cc | 24 -------- .../filters/http/test_read/config.h | 33 ----------- .../filters/http/test_read/filter.cc | 57 ------------------- .../filters/http/test_read/filter.h | 35 ------------ .../filters/http/test_read/filter.proto | 6 -- 14 files changed, 398 deletions(-) delete mode 100644 mobile/library/common/extensions/filters/http/test_accessor/BUILD delete mode 100644 mobile/library/common/extensions/filters/http/test_accessor/config.cc delete mode 100644 mobile/library/common/extensions/filters/http/test_accessor/config.h delete mode 100644 mobile/library/common/extensions/filters/http/test_accessor/filter.cc delete mode 100644 mobile/library/common/extensions/filters/http/test_accessor/filter.h delete mode 100644 mobile/library/common/extensions/filters/http/test_accessor/filter.proto delete mode 100644 mobile/library/common/extensions/filters/http/test_read/BUILD delete mode 100644 mobile/library/common/extensions/filters/http/test_read/config.cc delete mode 100644 mobile/library/common/extensions/filters/http/test_read/config.h delete mode 100644 mobile/library/common/extensions/filters/http/test_read/filter.cc delete mode 100644 mobile/library/common/extensions/filters/http/test_read/filter.h delete mode 100644 mobile/library/common/extensions/filters/http/test_read/filter.proto diff --git a/mobile/envoy_build_config/BUILD b/mobile/envoy_build_config/BUILD index 3b3c27bddcf1..5f520f25a89f 100644 --- a/mobile/envoy_build_config/BUILD +++ b/mobile/envoy_build_config/BUILD @@ -117,11 +117,9 @@ envoy_cc_library( "@envoy//source/extensions/filters/http/buffer:config", "@envoy_mobile//library/common/extensions/filters/http/assertion:config", "@envoy_mobile//library/common/extensions/filters/http/route_cache_reset:config", - "@envoy_mobile//library/common/extensions/filters/http/test_accessor:config", "@envoy_mobile//library/common/extensions/filters/http/test_event_tracker:config", "@envoy_mobile//library/common/extensions/filters/http/test_kv_store:config", "@envoy_mobile//library/common/extensions/filters/http/test_logger:config", - "@envoy_mobile//library/common/extensions/filters/http/test_read:config", "@envoy_mobile//library/common/extensions/filters/http/test_remote_response:config", ], alwayslink = 1, diff --git a/mobile/envoy_build_config/test_extensions.cc b/mobile/envoy_build_config/test_extensions.cc index d0bb9c56087b..f97634722058 100644 --- a/mobile/envoy_build_config/test_extensions.cc +++ b/mobile/envoy_build_config/test_extensions.cc @@ -4,20 +4,16 @@ #include "external/envoy_build_config/test_extensions.h" #include "library/common/extensions/filters/http/assertion/config.h" #include "library/common/extensions/filters/http/route_cache_reset/config.h" -#include "library/common/extensions/filters/http/test_accessor/config.h" #include "library/common/extensions/filters/http/test_event_tracker/config.h" #include "library/common/extensions/filters/http/test_kv_store/config.h" #include "library/common/extensions/filters/http/test_logger/config.h" -#include "library/common/extensions/filters/http/test_read/config.h" void register_test_extensions() { Envoy::Extensions::HttpFilters::Assertion::forceRegisterAssertionFilterFactory(); Envoy::Extensions::HttpFilters::BufferFilter::forceRegisterBufferFilterFactory(); Envoy::Extensions::HttpFilters::RouteCacheReset::forceRegisterRouteCacheResetFilterFactory(); - Envoy::Extensions::HttpFilters::TestAccessor::forceRegisterTestAccessorFilterFactory(); Envoy::Extensions::HttpFilters::TestEventTracker::forceRegisterTestEventTrackerFilterFactory(); Envoy::Extensions::HttpFilters::TestKeyValueStore::forceRegisterTestKeyValueStoreFilterFactory(); Envoy::Extensions::HttpFilters::TestLogger::forceRegisterFactory(); - Envoy::HttpFilters::TestRead::forceRegisterTestReadFilterFactory(); Envoy::Upstream::forceRegisterStaticClusterFactory(); } diff --git a/mobile/library/common/extensions/filters/http/test_accessor/BUILD b/mobile/library/common/extensions/filters/http/test_accessor/BUILD deleted file mode 100644 index 977df4ab6783..000000000000 --- a/mobile/library/common/extensions/filters/http/test_accessor/BUILD +++ /dev/null @@ -1,44 +0,0 @@ -load( - "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", - "envoy_proto_library", -) - -licenses(["notice"]) # Apache 2 - -envoy_extension_package() - -envoy_proto_library( - name = "filter", - srcs = ["filter.proto"], - deps = [ - "@envoy_api//envoy/config/common/matcher/v3:pkg", - ], -) - -envoy_cc_extension( - name = "test_accessor_filter_lib", - srcs = ["filter.cc"], - hdrs = ["filter.h"], - repository = "@envoy", - deps = [ - "filter_cc_proto", - "//library/common/api:c_types", - "//library/common/api:external_api_lib", - "//library/common/data:utility_lib", - "@envoy//source/common/common:assert_lib", - "@envoy//source/extensions/filters/http/common:pass_through_filter_lib", - ], -) - -envoy_cc_extension( - name = "config", - srcs = ["config.cc"], - hdrs = ["config.h"], - repository = "@envoy", - deps = [ - ":test_accessor_filter_lib", - "@envoy//source/extensions/filters/http/common:factory_base_lib", - ], -) diff --git a/mobile/library/common/extensions/filters/http/test_accessor/config.cc b/mobile/library/common/extensions/filters/http/test_accessor/config.cc deleted file mode 100644 index 44deda4b9561..000000000000 --- a/mobile/library/common/extensions/filters/http/test_accessor/config.cc +++ /dev/null @@ -1,28 +0,0 @@ -#include "library/common/extensions/filters/http/test_accessor/config.h" - -#include "library/common/extensions/filters/http/test_accessor/filter.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace TestAccessor { - -Http::FilterFactoryCb TestAccessorFilterFactory::createFilterFactoryFromProtoTyped( - const envoymobile::extensions::filters::http::test_accessor::TestAccessor& proto_config, - const std::string&, Server::Configuration::FactoryContext&) { - - auto config = std::make_shared(proto_config); - return [config](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamFilter(std::make_shared(config)); - }; -} - -/** - * Static registration for the TestAccessor filter. @see NamedHttpFilterConfigFactory. - */ -REGISTER_FACTORY(TestAccessorFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory); - -} // namespace TestAccessor -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/config.h b/mobile/library/common/extensions/filters/http/test_accessor/config.h deleted file mode 100644 index 44bd26007b76..000000000000 --- a/mobile/library/common/extensions/filters/http/test_accessor/config.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include - -#include "source/extensions/filters/http/common/factory_base.h" - -#include "library/common/extensions/filters/http/test_accessor/filter.h" -#include "library/common/extensions/filters/http/test_accessor/filter.pb.h" -#include "library/common/extensions/filters/http/test_accessor/filter.pb.validate.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace TestAccessor { - -/** - * Config registration for the TestAccessor filter. @see NamedHttpFilterConfigFactory. - */ -class TestAccessorFilterFactory - : public Common::FactoryBase< - envoymobile::extensions::filters::http::test_accessor::TestAccessor> { -public: - TestAccessorFilterFactory() : FactoryBase("test_accessor") {} - -private: - ::Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped( - const envoymobile::extensions::filters::http::test_accessor::TestAccessor& config, - const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override; -}; - -DECLARE_FACTORY(TestAccessorFilterFactory); - -} // namespace TestAccessor -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.cc b/mobile/library/common/extensions/filters/http/test_accessor/filter.cc deleted file mode 100644 index e35f152dd004..000000000000 --- a/mobile/library/common/extensions/filters/http/test_accessor/filter.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include "library/common/extensions/filters/http/test_accessor/filter.h" - -#include "envoy/server/filter_config.h" - -#include "source/common/common/assert.h" - -#include "library/common/data/utility.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace TestAccessor { - -TestAccessorFilterConfig::TestAccessorFilterConfig( - const envoymobile::extensions::filters::http::test_accessor::TestAccessor& proto_config) - : accessor_(static_cast( - Api::External::retrieveApi(proto_config.accessor_name()))), - expected_string_(proto_config.expected_string()) {} - -Http::FilterHeadersStatus TestAccessorFilter::decodeHeaders(Http::RequestHeaderMap&, bool) { - RELEASE_ASSERT(config_->expectedString() == - Data::Utility::copyToString( - config_->accessor()->get_string(config_->accessor()->context)), - "accessed string is not equal to expected string"); - return Http::FilterHeadersStatus::Continue; -} - -} // namespace TestAccessor -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.h b/mobile/library/common/extensions/filters/http/test_accessor/filter.h deleted file mode 100644 index d5a7355c19e3..000000000000 --- a/mobile/library/common/extensions/filters/http/test_accessor/filter.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "envoy/http/filter.h" - -#include "source/extensions/filters/http/common/pass_through_filter.h" - -#include "library/common/api/c_types.h" -#include "library/common/api/external.h" -#include "library/common/extensions/filters/http/test_accessor/filter.pb.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace TestAccessor { - -class TestAccessorFilterConfig { -public: - TestAccessorFilterConfig( - const envoymobile::extensions::filters::http::test_accessor::TestAccessor& proto_config); - - const envoy_string_accessor* accessor() const { return accessor_; } - const std::string& expectedString() const { return expected_string_; } - -private: - const envoy_string_accessor* accessor_; - const std::string expected_string_; -}; - -using TestAccessorFilterConfigSharedPtr = std::shared_ptr; - -class TestAccessorFilter final : public ::Envoy::Http::PassThroughFilter { -public: - TestAccessorFilter(TestAccessorFilterConfigSharedPtr config) : config_(config) {} - - // StreamDecoderFilter - ::Envoy::Http::FilterHeadersStatus decodeHeaders(::Envoy::Http::RequestHeaderMap& headers, - bool end_stream) override; - -private: - const TestAccessorFilterConfigSharedPtr config_; -}; - -} // namespace TestAccessor -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.proto b/mobile/library/common/extensions/filters/http/test_accessor/filter.proto deleted file mode 100644 index 938da1b89d95..000000000000 --- a/mobile/library/common/extensions/filters/http/test_accessor/filter.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; - -package envoymobile.extensions.filters.http.test_accessor; - -import "validate/validate.proto"; - -message TestAccessor { - string accessor_name = 1 [(validate.rules).string.min_len = 1]; - string expected_string = 2 [(validate.rules).string.min_len = 1]; -} diff --git a/mobile/library/common/extensions/filters/http/test_read/BUILD b/mobile/library/common/extensions/filters/http/test_read/BUILD deleted file mode 100644 index 54324cca68ac..000000000000 --- a/mobile/library/common/extensions/filters/http/test_read/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -load( - "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", - "envoy_proto_library", -) - -licenses(["notice"]) # Apache 2 - -envoy_extension_package() - -envoy_proto_library( - name = "filter", - srcs = ["filter.proto"], - deps = [ - "@envoy_api//envoy/config/common/matcher/v3:pkg", - ], -) - -envoy_cc_extension( - name = "test_read_filter_lib", - srcs = ["filter.cc"], - hdrs = ["filter.h"], - repository = "@envoy", - deps = [ - "filter_cc_proto", - "@envoy//source/common/http:utility_lib", - "@envoy//source/common/stream_info:stream_info_lib", - "@envoy//source/extensions/filters/http/common:pass_through_filter_lib", - ], -) - -envoy_cc_extension( - name = "config", - srcs = ["config.cc"], - hdrs = ["config.h"], - repository = "@envoy", - deps = [ - ":test_read_filter_lib", - "@envoy//source/extensions/filters/http/common:factory_base_lib", - ], -) diff --git a/mobile/library/common/extensions/filters/http/test_read/config.cc b/mobile/library/common/extensions/filters/http/test_read/config.cc deleted file mode 100644 index 3c5ce3c402f8..000000000000 --- a/mobile/library/common/extensions/filters/http/test_read/config.cc +++ /dev/null @@ -1,24 +0,0 @@ -#include "library/common/extensions/filters/http/test_read/config.h" - -#include "library/common/extensions/filters/http/test_read/filter.h" - -namespace Envoy { -namespace HttpFilters { -namespace TestRead { - -Http::FilterFactoryCb TestReadFilterFactory::createFilterFactoryFromProtoTyped( - const envoymobile::test::integration::filters::http::test_read::TestRead& /*config*/, - const std::string&, Server::Configuration::FactoryContext& /*context*/) { - return [](Http::FilterChainFactoryCallbacks& callbacks) -> void { - callbacks.addStreamDecoderFilter(std::make_shared()); - }; -} - -/** - * Static registration for the TestRead filter. @see NamedHttpFilterConfigFactory. - */ -REGISTER_FACTORY(TestReadFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory); - -} // namespace TestRead -} // namespace HttpFilters -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/config.h b/mobile/library/common/extensions/filters/http/test_read/config.h deleted file mode 100644 index 24e22d706cb1..000000000000 --- a/mobile/library/common/extensions/filters/http/test_read/config.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -#include "source/extensions/filters/http/common/factory_base.h" - -#include "library/common/extensions/filters/http/test_read/filter.pb.h" -#include "library/common/extensions/filters/http/test_read/filter.pb.validate.h" - -namespace Envoy { -namespace HttpFilters { -namespace TestRead { - -/** - * Config registration for the TestRead filter. @see NamedHttpFilterConfigFactory. - */ -class TestReadFilterFactory - : public Envoy::Extensions::HttpFilters::Common::FactoryBase< - envoymobile::test::integration::filters::http::test_read::TestRead> { -public: - TestReadFilterFactory() : FactoryBase("test_read") {} - -private: - ::Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped( - const envoymobile::test::integration::filters::http::test_read::TestRead& config, - const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override; -}; - -DECLARE_FACTORY(TestReadFilterFactory); - -} // namespace TestRead -} // namespace HttpFilters -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.cc b/mobile/library/common/extensions/filters/http/test_read/filter.cc deleted file mode 100644 index fb7c42752727..000000000000 --- a/mobile/library/common/extensions/filters/http/test_read/filter.cc +++ /dev/null @@ -1,57 +0,0 @@ -#include "library/common/extensions/filters/http/test_read/filter.h" - -#include "envoy/server/filter_config.h" - -namespace Envoy { -namespace HttpFilters { -namespace TestRead { - -Http::FilterHeadersStatus TestReadFilter::decodeHeaders(Http::RequestHeaderMap& request_headers, - bool) { - // sample path is /failed?error=0x10000 - Http::Utility::QueryParams query_parameters = - Http::Utility::parseQueryString(request_headers.Path()->value().getStringView()); - auto error = query_parameters.find("error"); - uint64_t response_flag; - if (error != query_parameters.end() && absl::SimpleAtoi(error->second, &response_flag)) { - // set response error code - StreamInfo::StreamInfo& stream_info = decoder_callbacks_->streamInfo(); - stream_info.setResponseFlag(TestReadFilter::mapErrorToResponseFlag(response_flag)); - - // check if we want a quic server error: sample path is /failed?quic=1&error=0x10000 - if (query_parameters.find("quic") != query_parameters.end()) { - stream_info.setUpstreamInfo(std::make_shared()); - stream_info.upstreamInfo()->setUpstreamProtocol(Http::Protocol::Http3); - } - - // trigger the error and stop iteration to other filters - decoder_callbacks_->sendLocalReply(Http::Code::BadRequest, "test_read filter threw: ", nullptr, - absl::nullopt, ""); - return Http::FilterHeadersStatus::StopIteration; - } - - // continue to other filters since the provided query string is invalid for error simulation - return Http::FilterHeadersStatus::Continue; -} - -StreamInfo::ResponseFlag TestReadFilter::mapErrorToResponseFlag(uint64_t errorCode) { - switch (errorCode) { - case 0x4000000: - return StreamInfo::DnsResolutionFailed; - case 0x40: - return StreamInfo::UpstreamConnectionTermination; - case 0x20: - return StreamInfo::UpstreamConnectionFailure; - case 0x10: - return StreamInfo::UpstreamRemoteReset; - case 0x10000: - return StreamInfo::StreamIdleTimeout; - default: - // Any other error that we aren't interested in. I picked a random error. - return StreamInfo::RateLimitServiceError; - } -} - -} // namespace TestRead -} // namespace HttpFilters -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.h b/mobile/library/common/extensions/filters/http/test_read/filter.h deleted file mode 100644 index dc5c2e73cea2..000000000000 --- a/mobile/library/common/extensions/filters/http/test_read/filter.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "envoy/http/filter.h" - -#include "source/common/common/logger.h" -#include "source/common/http/utility.h" -#include "source/common/stream_info/stream_info_impl.h" -#include "source/extensions/filters/http/common/pass_through_filter.h" - -#include "library/common/extensions/filters/http/test_read/filter.pb.h" - -namespace Envoy { -namespace HttpFilters { -namespace TestRead { - -/** - * This is a test-only filter to return specified error code based on a request url query string. - * It either simulates the requested error if the url query matches the error patterns - * or does nothing - */ -class TestReadFilter final : public Http::PassThroughFilter, - public Logger::Loggable { -public: - Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& request_headers, bool) override; - -private: - /* A mapping of the envoymobile errors we care about for testing - * From https://github.com/envoyproxy/envoy/blob/main/envoy/stream_info/stream_info.h - */ - StreamInfo::ResponseFlag mapErrorToResponseFlag(uint64_t errorCode); -}; - -} // namespace TestRead -} // namespace HttpFilters -} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.proto b/mobile/library/common/extensions/filters/http/test_read/filter.proto deleted file mode 100644 index de164df7d450..000000000000 --- a/mobile/library/common/extensions/filters/http/test_read/filter.proto +++ /dev/null @@ -1,6 +0,0 @@ -syntax = "proto3"; - -package envoymobile.test.integration.filters.http.test_read; - -message TestRead { -} From 17e5ff881d11463b8af817e918d46b8b65fce4d6 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Wed, 24 May 2023 01:21:46 +0800 Subject: [PATCH 055/228] ci: fix the flaky of TcpProxyOdcdsIntegrationTest.ShutdownAllConnectionsOnClusterLookupTimeout (#27578) Signed-off-by: He Jie Xu --- test/integration/tcp_proxy_odcds_integration_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/tcp_proxy_odcds_integration_test.cc b/test/integration/tcp_proxy_odcds_integration_test.cc index e4081b5bf10c..7eab2092ef6a 100644 --- a/test/integration/tcp_proxy_odcds_integration_test.cc +++ b/test/integration/tcp_proxy_odcds_integration_test.cc @@ -303,8 +303,8 @@ TEST_P(TcpProxyOdcdsIntegrationTest, ShutdownAllConnectionsOnClusterLookupTimeou IntegrationTcpClientPtr tcp_client_2 = makeTcpConnection(lookupPort("tcp_proxy")); test_server_->waitForCounterEq("tcp.tcpproxy_stats.on_demand_cluster_attempt", 2); - tcp_client_1->waitForHalfClose(); - tcp_client_2->waitForHalfClose(); + tcp_client_1->waitForHalfClose(true); + tcp_client_2->waitForHalfClose(true); assertOnDemandCounters(0, 0, 2); tcp_client_1->close(); tcp_client_2->close(); From 7c4bbe1785ad41a868dec0b66f4ea06e802bce95 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Tue, 23 May 2023 10:40:29 -0700 Subject: [PATCH 056/228] bazel: remove tags from repository definition (#27583) I don't think these do anything here except for produce this warning: ``` DEBUG: Rule 'com_github_bufbuild_buf' indicated that a canonical reproducible form can be obtained by dropping arguments ["tags"] DEBUG: Repository com_github_bufbuild_buf instantiated at: /Users/ksmiley/dev/envoy4/WORKSPACE:9:23: in /Users/ksmiley/dev/envoy4/bazel/api_repositories.bzl:4:21: in envoy_api_dependencies /private/var/tmp/_bazel_ksmiley/81424bb29de8eeef22a825a179047d5f/external/envoy_api/bazel/repositories.bzl:47:26: in api_dependencies /private/var/tmp/_bazel_ksmiley/81424bb29de8eeef22a825a179047d5f/external/envoy_api/bazel/repositories.bzl:9:23: in external_http_archive /private/var/tmp/_bazel_ksmiley/81424bb29de8eeef22a825a179047d5f/external/envoy_api/bazel/envoy_http_archive.bzl:16:17: in envoy_http_archive ``` Signed-off-by: Keith Smiley --- api/bazel/repositories.bzl | 1 - api/bazel/repository_locations.bzl | 1 - 2 files changed, 2 deletions(-) diff --git a/api/bazel/repositories.bzl b/api/bazel/repositories.bzl index b23156e21f12..b49db8c59a0c 100644 --- a/api/bazel/repositories.bzl +++ b/api/bazel/repositories.bzl @@ -47,7 +47,6 @@ def api_dependencies(): external_http_archive( name = "com_github_bufbuild_buf", build_file_content = BUF_BUILD_CONTENT, - tags = ["manual"], ) PROMETHEUSMETRICS_BUILD_CONTENT = """ diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index 45015ca109f1..c259e3633f93 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -137,7 +137,6 @@ REPOSITORY_LOCATIONS_SPEC = dict( urls = ["https://github.com/bufbuild/buf/releases/download/v{version}/buf-Linux-x86_64.tar.gz"], release_date = "2023-02-09", use_category = ["api"], - tags = ["manual"], license = "Apache-2.0", license_url = "https://github.com/bufbuild/buf/blob/v{version}/LICENSE", ), From 67e4108c3a78c75cfc2237f876a316115429e1de Mon Sep 17 00:00:00 2001 From: Chris Schoener Date: Tue, 23 May 2023 15:48:47 -0400 Subject: [PATCH 057/228] Mobile: Replace direct response APIs with test server in Swift (#27429) This is a followup to #25582 We migrate the swift tests to use a mock test server. And then delete the direct response engine builder functionality entirely. Signed-off-by: caschoener --- mobile/bazel/apple.bzl | 3 +- mobile/library/cc/engine_builder.cc | 131 ------------------ mobile/library/cc/engine_builder.h | 5 - .../library/objective-c/EnvoyConfiguration.h | 3 - .../library/objective-c/EnvoyConfiguration.mm | 7 - mobile/library/swift/BUILD | 1 - mobile/library/swift/EngineBuilder.swift | 15 -- mobile/library/swift/TestEngineBuilder.swift | 19 --- mobile/test/common/integration/test_server.cc | 31 +++-- mobile/test/common/integration/test_server.h | 17 ++- .../integration/test_server_interface.cc | 23 ++- .../integration/test_server_interface.h | 9 +- mobile/test/common/jni/test_jni_interface.cc | 19 +-- .../engine/testing/QuicTestServerTest.java | 4 +- .../envoymobile/engine/testing/TestJni.java | 26 +--- .../test/kotlin/integration/SendDataTest.kt | 2 +- mobile/test/objective-c/BUILD | 16 ++- mobile/test/objective-c/EnvoyTestServer.h | 17 +++ mobile/test/objective-c/EnvoyTestServer.mm | 25 ++++ mobile/test/swift/integration/BUILD | 80 +---------- ...eContainsHeadersMatchIntegrationTest.swift | 60 -------- ...onseExactHeadersMatchIntegrationTest.swift | 59 -------- ...esponseExactPathMatchIntegrationTest.swift | 53 ------- ...esponseFilterMutationIntegrationTest.swift | 93 ------------- ...nsePrefixHeadersMatchIntegrationTest.swift | 59 -------- ...nseSuffixHeadersMatchIntegrationTest.swift | 59 -------- ...est.swift => EndToEndNetworkingTest.swift} | 25 ++-- 27 files changed, 154 insertions(+), 707 deletions(-) delete mode 100644 mobile/library/swift/TestEngineBuilder.swift create mode 100644 mobile/test/objective-c/EnvoyTestServer.h create mode 100644 mobile/test/objective-c/EnvoyTestServer.mm delete mode 100644 mobile/test/swift/integration/DirectResponseContainsHeadersMatchIntegrationTest.swift delete mode 100644 mobile/test/swift/integration/DirectResponseExactHeadersMatchIntegrationTest.swift delete mode 100644 mobile/test/swift/integration/DirectResponseExactPathMatchIntegrationTest.swift delete mode 100644 mobile/test/swift/integration/DirectResponseFilterMutationIntegrationTest.swift delete mode 100644 mobile/test/swift/integration/DirectResponsePrefixHeadersMatchIntegrationTest.swift delete mode 100644 mobile/test/swift/integration/DirectResponseSuffixHeadersMatchIntegrationTest.swift rename mobile/test/swift/integration/{DirectResponsePrefixPathMatchIntegrationTest.swift => EndToEndNetworkingTest.swift} (70%) diff --git a/mobile/bazel/apple.bzl b/mobile/bazel/apple.bzl index 209c8f31cedf..33945b329e7b 100644 --- a/mobile/bazel/apple.bzl +++ b/mobile/bazel/apple.bzl @@ -3,7 +3,7 @@ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") load("@envoy//bazel:envoy_build_system.bzl", "envoy_mobile_defines") load("//bazel:config.bzl", "MINIMUM_IOS_VERSION") -def envoy_objc_library(name, hdrs = [], visibility = [], data = [], deps = [], module_name = None, sdk_frameworks = [], srcs = []): +def envoy_objc_library(name, hdrs = [], visibility = [], data = [], deps = [], module_name = None, sdk_frameworks = [], srcs = [], testonly = False): native.objc_library( name = name, srcs = srcs, @@ -15,6 +15,7 @@ def envoy_objc_library(name, hdrs = [], visibility = [], data = [], deps = [], m visibility = visibility, data = data, deps = deps, + testonly = testonly, ) # Macros providing a way to easily/consistently define Swift/ObjC unit test targets. diff --git a/mobile/library/cc/engine_builder.cc b/mobile/library/cc/engine_builder.cc index 767132fb2d4f..bc4bce48509c 100644 --- a/mobile/library/cc/engine_builder.cc +++ b/mobile/library/cc/engine_builder.cc @@ -286,12 +286,6 @@ EngineBuilder& EngineBuilder::setRuntimeGuard(std::string guard, bool value) { return *this; } -EngineBuilder& -EngineBuilder::addDirectResponse(DirectResponseTesting::DirectResponse direct_response) { - direct_responses_.push_back(direct_response); - return *this; -} - EngineBuilder& EngineBuilder::setOverrideConfigForTests(std::string config) { config_override_for_tests_ = std::move(config); return *this; @@ -319,46 +313,6 @@ std::unique_ptr EngineBuilder::generate remote_service->set_name("remote_service"); remote_service->add_domains("127.0.0.1"); - for (auto& direct_response_in : direct_responses_) { - auto* direct_response_route = remote_service->add_routes(); - auto* direct_response = direct_response_route->mutable_direct_response(); - direct_response->set_status(direct_response_in.status); - direct_response->mutable_body()->set_inline_string(direct_response_in.body); - auto* direct_response_route_match = direct_response_route->mutable_match(); - auto matcher = direct_response_in.matcher; - if (!matcher.fullPath.empty()) { - direct_response_route_match->set_path(matcher.fullPath); - } else if (!matcher.pathPrefix.empty()) { - direct_response_route_match->set_prefix(matcher.pathPrefix); - } - - for (auto& header : matcher.headers) { - auto* direct_response_headers = direct_response_route_match->add_headers(); - direct_response_headers->set_name(header.name); - switch (header.mode) { - case DirectResponseTesting::MatchMode::Contains: - direct_response_headers->set_contains_match(header.value); - break; - case DirectResponseTesting::MatchMode::Exact: - direct_response_headers->set_exact_match(header.value); - break; - case DirectResponseTesting::MatchMode::Prefix: - direct_response_headers->set_prefix_match(header.value); - break; - case DirectResponseTesting::MatchMode::Suffix: - direct_response_headers->set_suffix_match(header.value); - break; - } - } - - for (auto& header_in : direct_response_in.headers) { - auto* resp_header = direct_response_route->add_response_headers_to_add(); - auto* header = resp_header->mutable_header(); - header->set_key(header_in.first); - header->set_value(header_in.second); - } - } - auto* route = remote_service->add_routes(); route->mutable_match()->set_prefix("/"); route->mutable_direct_response()->set_status(404); @@ -370,38 +324,6 @@ std::unique_ptr EngineBuilder::generate api_service->set_include_attempt_count_in_response(true); api_service->add_domains("*"); - for (auto& direct_response_in : direct_responses_) { - auto* this_route = api_service->add_routes(); - auto* mutable_route = this_route->mutable_route(); - mutable_route->set_cluster("fake_remote"); - auto* direct_response_route_match = this_route->mutable_match(); - auto matcher = direct_response_in.matcher; - if (!matcher.fullPath.empty()) { - direct_response_route_match->set_path(matcher.fullPath); - } else if (!matcher.pathPrefix.empty()) { - direct_response_route_match->set_prefix(matcher.pathPrefix); - } - - for (auto& header : matcher.headers) { - auto* direct_response_headers = direct_response_route_match->add_headers(); - direct_response_headers->set_name(header.name); - switch (header.mode) { - case DirectResponseTesting::MatchMode::Contains: - direct_response_headers->set_contains_match(header.value); - break; - case DirectResponseTesting::MatchMode::Exact: - direct_response_headers->set_exact_match(header.value); - break; - case DirectResponseTesting::MatchMode::Prefix: - direct_response_headers->set_prefix_match(header.value); - break; - case DirectResponseTesting::MatchMode::Suffix: - direct_response_headers->set_suffix_match(header.value); - break; - } - } - } - route = api_service->add_routes(); route->mutable_match()->set_prefix("/"); route->add_request_headers_to_remove("x-forwarded-proto"); @@ -540,14 +462,6 @@ std::unique_ptr EngineBuilder::generate tag_filter->mutable_typed_config()->PackFrom(tag_config); } - if (!direct_responses_.empty()) { - auto* cache_reset_filter = hcm->add_http_filters(); - cache_reset_filter->set_name("envoy.filters.http.route_cache_reset"); - cache_reset_filter->mutable_typed_config()->set_type_url( - "type.googleapis.com/" - "envoymobile.extensions.filters.http.route_cache_reset.RouteCacheReset"); - } - // Set up the always-present filters envoymobile::extensions::filters::http::network_configuration::NetworkConfiguration network_config; @@ -617,35 +531,6 @@ std::unique_ptr EngineBuilder::generate auto* static_resources = bootstrap->mutable_static_resources(); - if (!direct_responses_.empty()) { - auto* fake_remote_listener = static_resources->add_listeners(); - fake_remote_listener->set_name("fake_remote_listener"); - auto* base_address = fake_remote_listener->mutable_address(); - base_address->mutable_socket_address()->set_address("127.0.0.1"); - base_address->mutable_socket_address()->set_port_value(10101); - auto* filter = fake_remote_listener->add_filter_chains()->add_filters(); - envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager - fake_remote_listener_config; - filter->set_name("envoy.filters.network.http_connection_manager"); - fake_remote_listener_config.set_stat_prefix("remote_hcm"); - auto* route_config = fake_remote_listener_config.mutable_route_config(); - route_config->set_name("remote_route"); - auto* virtual_host = route_config->add_virtual_hosts(); - virtual_host->add_domains("*"); - virtual_host->set_name("remote_service"); - auto* route = virtual_host->add_routes(); - route->mutable_match()->set_prefix("/"); - route->mutable_direct_response()->set_status(404); - route->mutable_direct_response()->mutable_body()->set_inline_string("not found"); - route->add_request_headers_to_remove("x-forwarded-proto"); - route->add_request_headers_to_remove("x-envoy-mobile-cluster"); - auto* router_filter = fake_remote_listener_config.add_http_filters(); - envoy::extensions::filters::http::router::v3::Router router_config; - router_filter->set_name("envoy.router"); - router_filter->mutable_typed_config()->PackFrom(router_config); - filter->mutable_typed_config()->PackFrom(fake_remote_listener_config); - } - // Finally create the base listener, and point it at the HCM. auto* base_listener = static_resources->add_listeners(); base_listener->set_name("base_api_listener"); @@ -696,22 +581,6 @@ std::unique_ptr EngineBuilder::generate base_tls_socket.set_name("envoy.transport_sockets.http_11_proxy"); base_tls_socket.mutable_typed_config()->PackFrom(ssl_proxy_socket); - if (!direct_responses_.empty()) { - // fake remote cluster - auto* fake_remote_cluster = static_resources->add_clusters(); - fake_remote_cluster->set_name("fake_remote"); - fake_remote_cluster->set_type(envoy::config::cluster::v3::Cluster::LOGICAL_DNS); - fake_remote_cluster->mutable_connect_timeout()->set_seconds(30); - fake_remote_cluster->mutable_load_assignment()->set_cluster_name("fake_remote"); - auto* address = fake_remote_cluster->mutable_load_assignment() - ->add_endpoints() - ->add_lb_endpoints() - ->mutable_endpoint() - ->mutable_address(); - address->mutable_socket_address()->set_address("127.0.0.1"); - address->mutable_socket_address()->set_port_value(10101); - } - envoy::extensions::upstreams::http::v3::HttpProtocolOptions h2_protocol_options; h2_protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options(); if (!stats_domain_.empty()) { diff --git a/mobile/library/cc/engine_builder.h b/mobile/library/cc/engine_builder.h index 63dcc36374ac..4eedcaac8296 100644 --- a/mobile/library/cc/engine_builder.h +++ b/mobile/library/cc/engine_builder.h @@ -104,10 +104,6 @@ class EngineBuilder { EngineBuilder& setRuntimeGuard(std::string guard, bool value); - // Add a direct response. For testing purposes only. - // TODO(jpsim): Move this out of the main engine builder API - EngineBuilder& addDirectResponse(DirectResponseTesting::DirectResponse direct_response); - // These functions don't affect the Bootstrap configuration but instead perform registrations. EngineBuilder& addKeyValueStore(std::string name, KeyValueStoreSharedPtr key_value_store); EngineBuilder& addStringAccessor(std::string name, StringAccessorSharedPtr accessor); @@ -189,7 +185,6 @@ class EngineBuilder { std::vector native_filter_chain_; std::vector dns_preresolve_hostnames_; - std::vector direct_responses_; std::vector> runtime_guards_; absl::flat_hash_map string_accessors_; diff --git a/mobile/library/objective-c/EnvoyConfiguration.h b/mobile/library/objective-c/EnvoyConfiguration.h index 313f77ab1ba5..7c2afa305c42 100644 --- a/mobile/library/objective-c/EnvoyConfiguration.h +++ b/mobile/library/objective-c/EnvoyConfiguration.h @@ -39,7 +39,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong) NSString *appVersion; @property (nonatomic, strong) NSString *appId; @property (nonatomic, strong) NSDictionary *runtimeGuards; -@property (nonatomic, strong) NSArray *typedDirectResponses; @property (nonatomic, strong) NSArray *nativeFilterChain; @property (nonatomic, strong) NSArray *httpPlatformFilterFactories; @property (nonatomic, strong) NSDictionary *stringAccessors; @@ -94,8 +93,6 @@ NS_ASSUME_NONNULL_BEGIN appId:(NSString *)appId runtimeGuards: (NSDictionary *)runtimeGuards - typedDirectResponses: - (NSArray *)typedDirectResponses nativeFilterChain: (NSArray *)nativeFilterChain platformFilterChain: diff --git a/mobile/library/objective-c/EnvoyConfiguration.mm b/mobile/library/objective-c/EnvoyConfiguration.mm index aa76f9135d75..b75d01bb85a2 100644 --- a/mobile/library/objective-c/EnvoyConfiguration.mm +++ b/mobile/library/objective-c/EnvoyConfiguration.mm @@ -97,8 +97,6 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled appId:(NSString *)appId runtimeGuards: (NSDictionary *)runtimeGuards - typedDirectResponses: - (NSArray *)typedDirectResponses nativeFilterChain: (NSArray *)nativeFilterChain platformFilterChain: @@ -160,7 +158,6 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled self.appVersion = appVersion; self.appId = appId; self.runtimeGuards = runtimeGuards; - self.typedDirectResponses = typedDirectResponses; self.nativeFilterChain = nativeFilterChain; self.httpPlatformFilterFactories = httpPlatformFilterFactories; self.stringAccessors = stringAccessors; @@ -211,10 +208,6 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled builder.setRuntimeGuard([key toCXXString], value); } - for (EMODirectResponse *directResponse in self.typedDirectResponses) { - builder.addDirectResponse([directResponse toCXX]); - } - builder.addConnectTimeoutSeconds(self.connectTimeoutSeconds); builder.addDnsFailureRefreshSeconds(self.dnsFailureRefreshSecondsBase, diff --git a/mobile/library/swift/BUILD b/mobile/library/swift/BUILD index 9ddeb5d61ca0..58b660e7b607 100644 --- a/mobile/library/swift/BUILD +++ b/mobile/library/swift/BUILD @@ -44,7 +44,6 @@ swift_library( "StreamClientImpl.swift", "StreamIntel.swift", "StreamPrototype.swift", - "TestEngineBuilder.swift", "Trailers.swift", "extensions/UserDefaults+KeyValueStore.swift", "filters/AsyncRequestFilter.swift", diff --git a/mobile/library/swift/EngineBuilder.swift b/mobile/library/swift/EngineBuilder.swift index 2e187639be2a..806548792066 100644 --- a/mobile/library/swift/EngineBuilder.swift +++ b/mobile/library/swift/EngineBuilder.swift @@ -59,7 +59,6 @@ open class EngineBuilder: NSObject { private var stringAccessors: [String: EnvoyStringAccessor] = [:] private var keyValueStores: [String: EnvoyKeyValueStore] = [:] private var runtimeGuards: [String: Bool] = [:] - private var directResponses: [DirectResponse] = [] private var statsSinks: [String] = [] private var rtdsLayerName: String? private var rtdsTimeoutSeconds: UInt32 = 0 @@ -693,15 +692,6 @@ open class EngineBuilder: NSObject { return self } - /// Add a direct response to be used when configuring the engine. - /// This function is internal so it is not publicly exposed to production builders, - /// but is available for use by the `TestEngineBuilder`. - /// - /// - parameter directResponse: The response configuration to add. - func addDirectResponseInternal(_ directResponse: DirectResponse) { - self.directResponses.append(directResponse) - } - func makeConfig() -> EnvoyConfiguration { EnvoyConfiguration( adminInterfaceEnabled: self.adminInterfaceEnabled, @@ -733,7 +723,6 @@ open class EngineBuilder: NSObject { appVersion: self.appVersion, appId: self.appId, runtimeGuards: self.runtimeGuards.mapValues({ "\($0)" }), - typedDirectResponses: self.directResponses.map({ $0.toObjC() }), nativeFilterChain: self.nativeFilterChain, platformFilterChain: self.platformFilterChain, stringAccessors: self.stringAccessors, @@ -816,10 +805,6 @@ private extension EngineBuilder { cxxBuilder.setRuntimeGuard(runtimeGuard.toCXX(), value) } - for directResponse in self.directResponses { - cxxBuilder.addDirectResponse(directResponse.toCXX()) - } - for filter in self.nativeFilterChain.reversed() { cxxBuilder.addNativeFilter(filter.name.toCXX(), filter.typedConfig.toCXX()) } diff --git a/mobile/library/swift/TestEngineBuilder.swift b/mobile/library/swift/TestEngineBuilder.swift deleted file mode 100644 index e654764b1b10..000000000000 --- a/mobile/library/swift/TestEngineBuilder.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Foundation - -/// Builder that can be used to construct instances of the Envoy engine -/// which have the added functionality of returning "direct" responses to -/// requests over a local connection. This can be particularly useful for mocking/testing. -public final class TestEngineBuilder: EngineBuilder { - /// Adds a direct response configuration which will be used when starting the engine. - /// Doing so will cause Envoy to clear its route cache for each stream in order to allow - /// filters to mutate headers (which can subsequently affect routing). - /// - /// - parameter response: The response configuration to add. - /// - /// - returns: This builder. - @discardableResult - public func addDirectResponse(_ response: DirectResponse) -> Self { - self.addDirectResponseInternal(response) - return self - } -} diff --git a/mobile/test/common/integration/test_server.cc b/mobile/test/common/integration/test_server.cc index f47ef32aeb00..de0847c1821a 100644 --- a/mobile/test/common/integration/test_server.cc +++ b/mobile/test/common/integration/test_server.cc @@ -4,6 +4,7 @@ #include "test/integration/server.h" #include "test/test_common/environment.h" +#include "test/test_common/network_utility.h" namespace Envoy { @@ -58,29 +59,35 @@ TestServer::TestServer() .WillByDefault(testing::ReturnRef(*stats_store_.rootScope())); } -void TestServer::startTestServer(bool use_quic) { +void TestServer::startTestServer(TestServerType test_server_type) { ASSERT(!upstream_); // pre-setup: see https://github.com/envoyproxy/envoy/blob/main/test/test_runner.cc Logger::Context logging_state(spdlog::level::level_enum::err, "[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v", lock, false, false); // end pre-setup + Network::DownstreamTransportSocketFactoryPtr factory; - if (use_quic) { + switch (test_server_type) { + case TestServerType::HTTP3: upstream_config_.upstream_protocol_ = Http::CodecType::HTTP3; upstream_config_.udp_fake_upstream_ = FakeUpstreamConfig::UdpConfig(); - } else { + factory = createQuicUpstreamTlsContext(factory_context_); + break; + case TestServerType::HTTP2_WITH_TLS: upstream_config_.upstream_protocol_ = Http::CodecType::HTTP2; + factory = createUpstreamTlsContext(factory_context_); + break; + case TestServerType::HTTP1_WITHOUT_TLS: + upstream_config_.upstream_protocol_ = Http::CodecType::HTTP1; + factory = Network::Test::createRawBufferDownstreamSocketFactory(); + break; } - Network::DownstreamTransportSocketFactoryPtr factory = - use_quic ? createQuicUpstreamTlsContext(factory_context_) - : createUpstreamTlsContext(factory_context_); - upstream_ = std::make_unique(std::move(factory), port_, version_, upstream_config_, true); // Legacy behavior for cronet tests. - if (use_quic) { + if (test_server_type == TestServerType::HTTP3) { upstream_->setResponseHeaders( std::make_unique(Http::TestResponseHeaderMapImpl( {{":status", "200"}, @@ -102,4 +109,12 @@ int TestServer::getServerPort() { ASSERT(upstream_); return upstream_->localAddress()->ip()->port(); } + +void TestServer::setHeadersAndData(absl::string_view header_key, absl::string_view header_value, + absl::string_view response_body) { + upstream_->setResponseHeaders( + std::make_unique(Http::TestResponseHeaderMapImpl( + {{std::string(header_key), std::string(header_value)}, {":status", "200"}}))); + upstream_->setResponseBody(std::string(response_body)); +} } // namespace Envoy diff --git a/mobile/test/common/integration/test_server.h b/mobile/test/common/integration/test_server.h index cc90122b89b0..ff5411c7ad39 100644 --- a/mobile/test/common/integration/test_server.h +++ b/mobile/test/common/integration/test_server.h @@ -10,6 +10,13 @@ #include "test/mocks/server/transport_socket_factory_context.h" namespace Envoy { + +enum class TestServerType { + HTTP1_WITHOUT_TLS, + HTTP2_WITH_TLS, + HTTP3, +}; + class TestServer { private: testing::NiceMock factory_context_; @@ -37,8 +44,9 @@ class TestServer { /** * Starts the server. Can only have one server active per JVM. This is blocking until the port can * start accepting requests. + * test_server_type: selects between HTTP3, HTTP2, or HTTP1 without TLS */ - void startTestServer(bool use_quic); + void startTestServer(TestServerType test_server_type); /** * Shutdowns the server. Can be restarted later. This is blocking until the server has freed all @@ -50,6 +58,13 @@ class TestServer { * Returns the port that got attributed. Can only be called once the server has been started. */ int getServerPort(); + + /** + * Sets headers and data for the test server to return on all future requests. + * Can only be called once the server has been started. + */ + void setHeadersAndData(absl::string_view header_key, absl::string_view header_value, + absl::string_view response_body); }; } // namespace Envoy diff --git a/mobile/test/common/integration/test_server_interface.cc b/mobile/test/common/integration/test_server_interface.cc index fc70e258c4dc..f4e18a7bb53a 100644 --- a/mobile/test/common/integration/test_server_interface.cc +++ b/mobile/test/common/integration/test_server_interface.cc @@ -9,27 +9,36 @@ static std::weak_ptr weak_test_server_; static std::shared_ptr test_server() { return weak_test_server_.lock(); } -void start_server(bool use_quic) { +void start_server(Envoy::TestServerType test_server_type) { Envoy::ExtensionRegistry::registerFactories(); strong_test_server_ = std::make_shared(); weak_test_server_ = strong_test_server_; - if (auto e = test_server()) { - e->startTestServer(use_quic); + if (auto server = test_server()) { + server->startTestServer(test_server_type); } } void shutdown_server() { // Reset the primary handle to the test_server, // but retain it long enough to synchronously shutdown. - auto e = strong_test_server_; + auto server = strong_test_server_; strong_test_server_.reset(); - e->shutdownTestServer(); + server->shutdownTestServer(); } int get_server_port() { - if (auto e = test_server()) { - return e->getServerPort(); + if (auto server = test_server()) { + return server->getServerPort(); } return -1; // failure } + +void set_headers_and_data(absl::string_view header_key, absl::string_view header_value, + absl::string_view response_body) { + if (auto server = test_server()) { + // start_server() must be called before headers and data can be added. + ASSERT(server); + server->setHeadersAndData(header_key, header_value, response_body); + } +} diff --git a/mobile/test/common/integration/test_server_interface.h b/mobile/test/common/integration/test_server_interface.h index 1bc33286270e..0b51d2a6e55f 100644 --- a/mobile/test/common/integration/test_server_interface.h +++ b/mobile/test/common/integration/test_server_interface.h @@ -12,7 +12,7 @@ extern "C" { // functions * Starts the server. Can only have one server active per JVM. This is blocking until the port can * start accepting requests. */ -void start_server(bool use_quic); +void start_server(Envoy::TestServerType test_server_type); /** * Shutdowns the server. Can be restarted later. This is blocking until the server has freed all @@ -25,6 +25,13 @@ void shutdown_server(); */ int get_server_port(); +/** + * Set response data for server to return for any URL. Can only be called once the server has been + * started. + */ +void set_headers_and_data(absl::string_view header_key, absl::string_view header_value, + absl::string_view response_body); + #ifdef __cplusplus } // functions #endif diff --git a/mobile/test/common/jni/test_jni_interface.cc b/mobile/test/common/jni/test_jni_interface.cc index 6b549d77e4ed..6cc0e31909cb 100644 --- a/mobile/test/common/jni/test_jni_interface.cc +++ b/mobile/test/common/jni/test_jni_interface.cc @@ -10,10 +10,10 @@ // Quic Test ServerJniLibrary extern "C" JNIEXPORT void JNICALL -Java_io_envoyproxy_envoymobile_engine_testing_TestJni_nativeStartQuicTestServer(JNIEnv* env, - jclass clazz) { +Java_io_envoyproxy_envoymobile_engine_testing_TestJni_nativeStartHttp3TestServer(JNIEnv* env, + jclass clazz) { jni_log("[QTS]", "starting server"); - start_server(true); + start_server(Envoy::TestServerType::HTTP3); } extern "C" JNIEXPORT jint JNICALL @@ -24,17 +24,10 @@ Java_io_envoyproxy_envoymobile_engine_testing_TestJni_nativeGetServerPort(JNIEnv } extern "C" JNIEXPORT void JNICALL -Java_io_envoyproxy_envoymobile_engine_testing_TestJni_nativeShutdownQuicTestServer(JNIEnv* env, - jclass clazz) { - jni_log("[QTS]", "shutting down server"); - shutdown_server(); -} - -extern "C" JNIEXPORT void JNICALL -Java_io_envoyproxy_envoymobile_engine_testing_TestJni_nativeStartTestServer(JNIEnv* env, - jclass clazz) { +Java_io_envoyproxy_envoymobile_engine_testing_TestJni_nativeStartHttp2TestServer(JNIEnv* env, + jclass clazz) { jni_log("[QTS]", "starting server"); - start_server(false); + start_server(Envoy::TestServerType::HTTP2_WITH_TLS); } extern "C" JNIEXPORT void JNICALL diff --git a/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/QuicTestServerTest.java b/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/QuicTestServerTest.java index f885d97b9244..089314ac05dc 100644 --- a/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/QuicTestServerTest.java +++ b/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/QuicTestServerTest.java @@ -111,7 +111,7 @@ public static void loadJniLibrary() { @Before public void setUpEngine() throws Exception { - TestJni.startQuicTestServer(); + TestJni.startHttp3TestServer(); CountDownLatch latch = new CountDownLatch(1); engine = new AndroidEngineBuilder(appContext, new Custom(String.format(CONFIG, TestJni.getServerPort()))) @@ -127,7 +127,7 @@ public void setUpEngine() throws Exception { @After public void shutdownEngine() { engine.terminate(); - TestJni.shutdownQuicTestServer(); + TestJni.shutdownTestServer(); } @Test diff --git a/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/TestJni.java b/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/TestJni.java index d64f4d8c0492..177fc68d2155 100644 --- a/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/TestJni.java +++ b/mobile/test/java/io/envoyproxy/envoymobile/engine/testing/TestJni.java @@ -14,21 +14,21 @@ public final class TestJni { /* * Starts the server. Throws an {@link IllegalStateException} if already started. */ - public static void startQuicTestServer() { + public static void startHttp3TestServer() { if (!sServerRunning.compareAndSet(false, true)) { - throw new IllegalStateException("Quic server is already running"); + throw new IllegalStateException("Http3 server is already running"); } - nativeStartQuicTestServer(); + nativeStartHttp3TestServer(); } /* * Starts the server. Throws an {@link IllegalStateException} if already started. */ - public static void startTestServer() { + public static void startHttp2TestServer() { if (!sServerRunning.compareAndSet(false, true)) { throw new IllegalStateException("Server is already running"); } - nativeStartTestServer(); + nativeStartHttp2TestServer(); } /** @@ -41,16 +41,6 @@ public static void shutdownTestServer() { nativeShutdownTestServer(); } - /** - * Shutdowns the server. No-op if the server is already shutdown. - */ - public static void shutdownQuicTestServer() { - if (!sServerRunning.compareAndSet(true, false)) { - return; - } - nativeShutdownQuicTestServer(); - } - public static String getServerURL() { return "https://" + getServerHost() + ":" + getServerPort(); } @@ -71,11 +61,9 @@ public static String createYaml(EnvoyConfiguration envoyConfiguration) { return nativeCreateYaml(envoyConfiguration.createBootstrap()); } - private static native void nativeStartQuicTestServer(); - - private static native void nativeShutdownQuicTestServer(); + private static native void nativeStartHttp3TestServer(); - private static native void nativeStartTestServer(); + private static native void nativeStartHttp2TestServer(); private static native void nativeShutdownTestServer(); diff --git a/mobile/test/kotlin/integration/SendDataTest.kt b/mobile/test/kotlin/integration/SendDataTest.kt index 391553ff2ca0..e2917c1fc882 100644 --- a/mobile/test/kotlin/integration/SendDataTest.kt +++ b/mobile/test/kotlin/integration/SendDataTest.kt @@ -27,7 +27,7 @@ class SendDataTest { @Test fun `successful sending data`() { - TestJni.startTestServer(); + TestJni.startHttp2TestServer(); val port = TestJni.getServerPort(); val expectation = CountDownLatch(1) diff --git a/mobile/test/objective-c/BUILD b/mobile/test/objective-c/BUILD index 53e993aa3780..a67acb0ae0ef 100644 --- a/mobile/test/objective-c/BUILD +++ b/mobile/test/objective-c/BUILD @@ -1,4 +1,4 @@ -load("@envoy_mobile//bazel:apple.bzl", "envoy_mobile_objc_test") +load("@envoy_mobile//bazel:apple.bzl", "envoy_mobile_objc_test", "envoy_objc_library") licenses(["notice"]) # Apache 2 @@ -28,3 +28,17 @@ envoy_mobile_objc_test( "//library/objective-c:envoy_objc_bridge_lib", ], ) + +envoy_objc_library( + name = "envoy_test_server", + testonly = True, + srcs = [ + "EnvoyTestServer.mm", + ], + hdrs = ["EnvoyTestServer.h"], + module_name = "EnvoyTestServer", + visibility = ["//visibility:public"], + deps = [ + "//test/common/integration:test_server_interface_lib", + ], +) diff --git a/mobile/test/objective-c/EnvoyTestServer.h b/mobile/test/objective-c/EnvoyTestServer.h new file mode 100644 index 000000000000..651d53f4d245 --- /dev/null +++ b/mobile/test/objective-c/EnvoyTestServer.h @@ -0,0 +1,17 @@ +#import + +// Interface for starting and managing a test server. Calls into to test_server.cc +@interface EnvoyTestServer : NSObject + +// Get the port of the upstream server. ++ (NSInteger)getEnvoyPort; +// Starts a server with HTTP1 and no TLS. ++ (void)startHttp1PlaintextServer; +// Shut down and clean up server. ++ (void)shutdownTestServer; +// Add response data to the upstream. ++ (void)setHeadersAndData:(NSString *)header_key + header_value:(NSString *)header_value + response_body:(NSString *)response_body; + +@end diff --git a/mobile/test/objective-c/EnvoyTestServer.mm b/mobile/test/objective-c/EnvoyTestServer.mm new file mode 100644 index 000000000000..808863fb67cd --- /dev/null +++ b/mobile/test/objective-c/EnvoyTestServer.mm @@ -0,0 +1,25 @@ +#import "test/objective-c/EnvoyTestServer.h" +#import "test/common/integration/test_server_interface.h" + +@implementation EnvoyTestServer + ++ (NSInteger)getEnvoyPort { + return get_server_port(); +} + ++ (void)startHttp1PlaintextServer { + start_server(Envoy::TestServerType::HTTP1_WITHOUT_TLS); +} + ++ (void)shutdownTestServer { + shutdown_server(); +} + ++ (void)setHeadersAndData:(NSString *)header_key + header_value:(NSString *)header_value + response_body:(NSString *)response_body { + set_headers_and_data([header_key UTF8String], [header_value UTF8String], + [response_body UTF8String]); +} + +@end diff --git a/mobile/test/swift/integration/BUILD b/mobile/test/swift/integration/BUILD index 08be85a67018..86be3c4319e3 100644 --- a/mobile/test/swift/integration/BUILD +++ b/mobile/test/swift/integration/BUILD @@ -20,54 +20,9 @@ envoy_mobile_swift_test( ) envoy_mobile_swift_test( - name = "direct_response_contains_headers_match_test", + name = "end_to_end_networking_test", srcs = [ - "DirectResponseContainsHeadersMatchIntegrationTest.swift", - ], - tags = [ - "no-remote-exec", - ], - visibility = ["//visibility:public"], - deps = [ - ":test_extensions", - "//library/objective-c:envoy_engine_objc_lib", - ], -) - -envoy_mobile_swift_test( - name = "direct_response_exact_match_test", - srcs = [ - "DirectResponseExactPathMatchIntegrationTest.swift", - ], - tags = [ - "no-remote-exec", - ], - visibility = ["//visibility:public"], - deps = [ - ":test_extensions", - "//library/objective-c:envoy_engine_objc_lib", - ], -) - -envoy_mobile_swift_test( - name = "direct_response_filter_mutation", - srcs = [ - "DirectResponseFilterMutationIntegrationTest.swift", - ], - tags = [ - "no-remote-exec", - ], - visibility = ["//visibility:public"], - deps = [ - ":test_extensions", - "//library/objective-c:envoy_engine_objc_lib", - ], -) - -envoy_mobile_swift_test( - name = "direct_response_prefix_headers_match", - srcs = [ - "DirectResponsePrefixHeadersMatchIntegrationTest.swift", + "EndToEndNetworkingTest.swift", ], tags = [ "no-remote-exec", @@ -76,6 +31,7 @@ envoy_mobile_swift_test( deps = [ ":test_extensions", "//library/objective-c:envoy_engine_objc_lib", + "//test/objective-c:envoy_test_server", ], ) @@ -94,36 +50,6 @@ envoy_mobile_swift_test( ], ) -envoy_mobile_swift_test( - name = "direct_response_prefix_path_match", - srcs = [ - "DirectResponsePrefixPathMatchIntegrationTest.swift", - ], - tags = [ - "no-remote-exec", - ], - visibility = ["//visibility:public"], - deps = [ - ":test_extensions", - "//library/objective-c:envoy_engine_objc_lib", - ], -) - -envoy_mobile_swift_test( - name = "direct_response_suffix_headers_match", - srcs = [ - "DirectResponseSuffixHeadersMatchIntegrationTest.swift", - ], - tags = [ - "no-remote-exec", - ], - visibility = ["//visibility:public"], - deps = [ - ":test_extensions", - "//library/objective-c:envoy_engine_objc_lib", - ], -) - envoy_mobile_swift_test( name = "engine_api_test", srcs = [ diff --git a/mobile/test/swift/integration/DirectResponseContainsHeadersMatchIntegrationTest.swift b/mobile/test/swift/integration/DirectResponseContainsHeadersMatchIntegrationTest.swift deleted file mode 100644 index 98d6323ba49d..000000000000 --- a/mobile/test/swift/integration/DirectResponseContainsHeadersMatchIntegrationTest.swift +++ /dev/null @@ -1,60 +0,0 @@ -import Envoy -import TestExtensions -import XCTest - -final class DirectResponseContainsHeadersMatchIntegrationTest: XCTestCase { - override static func setUp() { - super.setUp() - register_test_extensions() - } - - func testDirectResponseWithContainsHeadersMatch() { - let headersExpectation = self.expectation(description: "Response headers received") - let dataExpectation = self.expectation(description: "Response data received") - - let requestHeaders = RequestHeadersBuilder( - method: .get, authority: "127.0.0.1", path: "/v1/abc" - ) - .add(name: "x-foo", value: "123") - .add(name: "x-foo", value: "456") - .build() - - let engine = TestEngineBuilder() - .addDirectResponse( - .init( - matcher: RouteMatcher( - fullPath: "/v1/abc", headers: [ - .init(name: "x-foo", value: "123", mode: .contains), - ] - ), - status: 200, body: "hello world", headers: ["x-response-foo": "aaa"] - ) - ) - .build() - - var responseBuffer = Data() - engine - .streamClient() - .newStreamPrototype() - .setOnResponseHeaders { headers, endStream, _ in - XCTAssertEqual(200, headers.httpStatus) - XCTAssertEqual(["aaa"], headers.value(forName: "x-response-foo")) - XCTAssertFalse(endStream) - headersExpectation.fulfill() - } - .setOnResponseData { data, endStream, _ in - responseBuffer.append(contentsOf: data) - if endStream { - XCTAssertEqual("hello world", String(data: responseBuffer, encoding: .utf8)) - dataExpectation.fulfill() - } - } - .start() - .sendHeaders(requestHeaders, endStream: true) - - let expectations = [headersExpectation, dataExpectation] - XCTAssertEqual(.completed, XCTWaiter().wait(for: expectations, timeout: 10, enforceOrder: true)) - - engine.terminate() - } -} diff --git a/mobile/test/swift/integration/DirectResponseExactHeadersMatchIntegrationTest.swift b/mobile/test/swift/integration/DirectResponseExactHeadersMatchIntegrationTest.swift deleted file mode 100644 index 186328d12803..000000000000 --- a/mobile/test/swift/integration/DirectResponseExactHeadersMatchIntegrationTest.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Envoy -import TestExtensions -import XCTest - -final class DirectResponseExactHeadersMatchIntegrationTest: XCTestCase { - override static func setUp() { - super.setUp() - register_test_extensions() - } - - func testDirectResponseWithExactHeadersMatch() { - let headersExpectation = self.expectation(description: "Response headers received") - let dataExpectation = self.expectation(description: "Response data received") - - let requestHeaders = RequestHeadersBuilder( - method: .get, authority: "127.0.0.1", path: "/v1/abc" - ) - .add(name: "x-foo", value: "123") - .build() - - let engine = TestEngineBuilder() - .addDirectResponse( - .init( - matcher: RouteMatcher( - fullPath: "/v1/abc", headers: [ - .init(name: "x-foo", value: "123", mode: .exact), - ] - ), - status: 200, body: "hello world", headers: ["x-response-foo": "aaa"] - ) - ) - .build() - - var responseBuffer = Data() - engine - .streamClient() - .newStreamPrototype() - .setOnResponseHeaders { headers, endStream, _ in - XCTAssertEqual(200, headers.httpStatus) - XCTAssertEqual(["aaa"], headers.value(forName: "x-response-foo")) - XCTAssertFalse(endStream) - headersExpectation.fulfill() - } - .setOnResponseData { data, endStream, _ in - responseBuffer.append(contentsOf: data) - if endStream { - XCTAssertEqual("hello world", String(data: responseBuffer, encoding: .utf8)) - dataExpectation.fulfill() - } - } - .start() - .sendHeaders(requestHeaders, endStream: true) - - let expectations = [headersExpectation, dataExpectation] - XCTAssertEqual(.completed, XCTWaiter().wait(for: expectations, timeout: 10, enforceOrder: true)) - - engine.terminate() - } -} diff --git a/mobile/test/swift/integration/DirectResponseExactPathMatchIntegrationTest.swift b/mobile/test/swift/integration/DirectResponseExactPathMatchIntegrationTest.swift deleted file mode 100644 index 863890e51e98..000000000000 --- a/mobile/test/swift/integration/DirectResponseExactPathMatchIntegrationTest.swift +++ /dev/null @@ -1,53 +0,0 @@ -import Envoy -import TestExtensions -import XCTest - -final class DirectResponseExactPathMatchIntegrationTest: XCTestCase { - override static func setUp() { - super.setUp() - register_test_extensions() - } - - func testDirectResponseWithExactPathMatch() { - let headersExpectation = self.expectation(description: "Response headers received") - let dataExpectation = self.expectation(description: "Response data received") - - let requestHeaders = RequestHeadersBuilder( - method: .get, authority: "127.0.0.1", path: "/v1/abc" - ).build() - - let engine = TestEngineBuilder() - .addDirectResponse( - .init( - matcher: RouteMatcher(fullPath: "/v1/abc"), - status: 200, body: "hello world", headers: ["x-response-foo": "aaa"] - ) - ) - .build() - - var responseBuffer = Data() - engine - .streamClient() - .newStreamPrototype() - .setOnResponseHeaders { headers, endStream, _ in - XCTAssertEqual(200, headers.httpStatus) - XCTAssertEqual(["aaa"], headers.value(forName: "x-response-foo")) - XCTAssertFalse(endStream) - headersExpectation.fulfill() - } - .setOnResponseData { data, endStream, _ in - responseBuffer.append(contentsOf: data) - if endStream { - XCTAssertEqual("hello world", String(data: responseBuffer, encoding: .utf8)) - dataExpectation.fulfill() - } - } - .start() - .sendHeaders(requestHeaders, endStream: true) - - let expectations = [headersExpectation, dataExpectation] - XCTAssertEqual(.completed, XCTWaiter().wait(for: expectations, timeout: 10, enforceOrder: true)) - - engine.terminate() - } -} diff --git a/mobile/test/swift/integration/DirectResponseFilterMutationIntegrationTest.swift b/mobile/test/swift/integration/DirectResponseFilterMutationIntegrationTest.swift deleted file mode 100644 index b772717b1235..000000000000 --- a/mobile/test/swift/integration/DirectResponseFilterMutationIntegrationTest.swift +++ /dev/null @@ -1,93 +0,0 @@ -import Envoy -import TestExtensions -import XCTest - -private final class MockHeaderMutationFilter: RequestFilter { - private let headersToAdd: [String: String] - - init(headersToAdd: [String: String]) { - self.headersToAdd = headersToAdd - } - - func onRequestHeaders(_ headers: RequestHeaders, endStream: Bool, streamIntel: StreamIntel) - -> FilterHeadersStatus - { - let builder = headers.toRequestHeadersBuilder() - for (name, value) in self.headersToAdd { - builder.add(name: name, value: value) - } - return .continue(headers: builder.build()) - } - - func onRequestData(_ body: Data, endStream: Bool, streamIntel: StreamIntel) - -> FilterDataStatus - { - return .continue(data: body) - } - - func onRequestTrailers(_ trailers: RequestTrailers, streamIntel: StreamIntel) - -> FilterTrailersStatus - { - return .continue(trailers: trailers) - } -} - -final class DirectResponseFilterMutationIntegrationTest: XCTestCase { - override static func setUp() { - super.setUp() - register_test_extensions() - } - - func testDirectResponseThatOnlyMatchesWhenUsingHeadersAddedByFilter() { - let headersExpectation = self.expectation(description: "Response headers received") - let dataExpectation = self.expectation(description: "Response data received") - - let requestHeaders = RequestHeadersBuilder( - method: .get, authority: "127.0.0.1", path: "/v1/abc" - ) - .build() - - // This test validates that Envoy is able to properly route direct responses when a filter - // mutates the outbound request in a way that makes it match one of the direct response - // configurations (whereas if the filter was not present in the chain, the request would not - // match any configurations). This behavior is provided by the C++ `RouteCacheResetFilter`. - let engine = TestEngineBuilder() - .addPlatformFilter { MockHeaderMutationFilter(headersToAdd: ["x-foo": "123"]) } - .addDirectResponse( - .init( - matcher: RouteMatcher( - fullPath: "/v1/abc", headers: [ - .init(name: "x-foo", value: "123", mode: .exact), - ] - ), - status: 200, body: "hello world", headers: ["x-response-foo": "aaa"] - ) - ) - .build() - - var responseBuffer = Data() - engine - .streamClient() - .newStreamPrototype() - .setOnResponseHeaders { headers, endStream, _ in - XCTAssertEqual(200, headers.httpStatus) - XCTAssertEqual(["aaa"], headers.value(forName: "x-response-foo")) - XCTAssertFalse(endStream) - headersExpectation.fulfill() - } - .setOnResponseData { data, endStream, _ in - responseBuffer.append(contentsOf: data) - if endStream { - XCTAssertEqual("hello world", String(data: responseBuffer, encoding: .utf8)) - dataExpectation.fulfill() - } - } - .start() - .sendHeaders(requestHeaders, endStream: true) - - let expectations = [headersExpectation, dataExpectation] - XCTAssertEqual(.completed, XCTWaiter().wait(for: expectations, timeout: 10, enforceOrder: true)) - - engine.terminate() - } -} diff --git a/mobile/test/swift/integration/DirectResponsePrefixHeadersMatchIntegrationTest.swift b/mobile/test/swift/integration/DirectResponsePrefixHeadersMatchIntegrationTest.swift deleted file mode 100644 index c99754d06d36..000000000000 --- a/mobile/test/swift/integration/DirectResponsePrefixHeadersMatchIntegrationTest.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Envoy -import TestExtensions -import XCTest - -final class DirectResponsePrefixHeadersMatchIntegrationTest: XCTestCase { - override static func setUp() { - super.setUp() - register_test_extensions() - } - - func testDirectResponseWithPrefixHeadersMatch() { - let headersExpectation = self.expectation(description: "Response headers received") - let dataExpectation = self.expectation(description: "Response data received") - - let requestHeaders = RequestHeadersBuilder( - method: .get, authority: "127.0.0.1", path: "/v1/abc" - ) - .add(name: "x-foo", value: "123456") - .build() - - let engine = TestEngineBuilder() - .addDirectResponse( - .init( - matcher: RouteMatcher( - fullPath: "/v1/abc", headers: [ - .init(name: "x-foo", value: "123", mode: .prefix), - ] - ), - status: 200, body: "hello world", headers: ["x-response-foo": "aaa"] - ) - ) - .build() - - var responseBuffer = Data() - engine - .streamClient() - .newStreamPrototype() - .setOnResponseHeaders { headers, endStream, _ in - XCTAssertEqual(200, headers.httpStatus) - XCTAssertEqual(["aaa"], headers.value(forName: "x-response-foo")) - XCTAssertFalse(endStream) - headersExpectation.fulfill() - } - .setOnResponseData { data, endStream, _ in - responseBuffer.append(contentsOf: data) - if endStream { - XCTAssertEqual("hello world", String(data: responseBuffer, encoding: .utf8)) - dataExpectation.fulfill() - } - } - .start() - .sendHeaders(requestHeaders, endStream: true) - - let expectations = [headersExpectation, dataExpectation] - XCTAssertEqual(.completed, XCTWaiter().wait(for: expectations, timeout: 10, enforceOrder: true)) - - engine.terminate() - } -} diff --git a/mobile/test/swift/integration/DirectResponseSuffixHeadersMatchIntegrationTest.swift b/mobile/test/swift/integration/DirectResponseSuffixHeadersMatchIntegrationTest.swift deleted file mode 100644 index 9413a1d36327..000000000000 --- a/mobile/test/swift/integration/DirectResponseSuffixHeadersMatchIntegrationTest.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Envoy -import TestExtensions -import XCTest - -final class DirectResponseSuffixHeadersMatchIntegrationTest: XCTestCase { - override static func setUp() { - super.setUp() - register_test_extensions() - } - - func testDirectResponseWithSuffixHeadersMatch() { - let headersExpectation = self.expectation(description: "Response headers received") - let dataExpectation = self.expectation(description: "Response data received") - - let requestHeaders = RequestHeadersBuilder( - method: .get, authority: "127.0.0.1", path: "/v1/abc" - ) - .add(name: "x-foo", value: "123456") - .build() - - let engine = TestEngineBuilder() - .addDirectResponse( - .init( - matcher: RouteMatcher( - fullPath: "/v1/abc", headers: [ - .init(name: "x-foo", value: "456", mode: .suffix), - ] - ), - status: 200, body: "hello world", headers: ["x-response-foo": "aaa"] - ) - ) - .build() - - var responseBuffer = Data() - engine - .streamClient() - .newStreamPrototype() - .setOnResponseHeaders { headers, endStream, _ in - XCTAssertEqual(200, headers.httpStatus) - XCTAssertEqual(["aaa"], headers.value(forName: "x-response-foo")) - XCTAssertFalse(endStream) - headersExpectation.fulfill() - } - .setOnResponseData { data, endStream, _ in - responseBuffer.append(contentsOf: data) - if endStream { - XCTAssertEqual("hello world", String(data: responseBuffer, encoding: .utf8)) - dataExpectation.fulfill() - } - } - .start() - .sendHeaders(requestHeaders, endStream: true) - - let expectations = [headersExpectation, dataExpectation] - XCTAssertEqual(.completed, XCTWaiter().wait(for: expectations, timeout: 10, enforceOrder: true)) - - engine.terminate() - } -} diff --git a/mobile/test/swift/integration/DirectResponsePrefixPathMatchIntegrationTest.swift b/mobile/test/swift/integration/EndToEndNetworkingTest.swift similarity index 70% rename from mobile/test/swift/integration/DirectResponsePrefixPathMatchIntegrationTest.swift rename to mobile/test/swift/integration/EndToEndNetworkingTest.swift index cd68b94cec37..140f10c75d17 100644 --- a/mobile/test/swift/integration/DirectResponsePrefixPathMatchIntegrationTest.swift +++ b/mobile/test/swift/integration/EndToEndNetworkingTest.swift @@ -1,28 +1,28 @@ import Envoy +import EnvoyTestServer +import Foundation import TestExtensions import XCTest -final class DirectResponsePrefixPathMatchIntegrationTest: XCTestCase { +final class EndToEndNetworkingTest: XCTestCase { override static func setUp() { super.setUp() register_test_extensions() } - func testDirectResponseWithPrefixMatch() { + func testNetworkRequestReturnsHeadersAndData() { + EnvoyTestServer.startHttp1PlaintextServer() + EnvoyTestServer.setHeadersAndData( + "x-response-foo", header_value: "aaa", response_body: "hello world") let headersExpectation = self.expectation(description: "Response headers received") let dataExpectation = self.expectation(description: "Response data received") - + let port = String(EnvoyTestServer.getEnvoyPort()) let requestHeaders = RequestHeadersBuilder( - method: .get, authority: "127.0.0.1", path: "/v1/foo/bar?param=1" - ).build() + method: .get, scheme: "http", authority: "localhost:" + port, path: "/" + ) + .build() - let engine = TestEngineBuilder() - .addDirectResponse( - .init( - matcher: RouteMatcher(pathPrefix: "/v1/foo"), - status: 200, body: "hello world", headers: ["x-response-foo": "aaa"] - ) - ) + let engine = EngineBuilder() .build() var responseBuffer = Data() @@ -49,5 +49,6 @@ final class DirectResponsePrefixPathMatchIntegrationTest: XCTestCase { XCTAssertEqual(.completed, XCTWaiter().wait(for: expectations, timeout: 10, enforceOrder: true)) engine.terminate() + EnvoyTestServer.shutdownTestServer() } } From ab3cc1fcc488436086407dd2127509e5b88d289d Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 23 May 2023 20:56:04 +0100 Subject: [PATCH 058/228] mobile/ci: Improve mobile jobs (#27404) Signed-off-by: Ryan Northey --- .github/workflows/env.yml | 64 ++++++++++++++ .github/workflows/mobile-android_build.yml | 81 ++++++------------ .github/workflows/mobile-android_tests.yml | 37 +++------ .github/workflows/mobile-asan.yml | 16 ++-- .github/workflows/mobile-cc_tests.yml | 10 ++- .../workflows/mobile-compile_time_options.yml | 37 +++------ .github/workflows/mobile-core.yml | 4 +- .github/workflows/mobile-coverage.yml | 18 ++-- .github/workflows/mobile-docs.yml | 4 +- .github/workflows/mobile-format.yml | 50 ++++------- .github/workflows/mobile-ios_build.yml | 83 +++++-------------- .github/workflows/mobile-ios_tests.yml | 27 +++--- .github/workflows/mobile-perf.yml | 12 +-- .../workflows/mobile-release_validation.yml | 19 ++--- .github/workflows/mobile-tsan.yml | 16 ++-- mobile/tools/should_run_ci.sh | 61 -------------- mobile/tools/what_to_run.sh | 52 ++++++++++++ 17 files changed, 260 insertions(+), 331 deletions(-) create mode 100644 .github/workflows/env.yml delete mode 100755 mobile/tools/should_run_ci.sh create mode 100755 mobile/tools/what_to_run.sh diff --git a/.github/workflows/env.yml b/.github/workflows/env.yml new file mode 100644 index 000000000000..a0caaa67cfb6 --- /dev/null +++ b/.github/workflows/env.yml @@ -0,0 +1,64 @@ +name: Environment + +on: + workflow_call: + outputs: + mobile_android_build: + value: ${{ jobs.mobile.outputs.mobile_android_build }} + mobile_android_build_all: + value: ${{ jobs.mobile.outputs.mobile_android_build_all }} + mobile_android_tests: + value: ${{ jobs.mobile.outputs.mobile_android_tests }} + mobile_asan: + value: ${{ jobs.mobile.outputs.mobile_asan }} + mobile_cc_tests: + value: ${{ jobs.mobile.outputs.mobile_cc_tests }} + mobile_compile_time_options: + value: ${{ jobs.mobile.outputs.mobile_compile_time_options }} + mobile_coverage: + value: ${{ jobs.mobile.outputs.mobile_coverage }} + mobile_formatting: + value: ${{ jobs.mobile.outputs.mobile_formatting }} + mobile_ios_build: + value: ${{ jobs.mobile.outputs.mobile_ios_build }} + mobile_ios_build_all: + value: ${{ jobs.mobile.outputs.mobile_ios_build_all }} + mobile_ios_tests: + value: ${{ jobs.mobile.outputs.mobile_ios_tests }} + mobile_release_validation: + value: ${{ jobs.mobile.outputs.mobile_release_validation }} + mobile_tsan: + value: ${{ jobs.mobile.outputs.mobile_tsan }} + +concurrency: + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }}-env + cancel-in-progress: true + +jobs: + mobile: + if: github.repository == 'envoyproxy/envoy' + runs-on: ubuntu-20.04 + outputs: + mobile_android_build: ${{ steps.should_run.outputs.mobile_android_build }} + mobile_android_build_all: ${{ steps.should_run.outputs.mobile_android_build_all }} + mobile_android_tests: ${{ steps.should_run.outputs.mobile_android_tests }} + mobile_asan: ${{ steps.should_run.outputs.mobile_asan }} + mobile_cc_tests: ${{ steps.should_run.outputs.mobile_cc_tests }} + mobile_compile_time_options: ${{ steps.should_run.outputs.mobile_compile_time_options }} + mobile_coverage: ${{ steps.should_run.outputs.mobile_coverage }} + mobile_formatting: ${{ steps.should_run.outputs.mobile_formatting }} + mobile_ios_build: ${{ steps.should_run.outputs.mobile_ios_build }} + mobile_ios_build_all: ${{ steps.should_run.outputs.mobile_ios_build_all }} + mobile_ios_tests: ${{ steps.should_run.outputs.mobile_ios_tests }} + mobile_release_validation: ${{ steps.should_run.outputs.mobile_release_validation }} + mobile_tsan: ${{ steps.should_run.outputs.mobile_tsan }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Add safe directory + run: git config --global --add safe.directory /__w/envoy/envoy + - id: should_run + name: 'Check what to run' + run: | + ./mobile/tools/what_to_run.sh diff --git a/.github/workflows/mobile-android_build.yml b/.github/workflows/mobile-android_build.yml index 4e1f8ec328e0..8f5c71a7d978 100644 --- a/.github/workflows/mobile-android_build.yml +++ b/.github/workflows/mobile-android_build.yml @@ -7,12 +7,18 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + androidbuild: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_build == 'true' }} + needs: env name: android_build runs-on: ubuntu-20.04 timeout-minutes: 90 @@ -23,15 +29,9 @@ jobs: CXX: /opt/llvm/bin/clang++ steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Build envoy.aar distributable' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -40,31 +40,26 @@ jobs: --fat_apk_cpu=x86_64 \ --linkopt=-fuse-ld=lld \ //:android_dist + javahelloworld: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_build_all == 'true' }} + needs: + - env + - androidbuild name: java_helloworld - needs: androidbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 - if: steps.should_run.outputs.run_ci_job == 'true' with: java-version: '8' java-package: jdk architecture: x64 distribution: zulu - run: cd mobile && ./ci/mac_ci_setup.sh --android - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start emulator' with: timeout_minutes: 10 @@ -74,7 +69,6 @@ jobs: # cd mobile && ./bazelw mobile-install --fat_apk_cpu=x86_64 --start_app //examples/java/hello_world:hello_envoy # When https://github.com/envoyproxy/envoy-mobile/issues/853 is fixed. - name: 'Start java app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -85,7 +79,6 @@ jobs: adb install -r --no-incremental bazel-bin/examples/java/hello_world/hello_envoy.apk adb shell am start -n io.envoyproxy.envoymobile.helloenvoy/.MainActivity - name: 'Check connectivity' - if: steps.should_run.outputs.run_ci_job == 'true' run: | timeout 30 adb logcat -e "received headers with status 301" -m 1 || { echo "Failed checking for headers in adb logcat" >&2 @@ -95,30 +88,24 @@ jobs: exit 1 } kotlinhelloworld: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_build == 'true' }} + needs: + - env + - androidbuild name: kotlin_helloworld - needs: androidbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 - if: steps.should_run.outputs.run_ci_job == 'true' with: java-version: '8' java-package: jdk architecture: x64 distribution: zulu - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh --android - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start emulator' with: timeout_minutes: 10 @@ -128,7 +115,6 @@ jobs: # ./bazelw mobile-install --fat_apk_cpu=x86_64 --start_app //examples/kotlin/hello_world:hello_envoy_kt # When https://github.com/envoyproxy/envoy-mobile/issues/853 is fixed. - name: 'Start kotlin app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -139,7 +125,6 @@ jobs: adb install -r --no-incremental bazel-bin/examples/kotlin/hello_world/hello_envoy_kt.apk adb shell am start -n io.envoyproxy.envoymobile.helloenvoykotlin/.MainActivity - name: 'Check connectivity' - if: steps.should_run.outputs.run_ci_job == 'true' run: | timeout 30 adb logcat -e "received headers with status 200" -m 1 || { echo "Failed checking for headers in adb logcat" >&2 @@ -150,30 +135,24 @@ jobs: } kotlinbaselineapp: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_build_all == 'true' }} + needs: + - env + - androidbuild name: kotlin_baseline_app - needs: androidbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 - if: steps.should_run.outputs.run_ci_job == 'true' with: java-version: '8' java-package: jdk architecture: x64 distribution: zulu - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh --android - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start emulator' with: timeout_minutes: 10 @@ -183,7 +162,6 @@ jobs: # ./bazelw mobile-install --fat_apk_cpu=x86_64 --start_app //examples/kotlin/hello_world:hello_envoy_kt # When https://github.com/envoyproxy/envoy-mobile/issues/853 is fixed. - name: 'Start kotlin app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -194,7 +172,6 @@ jobs: adb install -r --no-incremental bazel-bin/test/kotlin/apps/baseline/hello_envoy_kt.apk adb shell am start -n io.envoyproxy.envoymobile.helloenvoybaselinetest/.MainActivity - name: 'Check connectivity' - if: steps.should_run.outputs.run_ci_job == 'true' run: | timeout 30 adb logcat -e "received headers with status 301" -m 1 || { echo "Failed checking for headers in adb logcat" >&2 @@ -204,30 +181,24 @@ jobs: exit 1 } kotlinexperimentalapp: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_build_all == 'true' }} + needs: + - env + - androidbuild name: kotlin_experimental_app - needs: androidbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 - if: steps.should_run.outputs.run_ci_job == 'true' with: java-version: '8' java-package: jdk architecture: x64 distribution: zulu - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh --android - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start emulator' with: timeout_minutes: 10 @@ -237,7 +208,6 @@ jobs: # ./bazelw mobile-install --fat_apk_cpu=x86_64 --start_app //examples/kotlin/hello_world:hello_envoy_kt # When https://github.com/envoyproxy/envoy-mobile/issues/853 is fixed. - name: 'Start kotlin app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -250,7 +220,6 @@ jobs: adb install -r --no-incremental bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apk adb shell am start -n io.envoyproxy.envoymobile.helloenvoyexperimentaltest/.MainActivity - name: 'Check connectivity' - if: steps.should_run.outputs.run_ci_job == 'true' run: | timeout 30 adb logcat -e "received headers with status 200" -m 1 || { echo "Failed checking for headers in adb logcat" >&2 diff --git a/.github/workflows/mobile-android_tests.yml b/.github/workflows/mobile-android_tests.yml index f4b44217c0e7..9baf8b9922a7 100644 --- a/.github/workflows/mobile-android_tests.yml +++ b/.github/workflows/mobile-android_tests.yml @@ -7,12 +7,17 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + uses: ./.github/workflows/env.yml + secrets: inherit + kotlintestsmac: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_tests == 'true' }} + needs: env # revert to //test/kotlin/... once fixed # https://github.com/envoyproxy/envoy-mobile/issues/1932 name: kotlin_tests_mac @@ -20,13 +25,7 @@ jobs: timeout-minutes: 90 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Java setup' - if: steps.should_run.outputs.run_ci_job == 'true' uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 with: java-version: '8' @@ -34,10 +33,8 @@ jobs: architecture: x64 distribution: zulu - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh - name: 'Run Kotlin library tests' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -48,19 +45,14 @@ jobs: --define=signal_trace=disabled \ //test/kotlin/io/... javatestsmac: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_tests == 'true' }} + needs: env name: java_tests_mac runs-on: macos-12 timeout-minutes: 120 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Java setup' - if: steps.should_run.outputs.run_ci_job == 'true' uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 with: java-version: '8' @@ -68,10 +60,8 @@ jobs: architecture: x64 distribution: zulu - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh - name: 'Run Java library tests' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -85,7 +75,8 @@ jobs: --define=system-helper=android \ //test/java/... kotlintestslinux: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_android_tests == 'true' }} + needs: env # Only kotlin tests are executed since with linux: # https://github.com/envoyproxy/envoy-mobile/issues/1418. name: kotlin_tests_linux @@ -98,15 +89,9 @@ jobs: CXX: /opt/llvm/bin/clang++ steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Run Kotlin library integration tests' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | diff --git a/.github/workflows/mobile-asan.yml b/.github/workflows/mobile-asan.yml index 2681176bc068..e5a9378c262e 100644 --- a/.github/workflows/mobile-asan.yml +++ b/.github/workflows/mobile-asan.yml @@ -7,12 +7,18 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + asan: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_asan == 'true' }} + needs: env name: asan runs-on: ubuntu-20.04 timeout-minutes: 180 @@ -23,17 +29,11 @@ jobs: CXX: /opt/llvm/bin/clang++ steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Run tests' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: steps.should_run.outputs.run_ci_job == 'true' run: | cd mobile && ./bazelw test --test_output=all \ --test_env=ENVOY_IP_TEST_VERSIONS=v4only \ diff --git a/.github/workflows/mobile-cc_tests.yml b/.github/workflows/mobile-cc_tests.yml index 28f6c633ecd8..c824fc8f6ece 100644 --- a/.github/workflows/mobile-cc_tests.yml +++ b/.github/workflows/mobile-cc_tests.yml @@ -7,12 +7,18 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + cctests: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_cc_tests == 'true' }} + needs: env name: cc_tests runs-on: ubuntu-20.04 timeout-minutes: 120 diff --git a/.github/workflows/mobile-compile_time_options.yml b/.github/workflows/mobile-compile_time_options.yml index b9ee5e056dda..fc8ff2073781 100644 --- a/.github/workflows/mobile-compile_time_options.yml +++ b/.github/workflows/mobile-compile_time_options.yml @@ -7,12 +7,18 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + cc_test: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_compile_time_options == 'true' }} + needs: env name: cc_test runs-on: ubuntu-20.04 timeout-minutes: 120 @@ -20,15 +26,9 @@ jobs: image: envoyproxy/envoy-build-ubuntu:b0ff77ae3f25b0bf595f9b8bba46b489723ab446 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Build C++ library' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Envoy Mobile build verifies that the build configuration where HTTP/3 is enabled and @@ -45,22 +45,16 @@ jobs: --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ //test/cc/... swift_build: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_compile_time_options == 'true' }} + needs: env name: swift_build runs-on: macos-12 timeout-minutes: 120 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build Swift library' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -79,29 +73,22 @@ jobs: --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ //library/swift:ios_framework kotlin_build: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_compile_time_options == 'true' }} + needs: env name: kotlin_build runs-on: macos-12 timeout-minutes: 120 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 - if: steps.should_run.outputs.run_ci_job == 'true' with: java-version: '8' java-package: jdk architecture: x64 distribution: zulu - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh --android - name: 'Build Kotlin library' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | diff --git a/.github/workflows/mobile-core.yml b/.github/workflows/mobile-core.yml index 26cd00b8089d..7c111e04a88b 100644 --- a/.github/workflows/mobile-core.yml +++ b/.github/workflows/mobile-core.yml @@ -7,12 +7,12 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: unittests: - if: github.repository == 'envoyproxy/envoy' + if: ${{ github.repository == 'envoyproxy/envoy' }} name: unit_tests runs-on: ubuntu-20.04 timeout-minutes: 120 diff --git a/.github/workflows/mobile-coverage.yml b/.github/workflows/mobile-coverage.yml index cdb1cf2a9853..8ff027449a9e 100644 --- a/.github/workflows/mobile-coverage.yml +++ b/.github/workflows/mobile-coverage.yml @@ -7,12 +7,18 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + coverage: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_coverage == 'true' }} + needs: env name: coverage runs-on: ubuntu-20.04 timeout-minutes: 120 @@ -23,15 +29,9 @@ jobs: image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Run coverage' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -40,11 +40,9 @@ jobs: COVERAGE_THRESHOLD=76 \ ../test/run_envoy_bazel_coverage.sh //test/common/... //test/cc/... - name: 'Package coverage' - if: steps.should_run.outputs.run_ci_job == 'true' run: | cd mobile && tar -czf coverage.tar.gz generated/coverage - name: 'Upload report' - if: steps.should_run.outputs.run_ci_job == 'true' uses: actions/upload-artifact@v3 with: name: coverage.tar.gz diff --git a/.github/workflows/mobile-docs.yml b/.github/workflows/mobile-docs.yml index 403529803e14..093b5f29740c 100644 --- a/.github/workflows/mobile-docs.yml +++ b/.github/workflows/mobile-docs.yml @@ -7,12 +7,12 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: docs: - if: github.repository == 'envoyproxy/envoy' + if: ${{ github.repository == 'envoyproxy/envoy' }} runs-on: ubuntu-20.04 timeout-minutes: 20 container: diff --git a/.github/workflows/mobile-format.yml b/.github/workflows/mobile-format.yml index 97457d9f2015..ac48d4308063 100644 --- a/.github/workflows/mobile-format.yml +++ b/.github/workflows/mobile-format.yml @@ -7,12 +7,18 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + formatall: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_formatting == 'true' }} + needs: env name: format_all runs-on: ubuntu-20.04 timeout-minutes: 45 @@ -25,36 +31,25 @@ jobs: ENVOY_BAZEL_PREFIX: "@envoy" steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Run formatters' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./tools/check_format.sh precommit: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_formatting == 'true' }} + needs: env name: precommit runs-on: macos-12 timeout-minutes: 45 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Install precommit' - if: steps.should_run.outputs.run_ci_job == 'true' run: brew install pre-commit - name: 'Run precommit' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && find mobile/* | pre-commit run --files swiftlint: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_formatting == 'true' }} + needs: env name: swift_lint runs-on: ubuntu-latest timeout-minutes: 5 @@ -66,46 +61,34 @@ jobs: run: swiftlint lint --strict working-directory: mobile drstring: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_formatting == 'true' }} + needs: env name: drstring runs-on: macos-12 timeout-minutes: 10 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Run DrString' - if: steps.should_run.outputs.run_ci_job == 'true' env: DEVELOPER_DIR: /Applications/Xcode_14.1.app run: cd mobile && ./bazelw run @DrString//:drstring check kotlinlint: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_formatting == 'true' }} + needs: env name: kotlin_lint runs-on: macos-12 timeout-minutes: 45 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 - if: steps.should_run.outputs.run_ci_job == 'true' with: java-version: '8' java-package: jdk architecture: x64 distribution: zulu - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Run Kotlin Lint (Detekt)' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -114,5 +97,4 @@ jobs: //library/kotlin/io/envoyproxy/envoymobile:envoy_lib_lint \ //examples/kotlin/hello_world:hello_envoy_kt_lint - name: 'Run Kotlin Formatter (ktlint)' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./bazelw build kotlin_format diff --git a/.github/workflows/mobile-ios_build.yml b/.github/workflows/mobile-ios_build.yml index fd3601c1cc9b..a1d117ff13cd 100644 --- a/.github/workflows/mobile-ios_build.yml +++ b/.github/workflows/mobile-ios_build.yml @@ -7,27 +7,26 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + iosbuild: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_build == 'true' }} + needs: env name: ios_build runs-on: macos-12 timeout-minutes: 120 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build Envoy.framework distributable' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -37,23 +36,16 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //library/swift:ios_framework swifthelloworld: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_build == 'true' }} name: swift_helloworld needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -62,7 +54,6 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //examples/swift/hello_world:app - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start simulator' with: timeout_minutes: 5 @@ -70,7 +61,6 @@ jobs: command: ./mobile/ci/start_ios_simulator.sh # Run the app in the background and redirect logs. - name: 'Run app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -79,29 +69,23 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //examples/swift/hello_world:app &> /tmp/envoy.log & - run: sed '/received headers with status 200/q' <(touch /tmp/envoy.log && tail -F /tmp/envoy.log) - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Check connectivity' - run: cat /tmp/envoy.log if: ${{ failure() || cancelled() }} name: 'Log app run' swiftbaselineapp: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_build_all == 'true' }} + needs: + - env + - iosbuild name: swift_baseline_app - needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -110,7 +94,6 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //test/swift/apps/baseline:app - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start simulator' with: timeout_minutes: 5 @@ -118,7 +101,6 @@ jobs: command: ./mobile/ci/start_ios_simulator.sh # Run the app in the background and redirect logs. - name: 'Run app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -127,29 +109,22 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //test/swift/apps/baseline:app &> /tmp/envoy.log & - run: sed '/received headers with status 301/q' <(touch /tmp/envoy.log && tail -F /tmp/envoy.log) - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Check connectivity' - run: cat /tmp/envoy.log if: ${{ failure() || cancelled() }} name: 'Log app run' swiftexperimentalapp: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_build_all == 'true' }} + needs: env name: swift_experimental_app needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -160,7 +135,6 @@ jobs: --define envoy_mobile_listener=enabled \ //test/swift/apps/experimental:app - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start simulator' with: timeout_minutes: 5 @@ -168,7 +142,6 @@ jobs: command: ./mobile/ci/start_ios_simulator.sh # Run the app in the background and redirect logs. - name: 'Run app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -179,29 +152,22 @@ jobs: --define envoy_mobile_listener=enabled \ //test/swift/apps/experimental:app &> /tmp/envoy.log & - run: sed '/received headers with status 200/q' <(touch /tmp/envoy.log && tail -F /tmp/envoy.log) - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Check connectivity' - run: cat /tmp/envoy.log if: ${{ failure() || cancelled() }} name: 'Log app run' swiftasyncawait: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_build_all == 'true' }} + needs: env name: swift_async_await needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -210,7 +176,6 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //examples/swift/async_await:app - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start simulator' with: timeout_minutes: 5 @@ -218,7 +183,6 @@ jobs: command: ./mobile/ci/start_ios_simulator.sh # Run the app in the background and redirect logs. - name: 'Run app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -249,23 +213,17 @@ jobs: if: ${{ failure() || cancelled() }} name: 'Log app run' objchelloworld: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_build_all == 'true' }} + needs: env name: objc_helloworld needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -274,7 +232,6 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //examples/objective-c/hello_world:app - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Start simulator' with: timeout_minutes: 5 @@ -282,7 +239,6 @@ jobs: command: ./mobile/ci/start_ios_simulator.sh # Run the app in the background and redirect logs. - name: 'Run app' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -291,7 +247,6 @@ jobs: $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ //examples/objective-c/hello_world:app &> /tmp/envoy.log & - run: sed '/received headers with status 301/q' <(touch /tmp/envoy.log && tail -F /tmp/envoy.log) - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Check connectivity' - run: cat /tmp/envoy.log if: ${{ failure() || cancelled() }} diff --git a/.github/workflows/mobile-ios_tests.yml b/.github/workflows/mobile-ios_tests.yml index c2b141027d9f..e6f25e960d7e 100644 --- a/.github/workflows/mobile-ios_tests.yml +++ b/.github/workflows/mobile-ios_tests.yml @@ -7,27 +7,26 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + swifttests: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_tests == 'true' }} + needs: env name: swift_tests runs-on: macos-12 timeout-minutes: 120 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh - name: 'Run swift library tests' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # runs with admin enabled due to regression testing admin interface @@ -43,22 +42,16 @@ jobs: --define=admin_functionality=enabled \ //test/swift/... objctests: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_ios_tests == 'true' }} + needs: env name: c_and_objc_tests runs-on: macos-12 timeout-minutes: 120 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Install dependencies' - if: steps.should_run.outputs.run_ci_job == 'true' run: cd mobile && ./ci/mac_ci_setup.sh - name: 'Run Objective-C library tests' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | diff --git a/.github/workflows/mobile-perf.yml b/.github/workflows/mobile-perf.yml index 26084818d469..b1c142bf2c1b 100644 --- a/.github/workflows/mobile-perf.yml +++ b/.github/workflows/mobile-perf.yml @@ -7,12 +7,12 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: sizecurrent: - if: github.repository == 'envoyproxy/envoy' + if: ${{ github.repository == 'envoyproxy/envoy' }} name: size_current runs-on: ubuntu-20.04 timeout-minutes: 120 @@ -39,7 +39,7 @@ jobs: name: sizecurrent path: mobile/bazel-bin/test/performance/test_binary_size sizemain: - if: github.repository == 'envoyproxy/envoy' + if: ${{ github.repository == 'envoyproxy/envoy' }} name: size_main runs-on: ubuntu-20.04 timeout-minutes: 90 @@ -68,9 +68,11 @@ jobs: name: sizemain path: mobile/bazel-bin/test/performance/test_binary_size sizecompare: - if: github.repository == 'envoyproxy/envoy' + if: ${{ github.repository == 'envoyproxy/envoy' }} + needs: + - sizecurrent + - sizemain name: size_compare - needs: [sizecurrent, sizemain] runs-on: ubuntu-20.04 timeout-minutes: 30 container: diff --git a/.github/workflows/mobile-release_validation.yml b/.github/workflows/mobile-release_validation.yml index f5f03d84420a..34cf2878aeea 100644 --- a/.github/workflows/mobile-release_validation.yml +++ b/.github/workflows/mobile-release_validation.yml @@ -7,27 +7,26 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + validate_swiftpm_example: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_release_validation == 'true' }} + needs: env name: validate_swiftpm_example runs-on: macos-12 timeout-minutes: 120 steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - run: cd mobile && ./ci/mac_ci_setup.sh - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Install dependencies' - name: 'Build xcframework' - if: steps.should_run.outputs.run_ci_job == 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -37,9 +36,7 @@ jobs: //:ios_xcframework # Ignore errors: Bad CRC when unzipping large files: https://bbs.archlinux.org/viewtopic.php?id=153011 - run: unzip mobile/bazel-bin/library/swift/Envoy.xcframework.zip -d mobile/examples/swift/swiftpm/Packages || true - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Unzip xcframework' - run: xcodebuild -project mobile/examples/swift/swiftpm/EnvoySwiftPMExample.xcodeproj -scheme EnvoySwiftPMExample -destination platform="iOS Simulator,name=iPhone 14 Pro Max,OS=16.1" - if: steps.should_run.outputs.run_ci_job == 'true' name: 'Build app' # TODO(jpsim): Run app and inspect logs to validate diff --git a/.github/workflows/mobile-tsan.yml b/.github/workflows/mobile-tsan.yml index 8a5898f2b813..918613f15146 100644 --- a/.github/workflows/mobile-tsan.yml +++ b/.github/workflows/mobile-tsan.yml @@ -7,12 +7,18 @@ on: pull_request: concurrency: - group: ${{ github.head_ref-github.workflow || github.run_id }} + group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + tsan: - if: github.repository == 'envoyproxy/envoy' + if: ${{ needs.env.outputs.mobile_tsan == 'true' }} + needs: env name: tsan runs-on: ubuntu-20.04 timeout-minutes: 90 @@ -23,17 +29,11 @@ jobs: CXX: /opt/llvm/bin/clang++ steps: - uses: actions/checkout@v3 - with: - fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - id: should_run - name: 'Check whether to run' - run: ./mobile/tools/should_run_ci.sh - name: 'Run tests' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: steps.should_run.outputs.run_ci_job == 'true' run: | cd mobile && ./bazelw test \ --test_output=all \ diff --git a/mobile/tools/should_run_ci.sh b/mobile/tools/should_run_ci.sh deleted file mode 100755 index 1ee2622db98f..000000000000 --- a/mobile/tools/should_run_ci.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -######################################################################## -# should_run_ci.sh -# -# Checks current branch and changed PR paths to determine if mobile CI -# jobs should be run. -######################################################################## - -job="$GITHUB_JOB" -branch_name="$GITHUB_REF_NAME" - -function success() { - echo "Running $job because there are $1 changes on $branch_name" - echo "run_ci_job=true" >> "$GITHUB_OUTPUT" -} - -function failure() { - echo "Skipping $job because there are no mobile changes on $branch_name" - echo "run_ci_job=false" >> "$GITHUB_OUTPUT" -} - -if [[ $branch_name == "main" ]]; then - # Skip some example apps on `main` to reduce CI load - case "$job" in - swiftbaselineapp|swiftexperimentalapp|swiftasyncawait|objchelloworld|javahelloworld|kotlinbaselineapp|kotlinexperimentalapp) - echo "Skipping $job because current branch is main" - echo "run_ci_job=false" >> "$GITHUB_OUTPUT" - exit 0 - ;; - esac - - # Run all other mobile CI jobs on `main` - echo "Running $job because current branch is main" - echo "run_ci_job=true" >> "$GITHUB_OUTPUT" - exit 0 -fi - -if [[ $GITHUB_BASE_REF == release/* ]]; then - # Skip mobile CI jobs on PRs targeting release branches - echo "Skipping $job because the PR is targeting a release branch" - echo "run_ci_job=false" >> "$GITHUB_OUTPUT" - exit 0 -fi - -base_commit="$(git merge-base origin/main HEAD)" -changed_files="$(git diff "$base_commit" --name-only)" - -if grep -q "^mobile/" <<< "$changed_files"; then - success "mobile" -elif grep -q "^bazel/repository_locations\.bzl" <<< "$changed_files"; then - success "bazel/repository_locations.bzl" -elif grep -q "^\.bazelrc" <<< "$changed_files"; then - success ".bazelrc" -elif grep -q "^\.github/workflows/mobile-*" <<< "$changed_files"; then - success "GitHub Workflows" -else - failure -fi diff --git a/mobile/tools/what_to_run.sh b/mobile/tools/what_to_run.sh new file mode 100755 index 000000000000..d67ca8e9c9b4 --- /dev/null +++ b/mobile/tools/what_to_run.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +set -euo pipefail + +BRANCH_NAME="$GITHUB_REF_NAME" +BASE_COMMIT="$(git merge-base origin/main HEAD)" +CHANGED_FILES="$(git diff "${BASE_COMMIT}" --name-only)" +CHANGE_MATCH='^mobile/|^bazel/repository_locations\.bzl|^\.bazelrc|^\.github/workflows/mobile-*|^\.github/workflows/env.yml' + +# The logic in this file is roughly: +# +# pull_request + changed files = run all mobile CI +# +# main = run some mobile CI +# +# all other commits = run minimal mobile CI (these jobs have no conditions) +# +# Branches are not currently tested, altho that should be restricted by the workflow + + +run_default_ci () { + { + echo "mobile_android_build=true" + echo "mobile_android_tests=true" + echo "mobile_asan=true" + echo "mobile_cc_tests=true" + echo "mobile_compile_time_options=true" + echo "mobile_coverage=true" + echo "mobile_formatting=true" + echo "mobile_ios_build=true" + echo "mobile_ios_tests=true" + echo "mobile_release_validation=true" + echo "mobile_tsan=true" + } >> "$GITHUB_OUTPUT" +} + +run_ci_for_changed_files () { + run_default_ci + { + echo "mobile_android_build_all=true" + echo "mobile_ios_build_all=true" + } >> "$GITHUB_OUTPUT" +} + +if [[ "$BRANCH_NAME" == "main" ]]; then + run_default_ci + exit 0 +fi + +if grep -qE "$CHANGE_MATCH" <<< "$CHANGED_FILES"; then + run_ci_for_changed_files +fi From 9f1aa4330060331bd074be2ee20516252f909d1a Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 23 May 2023 16:58:21 -0400 Subject: [PATCH 059/228] test: moving ssl utility to use parsed protos (#27585) Signed-off-by: Alyssa Wilk --- test/integration/BUILD | 6 ++-- test/integration/ssl_utility.cc | 53 +++++++++++---------------------- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/test/integration/BUILD b/test/integration/BUILD index fbcbfbfaf828..cb6be550d383 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -1101,12 +1101,14 @@ envoy_cc_test_library( name = "utility_lib", srcs = [ "server.cc", + "ssl_utility.cc", "utility.cc", - ] + envoy_select_enable_yaml(["ssl_utility.cc"]), + ], hdrs = [ "server.h", + "ssl_utility.h", "utility.h", - ] + envoy_select_enable_yaml(["ssl_utility.h"]), + ], data = ["//test/common/runtime:filesystem_test_data"], deps = [ ":server_stats_interface", diff --git a/test/integration/ssl_utility.cc b/test/integration/ssl_utility.cc index af93ec2c3a48..be1c9d8a2009 100644 --- a/test/integration/ssl_utility.cc +++ b/test/integration/ssl_utility.cc @@ -25,47 +25,30 @@ namespace Ssl { void initializeUpstreamTlsContextConfig( const ClientSslTransportOptions& options, envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext& tls_context) { - std::string yaml_plain = R"EOF( - common_tls_context: - validation_context: - trusted_ca: - filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" -)EOF"; + std::string rundir = TestEnvironment::runfilesDirectory(); + tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_trusted_ca() + ->set_filename(rundir + "/test/config/integration/certs/cacert.pem"); + auto* certs = tls_context.mutable_common_tls_context()->add_tls_certificates(); + std::string chain; + std::string key; if (options.client_ecdsa_cert_) { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/config/integration/certs/client_ecdsacert.pem" - private_key: - filename: "{{ test_rundir }}/test/config/integration/certs/client_ecdsakey.pem" -)EOF"; + chain = rundir + "/test/config/integration/certs/client_ecdsacert.pem"; + key = rundir + "/test/config/integration/certs/client_ecdsakey.pem"; } else if (options.use_expired_spiffe_cert_) { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem" - private_key: - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_key.pem" -)EOF"; + chain = rundir + "/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem"; + key = rundir + "/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_key.pem"; } else if (options.client_with_intermediate_cert_) { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/config/integration/certs/client2_chain.pem" - private_key: - filename: "{{ test_rundir }}/test/config/integration/certs/client2key.pem" -)EOF"; + chain = rundir + "/test/config/integration/certs/client2_chain.pem"; + key = rundir + "/test/config/integration/certs/client2key.pem"; } else { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/config/integration/certs/clientcert.pem" - private_key: - filename: "{{ test_rundir }}/test/config/integration/certs/clientkey.pem" -)EOF"; + chain = rundir + "/test/config/integration/certs/clientcert.pem"; + key = rundir + "/test/config/integration/certs/clientkey.pem"; } + certs->mutable_certificate_chain()->set_filename(chain); + certs->mutable_private_key()->set_filename(key); - TestUtility::loadFromYaml(TestEnvironment::substitute(yaml_plain), tls_context); auto* common_context = tls_context.mutable_common_tls_context(); if (options.alpn_) { From ce9c61fe760fafa6d3033fc6bc45a013d37a8b5e Mon Sep 17 00:00:00 2001 From: Shriram Rajagopalan Date: Tue, 23 May 2023 20:16:27 -0400 Subject: [PATCH 060/228] Ext proc logging: track bytes transferred and upstream info in filter state (#27521) ext proc: track bytes transferred and upstream info in filter state Risk Level: Low Testing: Unit tests Signed-off-by: Shriram Rajagopalan --- changelogs/current.yaml | 2 +- envoy/http/filter.h | 2 +- .../extensions/filters/http/ext_proc/client.h | 1 + .../filters/http/ext_proc/client_impl.h | 2 ++ .../filters/http/ext_proc/ext_proc.cc | 10 +++++++ .../filters/http/ext_proc/ext_proc.h | 25 ++++++++++++++++ .../filters/http/ext_proc/filter_test.cc | 30 +++++++++++++++---- .../filters/http/ext_proc/mock_server.h | 1 + .../filters/http/ext_proc/ordering_test.cc | 3 ++ .../unit_test_fuzz/ext_proc_unit_test_fuzz.cc | 3 ++ .../http/ext_proc/unit_test_fuzz/mocks.h | 1 + 11 files changed, 72 insertions(+), 8 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index c73629831412..a39d3c460410 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -219,7 +219,7 @@ new_features: - area: ext_proc change: | added new field ``filter_metadata downstreamCallbacks() PURE; /** - * @return absl::string_view the name of the filter as configured in the filter chain.. + * @return absl::string_view the name of the filter as configured in the filter chain. */ virtual absl::string_view filterConfigName() const PURE; }; diff --git a/source/extensions/filters/http/ext_proc/client.h b/source/extensions/filters/http/ext_proc/client.h index 95c50f9ec5b1..1cf1bb605308 100644 --- a/source/extensions/filters/http/ext_proc/client.h +++ b/source/extensions/filters/http/ext_proc/client.h @@ -20,6 +20,7 @@ class ExternalProcessorStream { bool end_stream) PURE; // Idempotent close. Return true if it actually closed. virtual bool close() PURE; + virtual const StreamInfo::StreamInfo& streamInfo() const PURE; }; using ExternalProcessorStreamPtr = std::unique_ptr; diff --git a/source/extensions/filters/http/ext_proc/client_impl.h b/source/extensions/filters/http/ext_proc/client_impl.h index 498139e3a3e5..4f808b02b67f 100644 --- a/source/extensions/filters/http/ext_proc/client_impl.h +++ b/source/extensions/filters/http/ext_proc/client_impl.h @@ -7,6 +7,7 @@ #include "envoy/grpc/async_client_manager.h" #include "envoy/service/ext_proc/v3/external_processor.pb.h" #include "envoy/stats/scope.h" +#include "envoy/stream_info/stream_info.h" #include "source/common/grpc/typed_async_client.h" #include "source/extensions/filters/http/ext_proc/client.h" @@ -54,6 +55,7 @@ class ExternalProcessorStreamImpl : public ExternalProcessorStream, void onReceiveInitialMetadata(Http::ResponseHeaderMapPtr&& metadata) override; void onReceiveTrailingMetadata(Http::ResponseTrailerMapPtr&& metadata) override; void onRemoteClose(Grpc::Status::GrpcStatus status, const std::string& message) override; + const StreamInfo::StreamInfo& streamInfo() const override { return stream_.streamInfo(); } private: ExternalProcessorCallbacks& callbacks_; diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index b56f3da39cb1..fd45f89921c8 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -127,12 +127,22 @@ Filter::StreamOpenState Filter::openStream() { // Stream failed while starting and either onGrpcError or onGrpcClose was already called return sent_immediate_response_ ? StreamOpenState::Error : StreamOpenState::IgnoreError; } + // For custom access logging purposes. Applicable only for Envoy gRPC as Google gRPC does not + // have a proper implementation of streamInfo. + if (grpc_service_.has_envoy_grpc()) { + logging_info_->setClusterInfo(stream_->streamInfo().upstreamClusterInfo()); + logging_info_->setUpstreamHost(stream_->streamInfo().upstreamInfo()->upstreamHost()); + } } return StreamOpenState::Ok; } void Filter::closeStream() { if (stream_) { + if (grpc_service_.has_envoy_grpc()) { + logging_info_->setBytesSent(stream_->streamInfo().bytesSent()); + logging_info_->setBytesReceived(stream_->streamInfo().bytesReceived()); + } ENVOY_LOG(debug, "Calling close on stream"); if (stream_->close()) { stats_.streams_closed_.inc(); diff --git a/source/extensions/filters/http/ext_proc/ext_proc.h b/source/extensions/filters/http/ext_proc/ext_proc.h index fbdd050f41ad..f3a380547a8b 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.h +++ b/source/extensions/filters/http/ext_proc/ext_proc.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -13,6 +14,9 @@ #include "envoy/service/ext_proc/v3/external_processor.pb.h" #include "envoy/stats/scope.h" #include "envoy/stats/stats_macros.h" +#include "envoy/stream_info/stream_info.h" +#include "envoy/upstream/host_description.h" +#include "envoy/upstream/upstream.h" #include "source/common/common/logger.h" #include "source/common/protobuf/protobuf.h" @@ -63,7 +67,23 @@ class ExtProcLoggingInfo : public Envoy::StreamInfo::FilterState::Object { void recordGrpcCall(std::chrono::microseconds latency, Grpc::Status::GrpcStatus call_status, ProcessorState::CallbackState callback_state, envoy::config::core::v3::TrafficDirection traffic_direction); + void setBytesSent(uint64_t bytes_sent) { bytes_sent_ = bytes_sent; } + void setBytesReceived(uint64_t bytes_received) { bytes_received_ = bytes_received; } + void setClusterInfo(absl::optional cluster_info) { + if (cluster_info) { + cluster_info_ = cluster_info.value(); + } + } + void setUpstreamHost(absl::optional upstream_host) { + if (upstream_host) { + upstream_host_ = upstream_host.value(); + } + } + uint64_t bytesSent() const { return bytes_sent_; } + uint64_t bytesReceived() const { return bytes_received_; } + Upstream::ClusterInfoConstSharedPtr clusterInfo() const { return cluster_info_; } + Upstream::HostDescriptionConstSharedPtr upstreamHost() const { return upstream_host_; } const GrpcCalls& grpcCalls(envoy::config::core::v3::TrafficDirection traffic_direction) const; const Envoy::ProtobufWkt::Struct& filterMetadata() const { return filter_metadata_; } @@ -72,6 +92,11 @@ class ExtProcLoggingInfo : public Envoy::StreamInfo::FilterState::Object { GrpcCalls decoding_processor_grpc_calls_; GrpcCalls encoding_processor_grpc_calls_; const Envoy::ProtobufWkt::Struct filter_metadata_; + // The following stats are populated for ext_proc filters using Envoy gRPC only. + // The bytes sent and received are for the entire stream. + uint64_t bytes_sent_{0}, bytes_received_{0}; + Upstream::ClusterInfoConstSharedPtr cluster_info_; + Upstream::HostDescriptionConstSharedPtr upstream_host_; }; class FilterConfig { diff --git a/test/extensions/filters/http/ext_proc/filter_test.cc b/test/extensions/filters/http/ext_proc/filter_test.cc index 45990a18e3cb..009458d53c6d 100644 --- a/test/extensions/filters/http/ext_proc/filter_test.cc +++ b/test/extensions/filters/http/ext_proc/filter_test.cc @@ -81,6 +81,17 @@ class HttpFilterTest : public testing::Test { EXPECT_CALL(decoder_callbacks_, dispatcher()).WillRepeatedly(ReturnRef(dispatcher_)); EXPECT_CALL(decoder_callbacks_, route()).WillRepeatedly(Return(route_)); EXPECT_CALL(decoder_callbacks_, streamInfo()).WillRepeatedly(ReturnRef(stream_info_)); + + EXPECT_CALL(async_client_stream_info_, bytesSent()).WillRepeatedly(Return(100)); + EXPECT_CALL(async_client_stream_info_, bytesReceived()).WillRepeatedly(Return(200)); + EXPECT_CALL(async_client_stream_info_, upstreamClusterInfo()); + EXPECT_CALL(testing::Const(async_client_stream_info_), upstreamInfo()); + // Get pointer to MockUpstreamInfo. + std::shared_ptr mock_upstream_info = + std::dynamic_pointer_cast( + async_client_stream_info_.upstreamInfo()); + EXPECT_CALL(testing::Const(*mock_upstream_info), upstreamHost()); + EXPECT_CALL(dispatcher_, createTimer_(_)) .Times(AnyNumber()) .WillRepeatedly(Invoke([this](Unused) { @@ -138,6 +149,9 @@ class HttpFilterTest : public testing::Test { auto stream = std::make_unique(); // We never send with the "close" flag set EXPECT_CALL(*stream, send(_, false)).WillRepeatedly(Invoke(this, &HttpFilterTest::doSend)); + + EXPECT_CALL(*stream, streamInfo()).WillRepeatedly(ReturnRef(async_client_stream_info_)); + // close is idempotent and only called once per filter EXPECT_CALL(*stream, close()).WillOnce(Invoke(this, &HttpFilterTest::doSendClose)); return stream; @@ -287,14 +301,17 @@ class HttpFilterTest : public testing::Test { } // The metadata configured as part of ext_proc filter should be in the filter state. - void expectMetadataInFilterState(const Envoy::ProtobufWkt::Struct& expected_metadata) { - const Envoy::ProtobufWkt::Struct& loggedMetadata = + // In addition, bytes sent/received should also be stored. + void expectFilterState(const Envoy::ProtobufWkt::Struct& expected_metadata) { + const auto* filterState = stream_info_.filterState() ->getDataReadOnly< Envoy::Extensions::HttpFilters::ExternalProcessing::ExtProcLoggingInfo>( - filter_config_name) - ->filterMetadata(); + filter_config_name); + const Envoy::ProtobufWkt::Struct& loggedMetadata = filterState->filterMetadata(); EXPECT_THAT(loggedMetadata, ProtoEq(expected_metadata)); + EXPECT_EQ(filterState->bytesSent(), 100); + EXPECT_EQ(filterState->bytesReceived(), 200); } absl::optional final_expected_grpc_service_; @@ -310,6 +327,7 @@ class HttpFilterTest : public testing::Test { testing::NiceMock encoder_callbacks_; Router::RouteConstSharedPtr route_; testing::NiceMock stream_info_; + testing::NiceMock async_client_stream_info_; Http::TestRequestHeaderMapImpl request_headers_; Http::TestResponseHeaderMapImpl response_headers_; Http::TestRequestTrailerMapImpl request_trailers_; @@ -385,7 +403,7 @@ TEST_F(HttpFilterTest, SimplestPost) { Envoy::ProtobufWkt::Struct filter_metadata; (*filter_metadata.mutable_fields())["scooby"].set_string_value("doo"); - expectMetadataInFilterState(filter_metadata); + expectFilterState(filter_metadata); } // Using the default configuration, test the filter with a processor that @@ -531,7 +549,7 @@ TEST_F(HttpFilterTest, PostAndRespondImmediately) { EXPECT_EQ(1, config_->stats().streams_closed_.value()); expectGrpcCalls(envoy::config::core::v3::TrafficDirection::INBOUND, Grpc::Status::Ok, 1); expectGrpcCalls(envoy::config::core::v3::TrafficDirection::OUTBOUND, Grpc::Status::Ok, 0); - expectMetadataInFilterState(Envoy::ProtobufWkt::Struct()); + expectFilterState(Envoy::ProtobufWkt::Struct()); } // Using the default configuration, test the filter with a processor that diff --git a/test/extensions/filters/http/ext_proc/mock_server.h b/test/extensions/filters/http/ext_proc/mock_server.h index f9d931603a79..f655e977a2e4 100644 --- a/test/extensions/filters/http/ext_proc/mock_server.h +++ b/test/extensions/filters/http/ext_proc/mock_server.h @@ -24,6 +24,7 @@ class MockStream : public ExternalProcessorStream { ~MockStream() override; MOCK_METHOD(void, send, (envoy::service::ext_proc::v3::ProcessingRequest&&, bool)); MOCK_METHOD(bool, close, ()); + MOCK_METHOD(const StreamInfo::StreamInfo&, streamInfo, (), (const override)); }; } // namespace ExternalProcessing diff --git a/test/extensions/filters/http/ext_proc/ordering_test.cc b/test/extensions/filters/http/ext_proc/ordering_test.cc index 1d0d4c52b7cb..2f9575c6265a 100644 --- a/test/extensions/filters/http/ext_proc/ordering_test.cc +++ b/test/extensions/filters/http/ext_proc/ordering_test.cc @@ -86,6 +86,7 @@ class OrderingTest : public testing::Test { stream_callbacks_ = &callbacks; auto stream = std::make_unique(); EXPECT_CALL(*stream, send(_, _)).WillRepeatedly(Invoke(this, &OrderingTest::doSend)); + EXPECT_CALL(*stream, streamInfo()).WillRepeatedly(ReturnRef(async_client_stream_info_)); EXPECT_CALL(*stream, close()); return stream; } @@ -206,6 +207,7 @@ class OrderingTest : public testing::Test { NiceMock decoder_callbacks_; NiceMock encoder_callbacks_; testing::NiceMock stream_info_; + testing::NiceMock async_client_stream_info_; Http::TestRequestHeaderMapImpl request_headers_; Http::TestResponseHeaderMapImpl response_headers_; Http::TestRequestTrailerMapImpl request_trailers_; @@ -221,6 +223,7 @@ class FastFailOrderingTest : public OrderingTest { const StreamInfo::StreamInfo&) override { auto stream = std::make_unique(); EXPECT_CALL(*stream, close()); + EXPECT_CALL(*stream, streamInfo()).WillRepeatedly(ReturnRef(async_client_stream_info_)); callbacks.onGrpcError(Grpc::Status::Internal); return stream; } diff --git a/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc index 89d6c55c9069..477a04bb2841 100644 --- a/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc +++ b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc @@ -33,6 +33,7 @@ class FuzzerMocks { NiceMock connection_; NiceMock request_trailers_; NiceMock response_trailers_; + testing::NiceMock async_client_stream_info_; }; DEFINE_PROTO_FUZZER( @@ -85,6 +86,8 @@ DEFINE_PROTO_FUZZER( input.response()); filter->onReceiveMessage(std::move(response)); })); + EXPECT_CALL(*stream, streamInfo()) + .WillRepeatedly(ReturnRef(mocks.async_client_stream_info_)); ON_CALL(*stream, close()).WillByDefault(Return(false)); return stream; })); diff --git a/test/extensions/filters/http/ext_proc/unit_test_fuzz/mocks.h b/test/extensions/filters/http/ext_proc/unit_test_fuzz/mocks.h index 9ae229e83a15..cbfafb5f2473 100644 --- a/test/extensions/filters/http/ext_proc/unit_test_fuzz/mocks.h +++ b/test/extensions/filters/http/ext_proc/unit_test_fuzz/mocks.h @@ -20,6 +20,7 @@ class MockStream : public ExternalProcessing::ExternalProcessorStream { MOCK_METHOD(void, send, (envoy::service::ext_proc::v3::ProcessingRequest && request, bool end_stream)); MOCK_METHOD(bool, close, ()); + MOCK_METHOD(const StreamInfo::StreamInfo&, streamInfo, (), (const override)); }; class MockClient : public ExternalProcessing::ExternalProcessorClient { From af9b04edc8349ee34fa21ab98b0965f8816f718d Mon Sep 17 00:00:00 2001 From: code Date: Wed, 24 May 2023 08:35:48 +0800 Subject: [PATCH 061/228] upstream: the cluster provoded load balancing policy could be configured as extension (#27512) * upstream: the cluster provoded load balancing policy could be configured as extension Signed-off-by: wbpcode * address comments Signed-off-by: wbpcode --------- Signed-off-by: wbpcode --- CODEOWNERS | 1 + api/BUILD | 1 + .../cluster_provided/v3/BUILD | 9 ++ .../v3/cluster_provided.proto | 24 ++++ api/versioning/BUILD | 1 + changelogs/current.yaml | 5 + .../common/upstream/cluster_manager_impl.cc | 58 +++++----- source/extensions/extensions_build_config.bzl | 5 +- source/extensions/extensions_metadata.yaml | 7 ++ .../cluster_provided/BUILD | 19 ++++ .../cluster_provided/config.cc | 24 ++++ .../cluster_provided/config.h | 31 ++++++ .../cluster_provided/BUILD | 40 +++++++ .../cluster_provided/config_test.cc | 41 +++++++ .../cluster_provided/integration_test.cc | 103 ++++++++++++++++++ 15 files changed, 342 insertions(+), 27 deletions(-) create mode 100644 api/envoy/extensions/load_balancing_policies/cluster_provided/v3/BUILD create mode 100644 api/envoy/extensions/load_balancing_policies/cluster_provided/v3/cluster_provided.proto create mode 100644 source/extensions/load_balancing_policies/cluster_provided/BUILD create mode 100644 source/extensions/load_balancing_policies/cluster_provided/config.cc create mode 100644 source/extensions/load_balancing_policies/cluster_provided/config.h create mode 100644 test/extensions/load_balancing_policies/cluster_provided/BUILD create mode 100644 test/extensions/load_balancing_policies/cluster_provided/config_test.cc create mode 100644 test/extensions/load_balancing_policies/cluster_provided/integration_test.cc diff --git a/CODEOWNERS b/CODEOWNERS index adc46f60230d..efa25078addf 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -298,6 +298,7 @@ extensions/filters/http/oauth2 @derekargueta @snowp /*/extensions/load_balancing_policies/ring_hash @wbpcode @UNOWNED /*/extensions/load_balancing_policies/maglev @wbpcode @UNOWNED /*/extensions/load_balancing_policies/subset @wbpcode @zuercher +/*/extensions/load_balancing_policies/cluster_provided @wbpcode @zuercher # Early header mutation /*/extensions/http/early_header_mutation/header_mutation @wbpcode @UNOWNED # Network matching extensions diff --git a/api/BUILD b/api/BUILD index 898f318b5795..cc3a5068531d 100644 --- a/api/BUILD +++ b/api/BUILD @@ -252,6 +252,7 @@ proto_library( "//envoy/extensions/internal_redirect/previous_routes/v3:pkg", "//envoy/extensions/internal_redirect/safe_cross_scheme/v3:pkg", "//envoy/extensions/key_value/file_based/v3:pkg", + "//envoy/extensions/load_balancing_policies/cluster_provided/v3:pkg", "//envoy/extensions/load_balancing_policies/common/v3:pkg", "//envoy/extensions/load_balancing_policies/least_request/v3:pkg", "//envoy/extensions/load_balancing_policies/maglev/v3:pkg", diff --git a/api/envoy/extensions/load_balancing_policies/cluster_provided/v3/BUILD b/api/envoy/extensions/load_balancing_policies/cluster_provided/v3/BUILD new file mode 100644 index 000000000000..ee92fb652582 --- /dev/null +++ b/api/envoy/extensions/load_balancing_policies/cluster_provided/v3/BUILD @@ -0,0 +1,9 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"], +) diff --git a/api/envoy/extensions/load_balancing_policies/cluster_provided/v3/cluster_provided.proto b/api/envoy/extensions/load_balancing_policies/cluster_provided/v3/cluster_provided.proto new file mode 100644 index 000000000000..bf12abc6e899 --- /dev/null +++ b/api/envoy/extensions/load_balancing_policies/cluster_provided/v3/cluster_provided.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +package envoy.extensions.load_balancing_policies.cluster_provided.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.load_balancing_policies.cluster_provided.v3"; +option java_outer_classname = "ClusterProvidedProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/cluster_provided/v3;cluster_providedv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Cluster Provided Load Balancing Policy] +// [#extension: envoy.load_balancing_policies.cluster_provided] + +// The cluster provided load balancing policy allows cluster to specify its own load balancing. +// If this extension is configured, the target cluster must provide load balancer when the cluster +// is created. +// +// ..note:: +// Cluster provided load balancing policy could not be used as sub-policy of other hierarchical +// load balancing policies, such as subset load balancing policy. +message ClusterProvided { +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index ad7aa0d75b47..4f4a25d60e82 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -191,6 +191,7 @@ proto_library( "//envoy/extensions/internal_redirect/safe_cross_scheme/v3:pkg", "//envoy/extensions/key_value/file_based/v3:pkg", "//envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3:pkg", + "//envoy/extensions/load_balancing_policies/cluster_provided/v3:pkg", "//envoy/extensions/load_balancing_policies/common/v3:pkg", "//envoy/extensions/load_balancing_policies/least_request/v3:pkg", "//envoy/extensions/load_balancing_policies/maglev/v3:pkg", diff --git a/changelogs/current.yaml b/changelogs/current.yaml index a39d3c460410..e0205dcb8888 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -212,6 +212,11 @@ new_features: - area: admin change: | Adds a new admin stats html bucket-mode ``detailed`` to generate all recorded buckets and summary percentiles. +- area: upstream + change: | + Added :ref:`cluster provided extension + ` + to suppport the :ref:`load balancer policy `. - area: fault change: | added new field ``envoy.extensions.filters.http.fault.v3.HTTPFault.filter_metadata`` to aid in logging. diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index d5a2b85fb0f6..a273a397b791 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -835,24 +835,35 @@ ClusterManagerImpl::loadCluster(const envoy::config::cluster::v3::Cluster& clust auto& lb = new_cluster_pair_or_error->second; Cluster& cluster_reference = *new_cluster; + const auto cluster_info = cluster_reference.info(); + if (!added_via_api) { - if (cluster_map.find(new_cluster->info()->name()) != cluster_map.end()) { + if (cluster_map.find(cluster_info->name()) != cluster_map.end()) { throw EnvoyException( - fmt::format("cluster manager: duplicate cluster '{}'", new_cluster->info()->name())); + fmt::format("cluster manager: duplicate cluster '{}'", cluster_info->name())); } } - if (cluster_reference.info()->lbType() == LoadBalancerType::ClusterProvided && lb == nullptr) { + // Check if the cluster provided load balancing policy is used. We need handle it as special + // case. + bool cluster_provided_lb = cluster_info->lbType() == LoadBalancerType::ClusterProvided; + if (cluster_info->lbType() == LoadBalancerType::LoadBalancingPolicyConfig) { + TypedLoadBalancerFactory* typed_lb_factory = cluster_info->loadBalancerFactory(); + RELEASE_ASSERT(typed_lb_factory != nullptr, "ClusterInfo should contain a valid factory"); + cluster_provided_lb = + typed_lb_factory->name() == "envoy.load_balancing_policies.cluster_provided"; + } + + if (cluster_provided_lb && lb == nullptr) { throw EnvoyException(fmt::format("cluster manager: cluster provided LB specified but cluster " "'{}' did not provide one. Check cluster documentation.", - new_cluster->info()->name())); + cluster_info->name())); } - - if (cluster_reference.info()->lbType() != LoadBalancerType::ClusterProvided && lb != nullptr) { + if (!cluster_provided_lb && lb != nullptr) { throw EnvoyException( fmt::format("cluster manager: cluster provided LB not specified but cluster " "'{}' provided one. Check cluster documentation.", - new_cluster->info()->name())); + cluster_info->name())); } if (new_cluster->healthChecker() != nullptr) { @@ -876,7 +887,7 @@ ClusterManagerImpl::loadCluster(const envoy::config::cluster::v3::Cluster& clust }); } ClusterDataPtr result; - auto cluster_entry_it = cluster_map.find(cluster_reference.info()->name()); + auto cluster_entry_it = cluster_map.find(cluster_info->name()); if (cluster_entry_it != cluster_map.end()) { result = std::exchange(cluster_entry_it->second, std::make_unique(cluster, cluster_hash, version_info, @@ -885,7 +896,7 @@ ClusterManagerImpl::loadCluster(const envoy::config::cluster::v3::Cluster& clust } else { bool inserted = false; std::tie(cluster_entry_it, inserted) = cluster_map.emplace( - cluster_reference.info()->name(), + cluster_info->name(), std::make_unique(cluster, cluster_hash, version_info, added_via_api, std::move(new_cluster), time_source_)); ASSERT(inserted); @@ -893,30 +904,27 @@ ClusterManagerImpl::loadCluster(const envoy::config::cluster::v3::Cluster& clust // If an LB is thread aware, create it here. The LB is not initialized until cluster pre-init // finishes. For RingHash/Maglev don't create the LB here if subset balancing is enabled, // because the thread_aware_lb_ field takes precedence over the subset lb). - if (cluster_reference.info()->lbType() == LoadBalancerType::RingHash) { - if (!cluster_reference.info()->lbSubsetInfo().isEnabled()) { + if (cluster_info->lbType() == LoadBalancerType::RingHash) { + if (!cluster_info->lbSubsetInfo().isEnabled()) { auto& factory = Config::Utility::getAndCheckFactoryByName( "envoy.load_balancing_policies.ring_hash"); - cluster_entry_it->second->thread_aware_lb_ = - factory.create(*cluster_reference.info(), cluster_reference.prioritySet(), runtime_, - random_, time_source_); + cluster_entry_it->second->thread_aware_lb_ = factory.create( + *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_); } - } else if (cluster_reference.info()->lbType() == LoadBalancerType::Maglev) { - if (!cluster_reference.info()->lbSubsetInfo().isEnabled()) { + } else if (cluster_info->lbType() == LoadBalancerType::Maglev) { + if (!cluster_info->lbSubsetInfo().isEnabled()) { auto& factory = Config::Utility::getAndCheckFactoryByName( "envoy.load_balancing_policies.maglev"); - cluster_entry_it->second->thread_aware_lb_ = - factory.create(*cluster_reference.info(), cluster_reference.prioritySet(), runtime_, - random_, time_source_); + cluster_entry_it->second->thread_aware_lb_ = factory.create( + *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_); } - } else if (cluster_reference.info()->lbType() == LoadBalancerType::ClusterProvided) { + } else if (cluster_provided_lb) { cluster_entry_it->second->thread_aware_lb_ = std::move(lb); - } else if (cluster_reference.info()->lbType() == LoadBalancerType::LoadBalancingPolicyConfig) { - TypedLoadBalancerFactory* typed_lb_factory = cluster_reference.info()->loadBalancerFactory(); + } else if (cluster_info->lbType() == LoadBalancerType::LoadBalancingPolicyConfig) { + TypedLoadBalancerFactory* typed_lb_factory = cluster_info->loadBalancerFactory(); RELEASE_ASSERT(typed_lb_factory != nullptr, "ClusterInfo should contain a valid factory"); - cluster_entry_it->second->thread_aware_lb_ = - typed_lb_factory->create(*cluster_reference.info(), cluster_reference.prioritySet(), - runtime_, random_, time_source_); + cluster_entry_it->second->thread_aware_lb_ = typed_lb_factory->create( + *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_); } updateClusterCounts(); diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index 9024d14b66c0..e0370c799dc2 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -426,8 +426,9 @@ EXTENSIONS = { "envoy.load_balancing_policies.random": "//source/extensions/load_balancing_policies/random:config", "envoy.load_balancing_policies.round_robin": "//source/extensions/load_balancing_policies/round_robin:config", "envoy.load_balancing_policies.maglev": "//source/extensions/load_balancing_policies/maglev:config", - "envoy.load_balancing_policies.ring_hash": "//source/extensions/load_balancing_policies/ring_hash:config", - "envoy.load_balancing_policies.subset": "//source/extensions/load_balancing_policies/subset:config", + "envoy.load_balancing_policies.ring_hash": "//source/extensions/load_balancing_policies/ring_hash:config", + "envoy.load_balancing_policies.subset": "//source/extensions/load_balancing_policies/subset:config", + "envoy.load_balancing_policies.cluster_provided": "//source/extensions/load_balancing_policies/cluster_provided:config", # # HTTP Early Header Mutation diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 4513925d8d31..c1e704971d5a 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -1490,6 +1490,13 @@ envoy.load_balancing_policies.subset: - envoy.load_balancing_policies security_posture: robust_to_untrusted_downstream_and_upstream status: stable +envoy.load_balancing_policies.cluster_provided: + categories: + - envoy.load_balancing_policies + security_posture: robust_to_untrusted_downstream_and_upstream + status: stable + type_urls: + - envoy.extensions.load_balancing_policies.cluster_provided.v3.ClusterProvided envoy.http.early_header_mutation.header_mutation: categories: - envoy.http.early_header_mutation diff --git a/source/extensions/load_balancing_policies/cluster_provided/BUILD b/source/extensions/load_balancing_policies/cluster_provided/BUILD new file mode 100644 index 000000000000..2cd5fcce2124 --- /dev/null +++ b/source/extensions/load_balancing_policies/cluster_provided/BUILD @@ -0,0 +1,19 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + deps = [ + "//source/common/upstream:load_balancer_factory_base_lib", + "@envoy_api//envoy/extensions/load_balancing_policies/cluster_provided/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/load_balancing_policies/cluster_provided/config.cc b/source/extensions/load_balancing_policies/cluster_provided/config.cc new file mode 100644 index 000000000000..33245f9b7907 --- /dev/null +++ b/source/extensions/load_balancing_policies/cluster_provided/config.cc @@ -0,0 +1,24 @@ +#include "source/extensions/load_balancing_policies/cluster_provided/config.h" + +namespace Envoy { +namespace Extensions { +namespace LoadBalancingPolices { +namespace ClusterProvided { + +Upstream::ThreadAwareLoadBalancerPtr Factory::create(const Upstream::ClusterInfo&, + const Upstream::PrioritySet&, Runtime::Loader&, + Random::RandomGenerator&, TimeSource&) { + // Cluster provided load balancer has empty implementation. Because it is a special case to + // tell the cluster to use the load balancer provided by the cluster. + return nullptr; +}; + +/** + * Static registration for the Factory. @see RegisterFactory. + */ +REGISTER_FACTORY(Factory, Upstream::TypedLoadBalancerFactory); + +} // namespace ClusterProvided +} // namespace LoadBalancingPolices +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/load_balancing_policies/cluster_provided/config.h b/source/extensions/load_balancing_policies/cluster_provided/config.h new file mode 100644 index 000000000000..ef1d73da6969 --- /dev/null +++ b/source/extensions/load_balancing_policies/cluster_provided/config.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "envoy/extensions/load_balancing_policies/cluster_provided/v3/cluster_provided.pb.h" +#include "envoy/upstream/load_balancer.h" + +#include "source/common/upstream/load_balancer_factory_base.h" + +namespace Envoy { +namespace Extensions { +namespace LoadBalancingPolices { +namespace ClusterProvided { + +class Factory + : public Upstream::TypedLoadBalancerFactoryBase< + envoy::extensions::load_balancing_policies::cluster_provided::v3::ClusterProvided> { +public: + Factory() : TypedLoadBalancerFactoryBase("envoy.load_balancing_policies.cluster_provided") {} + + Upstream::ThreadAwareLoadBalancerPtr create(const Upstream::ClusterInfo& cluster_info, + const Upstream::PrioritySet& priority_set, + Runtime::Loader& runtime, + Random::RandomGenerator& random, + TimeSource& time_source) override; +}; + +} // namespace ClusterProvided +} // namespace LoadBalancingPolices +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/load_balancing_policies/cluster_provided/BUILD b/test/extensions/load_balancing_policies/cluster_provided/BUILD new file mode 100644 index 000000000000..af0b1d96c2af --- /dev/null +++ b/test/extensions/load_balancing_policies/cluster_provided/BUILD @@ -0,0 +1,40 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_extension_cc_test( + name = "config_test", + srcs = ["config_test.cc"], + extension_names = ["envoy.load_balancing_policies.cluster_provided"], + deps = [ + "//source/extensions/load_balancing_policies/cluster_provided:config", + "//test/mocks/server:factory_context_mocks", + "//test/mocks/upstream:cluster_info_mocks", + "//test/mocks/upstream:priority_set_mocks", + "@envoy_api//envoy/config/core/v3:pkg_cc_proto", + ], +) + +envoy_extension_cc_test( + name = "integration_test", + size = "large", + srcs = ["integration_test.cc"], + extension_names = ["envoy.load_balancing_policies.cluster_provided"], + deps = [ + "//source/common/protobuf", + "//source/extensions/clusters/original_dst:original_dst_cluster_lib", + "//source/extensions/load_balancing_policies/cluster_provided:config", + "//test/integration:http_integration_lib", + "//test/test_common:utility_lib", + "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/load_balancing_policies/cluster_provided/config_test.cc b/test/extensions/load_balancing_policies/cluster_provided/config_test.cc new file mode 100644 index 000000000000..e0966208e7aa --- /dev/null +++ b/test/extensions/load_balancing_policies/cluster_provided/config_test.cc @@ -0,0 +1,41 @@ +#include "envoy/config/core/v3/extension.pb.h" + +#include "source/extensions/load_balancing_policies/cluster_provided/config.h" + +#include "test/mocks/server/factory_context.h" +#include "test/mocks/upstream/cluster_info.h" +#include "test/mocks/upstream/priority_set.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace LoadBalancingPolices { +namespace ClusterProvided { +namespace { + +TEST(ClusterProvidedConfigTest, ClusterProvidedConfigTest) { + NiceMock context; + NiceMock cluster_info; + NiceMock main_thread_priority_set; + NiceMock thread_local_priority_set; + + envoy::config::core::v3::TypedExtensionConfig config; + config.set_name("envoy.load_balancing_policies.cluster_provided"); + envoy::extensions::load_balancing_policies::cluster_provided::v3::ClusterProvided config_msg; + config.mutable_typed_config()->PackFrom(config_msg); + + auto& factory = Config::Utility::getAndCheckFactory(config); + EXPECT_EQ("envoy.load_balancing_policies.cluster_provided", factory.name()); + + auto thread_aware_lb = + factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_, + context.api_.random_, context.time_system_); + EXPECT_EQ(nullptr, thread_aware_lb); +} + +} // namespace +} // namespace ClusterProvided +} // namespace LoadBalancingPolices +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/load_balancing_policies/cluster_provided/integration_test.cc b/test/extensions/load_balancing_policies/cluster_provided/integration_test.cc new file mode 100644 index 000000000000..c190be34bc8d --- /dev/null +++ b/test/extensions/load_balancing_policies/cluster_provided/integration_test.cc @@ -0,0 +1,103 @@ +#include +#include + +#include "envoy/config/endpoint/v3/endpoint_components.pb.h" + +#include "source/common/common/base64.h" +#include "source/common/http/utility.h" +#include "source/common/protobuf/protobuf.h" +#include "source/extensions/load_balancing_policies/cluster_provided/config.h" + +#include "test/integration/http_integration.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace LoadBalancingPolices { +namespace ClusterProvided { +namespace { + +class ClusterProvidedIntegrationTest : public testing::TestWithParam, + public HttpIntegrationTest { +public: + ClusterProvidedIntegrationTest() : HttpIntegrationTest(Http::CodecType::HTTP1, GetParam()) { + // Create 3 different upstream server. + setUpstreamCount(3); + + // Update endpoints of default cluster `cluster_0` to `original_dst` cluster. + config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + auto* cluster_0 = bootstrap.mutable_static_resources()->mutable_clusters()->Mutable(0); + ASSERT(cluster_0->name() == "cluster_0"); + + std::string cluster_yaml = R"EOF( + name: cluster_0 + connect_timeout: 1.250s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + original_dst_lb_config: + use_http_header: true + )EOF"; + + TestUtility::loadFromYaml(cluster_yaml, *cluster_0); + + auto* policy = cluster_0->mutable_load_balancing_policy(); + + const std::string policy_yaml = R"EOF( + policies: + - typed_extension_config: + name: envoy.load_balancing_policies.cluster_provided + typed_config: + "@type": type.googleapis.com/envoy.extensions.load_balancing_policies.cluster_provided.v3.ClusterProvided + )EOF"; + + TestUtility::loadFromYaml(policy_yaml, *policy); + }); + } +}; + +INSTANTIATE_TEST_SUITE_P(IpVersions, ClusterProvidedIntegrationTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); + +// Test the case where the cluster provided load balancer is configured by the load balancing +// policy API and it works as expected. +TEST_P(ClusterProvidedIntegrationTest, NormalLoadBalancing) { + initialize(); + + for (uint64_t i = 0; i < 4; i++) { + for (size_t upstream_index = 0; upstream_index < fake_upstreams_.size(); upstream_index++) { + codec_client_ = makeHttpConnection(lookupPort("http")); + + const auto& upstream_target_address = + fake_upstreams_[upstream_index]->localAddress()->asString(); + + Http::TestRequestHeaderMapImpl request_headers{ + {":method", "GET"}, + {":path", "/"}, + {":scheme", "http"}, + {":authority", "example.com"}, + {"x-envoy-original-dst-host", upstream_target_address}}; + + auto response = codec_client_->makeRequestWithBody(request_headers, 0); + + auto upstream = waitForNextUpstreamRequest({0, 1, 2}); + EXPECT_EQ(upstream.value(), upstream_index); + + upstream_request_->encodeHeaders(default_response_headers_, true); + + ASSERT_TRUE(response->waitForEndStream()); + + EXPECT_TRUE(upstream_request_->complete()); + EXPECT_TRUE(response->complete()); + + cleanupUpstreamAndDownstream(); + } + } +} + +} // namespace +} // namespace ClusterProvided +} // namespace LoadBalancingPolices +} // namespace Extensions +} // namespace Envoy From 1cb5be99507b698c50c87ae332ca3fe95cbb12ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Wed, 24 May 2023 10:51:41 +0800 Subject: [PATCH 062/228] chore(dlb): remove unused isOpen call (#27539) Signed-off-by: spacewander --- .../connection_balance/dlb/source/connection_balancer_impl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc b/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc index 6d8cec6c3c04..1e5fd46d5bb9 100644 --- a/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc +++ b/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc @@ -236,9 +236,9 @@ void DlbBalancedConnectionHandlerImpl::setDlbEvent() { dlb_event_->setEnabled(Event::FileReadyType::Read); } -void DlbBalancedConnectionHandlerImpl::post(Network::ConnectionSocketPtr&& socket) { +void DlbBalancedConnectionHandlerImpl::post( + [[maybe_unused]] Network::ConnectionSocketPtr&& socket) { #ifdef DLB_DISABLED - socket->isOpen(); throw EnvoyException("X86_64 architecture is required for Dlb."); #else // The pointer will be casted to unique_ptr in onDlbEvents(), no need to consider free. From cbadae62b8b12e0c1e47a374b10ade88a6a0bba5 Mon Sep 17 00:00:00 2001 From: Peter Leng Date: Tue, 23 May 2023 19:52:18 -0700 Subject: [PATCH 063/228] Route level config support for AWS request signing filter (#27092) Signed-off-by: yleng --- .../v3/aws_request_signing.proto | 9 +++ ...t-signing-filter-route-level-override.yaml | 66 +++++++++++++++++++ .../_include/aws-request-signing-filter.yaml | 52 +++++++++++++++ .../aws_request_signing_filter.rst | 30 +++++---- source/extensions/extensions_metadata.yaml | 1 + .../aws_request_signing_filter.cc | 38 +++++++---- .../aws_request_signing_filter.h | 6 +- .../http/aws_request_signing/config.cc | 24 ++++++- .../filters/http/aws_request_signing/config.h | 23 +++++-- .../aws_request_signing_filter_test.cc | 19 ++++++ .../http/aws_request_signing/config_test.cc | 30 ++++++++- 11 files changed, 260 insertions(+), 38 deletions(-) create mode 100644 docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-route-level-override.yaml create mode 100644 docs/root/configuration/http/http_filters/_include/aws-request-signing-filter.yaml diff --git a/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto b/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto index ba26a3882407..df4633ce63ee 100644 --- a/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto +++ b/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto @@ -64,3 +64,12 @@ message AwsRequestSigning { // When applied, all headers that start with "x-envoy" and headers "foo" and "bar" will not be signed. repeated type.matcher.v3.StringMatcher match_excluded_headers = 5; } + +message AwsRequestSigningPerRoute { + // Override the global configuration of the filter with this new config. + // This overrides the entire message of AwsRequestSigning and not at field level. + AwsRequestSigning aws_request_signing = 1; + + // The human readable prefix to use when emitting stats. + string stat_prefix = 2 [(validate.rules).string = {min_len: 1}]; +} diff --git a/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-route-level-override.yaml b/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-route-level-override.yaml new file mode 100644 index 000000000000..987d99134053 --- /dev/null +++ b/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-route-level-override.yaml @@ -0,0 +1,66 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 80 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: app + domains: + - "*" + routes: + - match: + prefix: "/" + route: + cluster: versioned-cluster + typed_per_filter_config: + envoy.filters.http.aws_request_signing: + "@type": type.googleapis.com/envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigningPerRoute + aws_request_signing: + service_name: s3 + region: us-west-1 + use_unsigned_payload: true + host_rewrite: new-host + match_excluded_headers: + - prefix: x-envoy + - prefix: x-forwarded + - exact: x-amzn-trace-id + stat_prefix: some-prefix + http_filters: + - name: envoy.filters.http.aws_request_signing + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning + service_name: s3 + region: us-west-2 + use_unsigned_payload: true + host_rewrite: default-host + match_excluded_headers: + - prefix: x-envoy + - prefix: x-forwarded + - exact: x-amzn-trace-id + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + + clusters: + - name: versioned-cluster + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: versioned-cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8080 diff --git a/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter.yaml b/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter.yaml new file mode 100644 index 000000000000..16dde43446f0 --- /dev/null +++ b/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter.yaml @@ -0,0 +1,52 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 80 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: app + domains: + - "*" + routes: + - match: + prefix: "/" + route: + cluster: versioned-cluster + http_filters: + - name: envoy.filters.http.aws_request_signing + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning + service_name: s3 + region: us-west-2 + use_unsigned_payload: true + match_excluded_headers: + - prefix: x-envoy + - prefix: x-forwarded + - exact: x-amzn-trace-id + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + + clusters: + - name: versioned-cluster + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: versioned-cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8080 diff --git a/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst b/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst index 2f33a1e4f6ef..886baee1d27a 100644 --- a/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst +++ b/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst @@ -34,19 +34,23 @@ Example configuration Example filter configuration: -.. code-block:: yaml - - name: envoy.filters.http.aws_request_signing - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning - service_name: s3 - region: us-west-2 - use_unsigned_payload: true - match_excluded_headers: - - prefix: x-envoy - - prefix: x-forwarded - - exact: x-amzn-trace-id - +.. literalinclude:: _include/aws-request-signing-filter.yaml + :language: yaml + :lines: 25-35 + :lineno-start: 25 + :linenos: + :caption: :download:`aws-request-signing-filter.yaml <_include/aws-request-signing-filter.yaml>` + +Note that this filter also supports per route configuration: + +.. literalinclude:: _include/aws-request-signing-filter-route-level-override.yaml + :language: yaml + :lines: 20-37 + :lineno-start: 20 + :linenos: + :caption: :download:`aws-request-signing-filter-route-level-override.yaml <_include/aws-request-signing-filter-route-level-override.yaml>` + +Above shows an example of route-level config overriding the config on the virtual-host level. .. include:: _include/aws_credentials.rst diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index c1e704971d5a..c0113843a8dd 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -208,6 +208,7 @@ envoy.filters.http.aws_request_signing: status: alpha type_urls: - envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning + - envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigningPerRoute envoy.filters.http.bandwidth_limit: categories: - envoy.filters.http diff --git a/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.cc b/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.cc index 94b1c6add1a6..beefccd8c800 100644 --- a/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.cc +++ b/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.cc @@ -4,6 +4,7 @@ #include "source/common/common/hex.h" #include "source/common/crypto/utility.h" +#include "source/common/http/utility.h" namespace Envoy { namespace Extensions { @@ -31,8 +32,10 @@ FilterStats Filter::generateStats(const std::string& prefix, Stats::Scope& scope } Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, bool end_stream) { - const auto& host_rewrite = config_->hostRewrite(); - const bool use_unsigned_payload = config_->useUnsignedPayload(); + auto& config = getConfig(); + + const auto& host_rewrite = config.hostRewrite(); + const bool use_unsigned_payload = config.useUnsignedPayload(); if (!host_rewrite.empty()) { headers.setHost(host_rewrite); @@ -47,22 +50,24 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, ENVOY_LOG(debug, "aws request signing from decodeHeaders use_unsigned_payload: {}", use_unsigned_payload); if (use_unsigned_payload) { - config_->signer().signUnsignedPayload(headers); + config.signer().signUnsignedPayload(headers); } else { - config_->signer().signEmptyPayload(headers); + config.signer().signEmptyPayload(headers); } - config_->stats().signing_added_.inc(); + config.stats().signing_added_.inc(); } catch (const EnvoyException& e) { // TODO: sign should not throw to avoid exceptions in the request path ENVOY_LOG(debug, "signing failed: {}", e.what()); - config_->stats().signing_failed_.inc(); + config.stats().signing_failed_.inc(); } return Http::FilterHeadersStatus::Continue; } Http::FilterDataStatus Filter::decodeData(Buffer::Instance& data, bool end_stream) { - if (config_->useUnsignedPayload()) { + auto& config = getConfig(); + + if (config.useUnsignedPayload()) { return Http::FilterDataStatus::Continue; } @@ -80,19 +85,28 @@ Http::FilterDataStatus Filter::decodeData(Buffer::Instance& data, bool end_strea try { ENVOY_LOG(debug, "aws request signing from decodeData"); ASSERT(request_headers_ != nullptr); - config_->signer().sign(*request_headers_, hash); - config_->stats().signing_added_.inc(); - config_->stats().payload_signing_added_.inc(); + config.signer().sign(*request_headers_, hash); + config.stats().signing_added_.inc(); + config.stats().payload_signing_added_.inc(); } catch (const EnvoyException& e) { // TODO: sign should not throw to avoid exceptions in the request path ENVOY_LOG(debug, "signing failed: {}", e.what()); - config_->stats().signing_failed_.inc(); - config_->stats().payload_signing_failed_.inc(); + config.stats().signing_failed_.inc(); + config.stats().payload_signing_failed_.inc(); } return Http::FilterDataStatus::Continue; } +FilterConfig& Filter::getConfig() const { + auto* config = const_cast( + Http::Utility::resolveMostSpecificPerFilterConfig(decoder_callbacks_)); + if (config) { + return *config; + } + return *config_; +} + } // namespace AwsRequestSigningFilter } // namespace HttpFilters } // namespace Extensions diff --git a/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h b/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h index 2ae73277d995..c0a70106b619 100644 --- a/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h +++ b/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h @@ -34,9 +34,9 @@ struct FilterStats { /** * Abstract filter configuration. */ -class FilterConfig { +class FilterConfig : public Router::RouteSpecificFilterConfig { public: - virtual ~FilterConfig() = default; + ~FilterConfig() override = default; /** * @return the config's signer. @@ -95,6 +95,8 @@ class Filter : public Http::PassThroughDecoderFilter, Logger::Loggable config_; Http::RequestHeaderMap* request_headers_{}; }; diff --git a/source/extensions/filters/http/aws_request_signing/config.cc b/source/extensions/filters/http/aws_request_signing/config.cc index 6743c9473c8b..c277f8e600c6 100644 --- a/source/extensions/filters/http/aws_request_signing/config.cc +++ b/source/extensions/filters/http/aws_request_signing/config.cc @@ -15,8 +15,8 @@ namespace HttpFilters { namespace AwsRequestSigningFilter { Http::FilterFactoryCb AwsRequestSigningFilterFactory::createFilterFactoryFromProtoTyped( - const envoy::extensions::filters::http::aws_request_signing::v3::AwsRequestSigning& config, - const std::string& stats_prefix, Server::Configuration::FactoryContext& context) { + const AwsRequestSigningProtoConfig& config, const std::string& stats_prefix, + Server::Configuration::FactoryContext& context) { auto credentials_provider = std::make_shared( @@ -35,6 +35,26 @@ Http::FilterFactoryCb AwsRequestSigningFilterFactory::createFilterFactoryFromPro }; } +Router::RouteSpecificFilterConfigConstSharedPtr +AwsRequestSigningFilterFactory::createRouteSpecificFilterConfigTyped( + const AwsRequestSigningProtoPerRouteConfig& per_route_config, + Server::Configuration::ServerFactoryContext& context, ProtobufMessage::ValidationVisitor&) { + auto credentials_provider = + std::make_shared( + context.api(), Extensions::Common::Aws::Utility::fetchMetadata); + const auto matcher_config = Extensions::Common::Aws::AwsSigV4HeaderExclusionVector( + per_route_config.aws_request_signing().match_excluded_headers().begin(), + per_route_config.aws_request_signing().match_excluded_headers().end()); + auto signer = std::make_unique( + per_route_config.aws_request_signing().service_name(), + per_route_config.aws_request_signing().region(), credentials_provider, + context.mainThreadDispatcher().timeSource(), matcher_config); + return std::make_shared( + std::move(signer), per_route_config.stat_prefix(), context.scope(), + per_route_config.aws_request_signing().host_rewrite(), + per_route_config.aws_request_signing().use_unsigned_payload()); +} + /** * Static registration for the AWS request signing filter. @see RegisterFactory. */ diff --git a/source/extensions/filters/http/aws_request_signing/config.h b/source/extensions/filters/http/aws_request_signing/config.h index 55214c6afdbb..e066323ee9e5 100644 --- a/source/extensions/filters/http/aws_request_signing/config.h +++ b/source/extensions/filters/http/aws_request_signing/config.h @@ -10,20 +10,31 @@ namespace Extensions { namespace HttpFilters { namespace AwsRequestSigningFilter { +using AwsRequestSigningProtoConfig = + envoy::extensions::filters::http::aws_request_signing::v3::AwsRequestSigning; + +using AwsRequestSigningProtoPerRouteConfig = + envoy::extensions::filters::http::aws_request_signing::v3::AwsRequestSigningPerRoute; + /** * Config registration for the AWS request signing filter. */ class AwsRequestSigningFilterFactory - : public Common::FactoryBase< - envoy::extensions::filters::http::aws_request_signing::v3::AwsRequestSigning> { + : public Common::FactoryBase { public: AwsRequestSigningFilterFactory() : FactoryBase("envoy.filters.http.aws_request_signing") {} private: - Http::FilterFactoryCb createFilterFactoryFromProtoTyped( - const envoy::extensions::filters::http::aws_request_signing::v3::AwsRequestSigning& - proto_config, - const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override; + Http::FilterFactoryCb + createFilterFactoryFromProtoTyped(const AwsRequestSigningProtoConfig& proto_config, + const std::string& stats_prefix, + Server::Configuration::FactoryContext& context) override; + + Router::RouteSpecificFilterConfigConstSharedPtr + createRouteSpecificFilterConfigTyped(const AwsRequestSigningProtoPerRouteConfig& per_route_config, + Server::Configuration::ServerFactoryContext& context, + ProtobufMessage::ValidationVisitor&) override; }; } // namespace AwsRequestSigningFilter diff --git a/test/extensions/filters/http/aws_request_signing/aws_request_signing_filter_test.cc b/test/extensions/filters/http/aws_request_signing/aws_request_signing_filter_test.cc index 27aa33350919..e6b6fcbc5bad 100644 --- a/test/extensions/filters/http/aws_request_signing/aws_request_signing_filter_test.cc +++ b/test/extensions/filters/http/aws_request_signing/aws_request_signing_filter_test.cc @@ -198,6 +198,25 @@ TEST_F(AwsRequestSigningFilterTest, FilterConfigImplGetters) { EXPECT_EQ(true, config.useUnsignedPayload()); } +// Verify filter functionality when a host rewrite happens on route-level config. +TEST_F(AwsRequestSigningFilterTest, PerRouteConfigSignWithHostRewrite) { + setup(); + filter_config_->host_rewrite_ = "original-host"; + + Stats::IsolatedStoreImpl stats; + auto signer = std::make_unique(); + EXPECT_CALL(*(signer), signEmptyPayload(An(), An())); + + FilterConfigImpl per_route_config(std::move(signer), "prefix", *stats.rootScope(), + "overridden-host", false); + ON_CALL(*decoder_callbacks_.route_, mostSpecificPerFilterConfig(_)) + .WillByDefault(Return(&per_route_config)); + + Http::TestRequestHeaderMapImpl headers; + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(headers, true)); + EXPECT_EQ("overridden-host", headers.getHostValue()); +} + } // namespace } // namespace AwsRequestSigningFilter } // namespace HttpFilters diff --git a/test/extensions/filters/http/aws_request_signing/config_test.cc b/test/extensions/filters/http/aws_request_signing/config_test.cc index 27c9577a4b49..95e8773f5f96 100644 --- a/test/extensions/filters/http/aws_request_signing/config_test.cc +++ b/test/extensions/filters/http/aws_request_signing/config_test.cc @@ -1,6 +1,7 @@ #include "envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.pb.h" #include "envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.pb.validate.h" +#include "source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h" #include "source/extensions/filters/http/aws_request_signing/config.h" #include "test/mocks/server/factory_context.h" @@ -14,13 +15,11 @@ namespace Extensions { namespace HttpFilters { namespace AwsRequestSigningFilter { -using AwsRequestSigningProtoConfig = - envoy::extensions::filters::http::aws_request_signing::v3::AwsRequestSigning; - TEST(AwsRequestSigningFilterConfigTest, SimpleConfig) { const std::string yaml = R"EOF( service_name: s3 region: us-west-2 +host_rewrite: new-host match_excluded_headers: - prefix: x-envoy - exact: foo @@ -33,6 +32,7 @@ region: us-west-2 AwsRequestSigningProtoConfig expected_config; expected_config.set_service_name("s3"); expected_config.set_region("us-west-2"); + expected_config.set_host_rewrite("new-host"); expected_config.add_match_excluded_headers()->set_prefix("x-envoy"); expected_config.add_match_excluded_headers()->set_exact("foo"); expected_config.add_match_excluded_headers()->set_exact("bar"); @@ -51,6 +51,30 @@ region: us-west-2 cb(filter_callbacks); } +TEST(AwsRequestSigningFilterConfigTest, RouteSpecificFilterConfig) { + const std::string yaml = R"EOF( +aws_request_signing: + service_name: s3 + region: us-west-2 + host_rewrite: new-host + match_excluded_headers: + - prefix: x-envoy + - exact: foo + - exact: bar +stat_prefix: foo_prefix + )EOF"; + + AwsRequestSigningProtoPerRouteConfig proto_config; + TestUtility::loadFromYamlAndValidate(yaml, proto_config); + + testing::NiceMock context; + AwsRequestSigningFilterFactory factory; + + const auto route_config = factory.createRouteSpecificFilterConfig( + proto_config, context, ProtobufMessage::getNullValidationVisitor()); + ASSERT_NE(route_config, nullptr); +} + } // namespace AwsRequestSigningFilter } // namespace HttpFilters } // namespace Extensions From ef090cf51bb71ed1df45f231e332e736184cac1f Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 24 May 2023 02:32:09 -0400 Subject: [PATCH 064/228] Revert "mobile: removing unused test filters (#27550)" (#27588) This reverts commit c99607b614ba9dcb73204c06b190bc2d43389a1d. --- mobile/envoy_build_config/BUILD | 2 + mobile/envoy_build_config/test_extensions.cc | 4 ++ .../filters/http/test_accessor/BUILD | 44 ++++++++++++++ .../filters/http/test_accessor/config.cc | 28 +++++++++ .../filters/http/test_accessor/config.h | 36 ++++++++++++ .../filters/http/test_accessor/filter.cc | 31 ++++++++++ .../filters/http/test_accessor/filter.h | 46 +++++++++++++++ .../filters/http/test_accessor/filter.proto | 10 ++++ .../extensions/filters/http/test_read/BUILD | 42 ++++++++++++++ .../filters/http/test_read/config.cc | 24 ++++++++ .../filters/http/test_read/config.h | 33 +++++++++++ .../filters/http/test_read/filter.cc | 57 +++++++++++++++++++ .../filters/http/test_read/filter.h | 35 ++++++++++++ .../filters/http/test_read/filter.proto | 6 ++ 14 files changed, 398 insertions(+) create mode 100644 mobile/library/common/extensions/filters/http/test_accessor/BUILD create mode 100644 mobile/library/common/extensions/filters/http/test_accessor/config.cc create mode 100644 mobile/library/common/extensions/filters/http/test_accessor/config.h create mode 100644 mobile/library/common/extensions/filters/http/test_accessor/filter.cc create mode 100644 mobile/library/common/extensions/filters/http/test_accessor/filter.h create mode 100644 mobile/library/common/extensions/filters/http/test_accessor/filter.proto create mode 100644 mobile/library/common/extensions/filters/http/test_read/BUILD create mode 100644 mobile/library/common/extensions/filters/http/test_read/config.cc create mode 100644 mobile/library/common/extensions/filters/http/test_read/config.h create mode 100644 mobile/library/common/extensions/filters/http/test_read/filter.cc create mode 100644 mobile/library/common/extensions/filters/http/test_read/filter.h create mode 100644 mobile/library/common/extensions/filters/http/test_read/filter.proto diff --git a/mobile/envoy_build_config/BUILD b/mobile/envoy_build_config/BUILD index 5f520f25a89f..3b3c27bddcf1 100644 --- a/mobile/envoy_build_config/BUILD +++ b/mobile/envoy_build_config/BUILD @@ -117,9 +117,11 @@ envoy_cc_library( "@envoy//source/extensions/filters/http/buffer:config", "@envoy_mobile//library/common/extensions/filters/http/assertion:config", "@envoy_mobile//library/common/extensions/filters/http/route_cache_reset:config", + "@envoy_mobile//library/common/extensions/filters/http/test_accessor:config", "@envoy_mobile//library/common/extensions/filters/http/test_event_tracker:config", "@envoy_mobile//library/common/extensions/filters/http/test_kv_store:config", "@envoy_mobile//library/common/extensions/filters/http/test_logger:config", + "@envoy_mobile//library/common/extensions/filters/http/test_read:config", "@envoy_mobile//library/common/extensions/filters/http/test_remote_response:config", ], alwayslink = 1, diff --git a/mobile/envoy_build_config/test_extensions.cc b/mobile/envoy_build_config/test_extensions.cc index f97634722058..d0bb9c56087b 100644 --- a/mobile/envoy_build_config/test_extensions.cc +++ b/mobile/envoy_build_config/test_extensions.cc @@ -4,16 +4,20 @@ #include "external/envoy_build_config/test_extensions.h" #include "library/common/extensions/filters/http/assertion/config.h" #include "library/common/extensions/filters/http/route_cache_reset/config.h" +#include "library/common/extensions/filters/http/test_accessor/config.h" #include "library/common/extensions/filters/http/test_event_tracker/config.h" #include "library/common/extensions/filters/http/test_kv_store/config.h" #include "library/common/extensions/filters/http/test_logger/config.h" +#include "library/common/extensions/filters/http/test_read/config.h" void register_test_extensions() { Envoy::Extensions::HttpFilters::Assertion::forceRegisterAssertionFilterFactory(); Envoy::Extensions::HttpFilters::BufferFilter::forceRegisterBufferFilterFactory(); Envoy::Extensions::HttpFilters::RouteCacheReset::forceRegisterRouteCacheResetFilterFactory(); + Envoy::Extensions::HttpFilters::TestAccessor::forceRegisterTestAccessorFilterFactory(); Envoy::Extensions::HttpFilters::TestEventTracker::forceRegisterTestEventTrackerFilterFactory(); Envoy::Extensions::HttpFilters::TestKeyValueStore::forceRegisterTestKeyValueStoreFilterFactory(); Envoy::Extensions::HttpFilters::TestLogger::forceRegisterFactory(); + Envoy::HttpFilters::TestRead::forceRegisterTestReadFilterFactory(); Envoy::Upstream::forceRegisterStaticClusterFactory(); } diff --git a/mobile/library/common/extensions/filters/http/test_accessor/BUILD b/mobile/library/common/extensions/filters/http/test_accessor/BUILD new file mode 100644 index 000000000000..977df4ab6783 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_accessor/BUILD @@ -0,0 +1,44 @@ +load( + "@envoy//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_extension_package", + "envoy_proto_library", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_proto_library( + name = "filter", + srcs = ["filter.proto"], + deps = [ + "@envoy_api//envoy/config/common/matcher/v3:pkg", + ], +) + +envoy_cc_extension( + name = "test_accessor_filter_lib", + srcs = ["filter.cc"], + hdrs = ["filter.h"], + repository = "@envoy", + deps = [ + "filter_cc_proto", + "//library/common/api:c_types", + "//library/common/api:external_api_lib", + "//library/common/data:utility_lib", + "@envoy//source/common/common:assert_lib", + "@envoy//source/extensions/filters/http/common:pass_through_filter_lib", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + repository = "@envoy", + deps = [ + ":test_accessor_filter_lib", + "@envoy//source/extensions/filters/http/common:factory_base_lib", + ], +) diff --git a/mobile/library/common/extensions/filters/http/test_accessor/config.cc b/mobile/library/common/extensions/filters/http/test_accessor/config.cc new file mode 100644 index 000000000000..44deda4b9561 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_accessor/config.cc @@ -0,0 +1,28 @@ +#include "library/common/extensions/filters/http/test_accessor/config.h" + +#include "library/common/extensions/filters/http/test_accessor/filter.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace TestAccessor { + +Http::FilterFactoryCb TestAccessorFilterFactory::createFilterFactoryFromProtoTyped( + const envoymobile::extensions::filters::http::test_accessor::TestAccessor& proto_config, + const std::string&, Server::Configuration::FactoryContext&) { + + auto config = std::make_shared(proto_config); + return [config](Http::FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamFilter(std::make_shared(config)); + }; +} + +/** + * Static registration for the TestAccessor filter. @see NamedHttpFilterConfigFactory. + */ +REGISTER_FACTORY(TestAccessorFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory); + +} // namespace TestAccessor +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/config.h b/mobile/library/common/extensions/filters/http/test_accessor/config.h new file mode 100644 index 000000000000..44bd26007b76 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_accessor/config.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include "source/extensions/filters/http/common/factory_base.h" + +#include "library/common/extensions/filters/http/test_accessor/filter.h" +#include "library/common/extensions/filters/http/test_accessor/filter.pb.h" +#include "library/common/extensions/filters/http/test_accessor/filter.pb.validate.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace TestAccessor { + +/** + * Config registration for the TestAccessor filter. @see NamedHttpFilterConfigFactory. + */ +class TestAccessorFilterFactory + : public Common::FactoryBase< + envoymobile::extensions::filters::http::test_accessor::TestAccessor> { +public: + TestAccessorFilterFactory() : FactoryBase("test_accessor") {} + +private: + ::Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped( + const envoymobile::extensions::filters::http::test_accessor::TestAccessor& config, + const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override; +}; + +DECLARE_FACTORY(TestAccessorFilterFactory); + +} // namespace TestAccessor +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.cc b/mobile/library/common/extensions/filters/http/test_accessor/filter.cc new file mode 100644 index 000000000000..e35f152dd004 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_accessor/filter.cc @@ -0,0 +1,31 @@ +#include "library/common/extensions/filters/http/test_accessor/filter.h" + +#include "envoy/server/filter_config.h" + +#include "source/common/common/assert.h" + +#include "library/common/data/utility.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace TestAccessor { + +TestAccessorFilterConfig::TestAccessorFilterConfig( + const envoymobile::extensions::filters::http::test_accessor::TestAccessor& proto_config) + : accessor_(static_cast( + Api::External::retrieveApi(proto_config.accessor_name()))), + expected_string_(proto_config.expected_string()) {} + +Http::FilterHeadersStatus TestAccessorFilter::decodeHeaders(Http::RequestHeaderMap&, bool) { + RELEASE_ASSERT(config_->expectedString() == + Data::Utility::copyToString( + config_->accessor()->get_string(config_->accessor()->context)), + "accessed string is not equal to expected string"); + return Http::FilterHeadersStatus::Continue; +} + +} // namespace TestAccessor +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.h b/mobile/library/common/extensions/filters/http/test_accessor/filter.h new file mode 100644 index 000000000000..d5a7355c19e3 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_accessor/filter.h @@ -0,0 +1,46 @@ +#pragma once + +#include "envoy/http/filter.h" + +#include "source/extensions/filters/http/common/pass_through_filter.h" + +#include "library/common/api/c_types.h" +#include "library/common/api/external.h" +#include "library/common/extensions/filters/http/test_accessor/filter.pb.h" + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace TestAccessor { + +class TestAccessorFilterConfig { +public: + TestAccessorFilterConfig( + const envoymobile::extensions::filters::http::test_accessor::TestAccessor& proto_config); + + const envoy_string_accessor* accessor() const { return accessor_; } + const std::string& expectedString() const { return expected_string_; } + +private: + const envoy_string_accessor* accessor_; + const std::string expected_string_; +}; + +using TestAccessorFilterConfigSharedPtr = std::shared_ptr; + +class TestAccessorFilter final : public ::Envoy::Http::PassThroughFilter { +public: + TestAccessorFilter(TestAccessorFilterConfigSharedPtr config) : config_(config) {} + + // StreamDecoderFilter + ::Envoy::Http::FilterHeadersStatus decodeHeaders(::Envoy::Http::RequestHeaderMap& headers, + bool end_stream) override; + +private: + const TestAccessorFilterConfigSharedPtr config_; +}; + +} // namespace TestAccessor +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.proto b/mobile/library/common/extensions/filters/http/test_accessor/filter.proto new file mode 100644 index 000000000000..938da1b89d95 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_accessor/filter.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package envoymobile.extensions.filters.http.test_accessor; + +import "validate/validate.proto"; + +message TestAccessor { + string accessor_name = 1 [(validate.rules).string.min_len = 1]; + string expected_string = 2 [(validate.rules).string.min_len = 1]; +} diff --git a/mobile/library/common/extensions/filters/http/test_read/BUILD b/mobile/library/common/extensions/filters/http/test_read/BUILD new file mode 100644 index 000000000000..54324cca68ac --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_read/BUILD @@ -0,0 +1,42 @@ +load( + "@envoy//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_extension_package", + "envoy_proto_library", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_proto_library( + name = "filter", + srcs = ["filter.proto"], + deps = [ + "@envoy_api//envoy/config/common/matcher/v3:pkg", + ], +) + +envoy_cc_extension( + name = "test_read_filter_lib", + srcs = ["filter.cc"], + hdrs = ["filter.h"], + repository = "@envoy", + deps = [ + "filter_cc_proto", + "@envoy//source/common/http:utility_lib", + "@envoy//source/common/stream_info:stream_info_lib", + "@envoy//source/extensions/filters/http/common:pass_through_filter_lib", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + repository = "@envoy", + deps = [ + ":test_read_filter_lib", + "@envoy//source/extensions/filters/http/common:factory_base_lib", + ], +) diff --git a/mobile/library/common/extensions/filters/http/test_read/config.cc b/mobile/library/common/extensions/filters/http/test_read/config.cc new file mode 100644 index 000000000000..3c5ce3c402f8 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_read/config.cc @@ -0,0 +1,24 @@ +#include "library/common/extensions/filters/http/test_read/config.h" + +#include "library/common/extensions/filters/http/test_read/filter.h" + +namespace Envoy { +namespace HttpFilters { +namespace TestRead { + +Http::FilterFactoryCb TestReadFilterFactory::createFilterFactoryFromProtoTyped( + const envoymobile::test::integration::filters::http::test_read::TestRead& /*config*/, + const std::string&, Server::Configuration::FactoryContext& /*context*/) { + return [](Http::FilterChainFactoryCallbacks& callbacks) -> void { + callbacks.addStreamDecoderFilter(std::make_shared()); + }; +} + +/** + * Static registration for the TestRead filter. @see NamedHttpFilterConfigFactory. + */ +REGISTER_FACTORY(TestReadFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory); + +} // namespace TestRead +} // namespace HttpFilters +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/config.h b/mobile/library/common/extensions/filters/http/test_read/config.h new file mode 100644 index 000000000000..24e22d706cb1 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_read/config.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "source/extensions/filters/http/common/factory_base.h" + +#include "library/common/extensions/filters/http/test_read/filter.pb.h" +#include "library/common/extensions/filters/http/test_read/filter.pb.validate.h" + +namespace Envoy { +namespace HttpFilters { +namespace TestRead { + +/** + * Config registration for the TestRead filter. @see NamedHttpFilterConfigFactory. + */ +class TestReadFilterFactory + : public Envoy::Extensions::HttpFilters::Common::FactoryBase< + envoymobile::test::integration::filters::http::test_read::TestRead> { +public: + TestReadFilterFactory() : FactoryBase("test_read") {} + +private: + ::Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped( + const envoymobile::test::integration::filters::http::test_read::TestRead& config, + const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override; +}; + +DECLARE_FACTORY(TestReadFilterFactory); + +} // namespace TestRead +} // namespace HttpFilters +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.cc b/mobile/library/common/extensions/filters/http/test_read/filter.cc new file mode 100644 index 000000000000..fb7c42752727 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_read/filter.cc @@ -0,0 +1,57 @@ +#include "library/common/extensions/filters/http/test_read/filter.h" + +#include "envoy/server/filter_config.h" + +namespace Envoy { +namespace HttpFilters { +namespace TestRead { + +Http::FilterHeadersStatus TestReadFilter::decodeHeaders(Http::RequestHeaderMap& request_headers, + bool) { + // sample path is /failed?error=0x10000 + Http::Utility::QueryParams query_parameters = + Http::Utility::parseQueryString(request_headers.Path()->value().getStringView()); + auto error = query_parameters.find("error"); + uint64_t response_flag; + if (error != query_parameters.end() && absl::SimpleAtoi(error->second, &response_flag)) { + // set response error code + StreamInfo::StreamInfo& stream_info = decoder_callbacks_->streamInfo(); + stream_info.setResponseFlag(TestReadFilter::mapErrorToResponseFlag(response_flag)); + + // check if we want a quic server error: sample path is /failed?quic=1&error=0x10000 + if (query_parameters.find("quic") != query_parameters.end()) { + stream_info.setUpstreamInfo(std::make_shared()); + stream_info.upstreamInfo()->setUpstreamProtocol(Http::Protocol::Http3); + } + + // trigger the error and stop iteration to other filters + decoder_callbacks_->sendLocalReply(Http::Code::BadRequest, "test_read filter threw: ", nullptr, + absl::nullopt, ""); + return Http::FilterHeadersStatus::StopIteration; + } + + // continue to other filters since the provided query string is invalid for error simulation + return Http::FilterHeadersStatus::Continue; +} + +StreamInfo::ResponseFlag TestReadFilter::mapErrorToResponseFlag(uint64_t errorCode) { + switch (errorCode) { + case 0x4000000: + return StreamInfo::DnsResolutionFailed; + case 0x40: + return StreamInfo::UpstreamConnectionTermination; + case 0x20: + return StreamInfo::UpstreamConnectionFailure; + case 0x10: + return StreamInfo::UpstreamRemoteReset; + case 0x10000: + return StreamInfo::StreamIdleTimeout; + default: + // Any other error that we aren't interested in. I picked a random error. + return StreamInfo::RateLimitServiceError; + } +} + +} // namespace TestRead +} // namespace HttpFilters +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.h b/mobile/library/common/extensions/filters/http/test_read/filter.h new file mode 100644 index 000000000000..dc5c2e73cea2 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_read/filter.h @@ -0,0 +1,35 @@ +#pragma once + +#include "envoy/http/filter.h" + +#include "source/common/common/logger.h" +#include "source/common/http/utility.h" +#include "source/common/stream_info/stream_info_impl.h" +#include "source/extensions/filters/http/common/pass_through_filter.h" + +#include "library/common/extensions/filters/http/test_read/filter.pb.h" + +namespace Envoy { +namespace HttpFilters { +namespace TestRead { + +/** + * This is a test-only filter to return specified error code based on a request url query string. + * It either simulates the requested error if the url query matches the error patterns + * or does nothing + */ +class TestReadFilter final : public Http::PassThroughFilter, + public Logger::Loggable { +public: + Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& request_headers, bool) override; + +private: + /* A mapping of the envoymobile errors we care about for testing + * From https://github.com/envoyproxy/envoy/blob/main/envoy/stream_info/stream_info.h + */ + StreamInfo::ResponseFlag mapErrorToResponseFlag(uint64_t errorCode); +}; + +} // namespace TestRead +} // namespace HttpFilters +} // namespace Envoy diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.proto b/mobile/library/common/extensions/filters/http/test_read/filter.proto new file mode 100644 index 000000000000..de164df7d450 --- /dev/null +++ b/mobile/library/common/extensions/filters/http/test_read/filter.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +package envoymobile.test.integration.filters.http.test_read; + +message TestRead { +} From 2123fa90e709229b56a7edecc2bcf875870bbcc6 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 24 May 2023 08:27:59 +0100 Subject: [PATCH 065/228] mobile/ci: Fix workflow dependencies (#27592) Signed-off-by: Ryan Northey --- .github/workflows/mobile-ios_build.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/mobile-ios_build.yml b/.github/workflows/mobile-ios_build.yml index a1d117ff13cd..8f946ac1484f 100644 --- a/.github/workflows/mobile-ios_build.yml +++ b/.github/workflows/mobile-ios_build.yml @@ -38,7 +38,9 @@ jobs: swifthelloworld: if: ${{ needs.env.outputs.mobile_ios_build == 'true' }} name: swift_helloworld - needs: iosbuild + needs: + - env + - iosbuild runs-on: macos-12 timeout-minutes: 50 steps: @@ -115,9 +117,10 @@ jobs: name: 'Log app run' swiftexperimentalapp: if: ${{ needs.env.outputs.mobile_ios_build_all == 'true' }} - needs: env + needs: + - env + - iosbuild name: swift_experimental_app - needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: @@ -158,9 +161,10 @@ jobs: name: 'Log app run' swiftasyncawait: if: ${{ needs.env.outputs.mobile_ios_build_all == 'true' }} - needs: env + needs: + - env + - iosbuild name: swift_async_await - needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: @@ -214,9 +218,10 @@ jobs: name: 'Log app run' objchelloworld: if: ${{ needs.env.outputs.mobile_ios_build_all == 'true' }} - needs: env + needs: + - env + - iosbuild name: objc_helloworld - needs: iosbuild runs-on: macos-12 timeout-minutes: 50 steps: From dd290cd048a9f6d7851f3a43b4df8f9202a6e6f0 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 24 May 2023 08:57:29 +0100 Subject: [PATCH 066/228] ci: Improve release publishing (#27526) Signed-off-by: Ryan Northey --- .azure-pipelines/env.yml | 15 ++++-- .azure-pipelines/stage/publish.yml | 75 ++++++++++++++++++------------ ci/do_ci.sh | 46 +++++++++--------- distribution/BUILD | 48 +++++++++++++++++++ tools/base/requirements.in | 2 +- 5 files changed, 128 insertions(+), 58 deletions(-) diff --git a/.azure-pipelines/env.yml b/.azure-pipelines/env.yml index b90813001600..01a9a78d081f 100644 --- a/.azure-pipelines/env.yml +++ b/.azure-pipelines/env.yml @@ -122,6 +122,8 @@ jobs: - bash: | set -e VERSION_DEV="$(cat VERSION.txt | cut -d- -f2)" + VERSION_PATCH="$(cat VERSION.txt | cut -d- -f1 | rev | cut -d. -f1 | rev)" + echo "##vso[task.setvariable variable=versionPatch;isoutput=true]$VERSION_PATCH" if [[ $VERSION_DEV == "dev" ]]; then echo "##vso[task.setvariable variable=isDev;isoutput=true]true" else @@ -180,7 +182,7 @@ jobs: # TODO(phlax): move this to a script to ensure proper linting etc set -e - PUBLISH_GITHUB_RELEASE=false + PUBLISH_GITHUB_RELEASE=$(run.packaging) PUBLISH_DOCKERHUB=false PUBLISH_DOCS=false PUBLISH_DOCS_LATEST=false @@ -189,6 +191,7 @@ jobs: if [[ "$ISSTABLEBRANCH" == True && -n "$POSTSUBMIT" && "$NOSYNC" != true ]]; then # Build docs for publishing either latest or a release build PUBLISH_DOCS=true + # main if [[ "$ISMAIN" == True ]]; then # Update the Dockerhub README PUBLISH_DOCKERHUB=true @@ -196,9 +199,13 @@ jobs: # Postsubmit on `main` trigger rebuild of latest docs PUBLISH_DOCS_LATEST=true fi + # Not main, and not -dev elif [[ "$(state.isDev)" == false ]]; then - # A stable release, publish docs to the release and create a Github release - PUBLISH_GITHUB_RELEASE=true + if [[ "$(state.versionPatch)" -eq 0 ]]; then + # A just-forked branch + PUBLISH_GITHUB_RELEASE=false + fi + # A stable release, publish docs to the release PUBLISH_DOCS_RELEASE=true else # Postsubmit for non-main/release, skip publishing docs in this case @@ -226,9 +233,11 @@ jobs: echo "env.outputs['changed.requirements']: $(changed.requirements)" echo echo "env.outputs['state.isDev']: $(state.isDev)" + echo "env.outputs['state.versionPatch']: $(state.versionPatch)" echo echo "env.outputs['run.build']: $(run.build)" echo "env.outputs['run.checks']: $(run.checks)" + echo "env.outputs['run.packaging']: $(run.packaging)" echo echo "env.outputs['publish.githubRelease']: $(publish.githubRelease)" echo "env.outputs['publish.dockerhub]: $(publish.dockerhub)" diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml index bd74cb6424c7..248b7400b7ea 100644 --- a/.azure-pipelines/stage/publish.yml +++ b/.azure-pipelines/stage/publish.yml @@ -301,8 +301,43 @@ jobs: displayName: "Publish release docs" workingDirectory: $(Build.SourcesDirectory) +- job: signed_release + displayName: Signed binaries + dependsOn: + - package_x64 + - package_arm64 + condition: | + and(succeeded(), + eq(${{ parameters.runPackaging }}, 'true')) + timeoutInMinutes: 120 + pool: + vmImage: "ubuntu-20.04" + steps: + - task: DownloadBuildArtifacts@0 + inputs: + buildType: current + artifactName: "bazel.release" + itemPattern: "bazel.release/**/bin/*" + targetPath: $(Build.StagingDirectory) + - task: DownloadBuildArtifacts@0 + inputs: + buildType: current + artifactName: "bazel.distribution" + itemPattern: "bazel.distribution/**/packages.*.tar.gz" + targetPath: $(Build.StagingDirectory) + - template: ../bazel.yml + parameters: + ciTarget: release.signed + stepsPre: + - template: ../gpg.yml + parameters: + authGPGPassphrase: ${{ parameters.authGPGPassphrase }} + authGPGPath: ${{ parameters.authGPGPath }} + authGPGKey: ${{ parameters.authGPGKey }} + pathGPGConfiguredHome: /build/.gnupg + pathGPGHome: $(Build.StagingDirectory)/.gnupg - job: success - dependsOn: ["docker", "package_x64", "package_arm64", "docs"] + dependsOn: ["docker", "docs", "signed_release"] displayName: Success (linux artefacts) pool: vmImage: "ubuntu-20.04" @@ -313,9 +348,8 @@ jobs: condition: | and( in(dependencies.docker.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), - in(dependencies.package_x64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), - in(dependencies.package_arm64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), - in(dependencies.docs.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')) + in(dependencies.docs.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), + in(dependencies.signed_release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')) steps: - checkout: none - bash: | @@ -323,39 +357,22 @@ jobs: - job: github displayName: Publish release tag - dependsOn: ["docs"] + dependsOn: ["success"] condition: | and(not(canceled()), eq(${{ parameters.publishGithubRelease }}, 'true')) pool: vmImage: "ubuntu-20.04" steps: - - - task: DownloadBuildArtifacts@0 - inputs: - buildType: current - artifactName: "bazel.release" - itemPattern: "bazel.release/bin/*" - targetPath: $(Build.StagingDirectory) - task: DownloadBuildArtifacts@0 inputs: buildType: current - artifactName: "bazel.release.arm64" - itemPattern: "bazel.release.arm64/bin/*" + artifactName: "release.signed" + itemPattern: "release.signed/release.signed.tar.zst" targetPath: $(Build.StagingDirectory) - - template: ../gpg.yml + - template: ../bazel.yml parameters: - authGPGPassphrase: ${{ parameters.authGPGPassphrase }} - authGPGPath: ${{ parameters.authGPGPath }} - authGPGKey: ${{ parameters.authGPGKey }} - pathGPGConfiguredHome: /build/.gnupg - pathGPGHome: $(Build.StagingDirectory)/.gnupg - - script: ./ci/run_envoy_docker.sh './ci/do_ci.sh publish' - displayName: "Publish release to Github" - workingDirectory: $(Build.SourcesDirectory) - env: - AZP_BRANCH: $(Build.SourceBranch) - GITHUB_TOKEN: ${{ parameters.authGithub }} - - bash: | - set -e - rm -rf $(Build.StagingDirectory)/.gnupg + ciTarget: publish + cacheVersion: $(cacheKeyBazel) + publishEnvoy: false + publishTestResults: false diff --git a/ci/do_ci.sh b/ci/do_ci.sh index f35425f4de53..4d516321753c 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -585,32 +585,18 @@ case $CI_TARGET in ;; publish) - # If we are on a non-main release branch but the patch version is 0 - then this branch - # has just been created, and the tag/release was cut from `main` - there is no need to - # create the tag/release from here - version="$(cat VERSION.txt)" - patch_version="$(echo "$version" | rev | cut -d. -f1)" - if [[ "$AZP_BRANCH" == "main" || "$AZP_BRANCH" == "refs/heads/main" ]]; then - if [[ "$patch_version" -eq 0 ]]; then - # It can take some time to get here in CI so the branch may have changed - create the release - # from the current commit (as this only happens on non-PRs we are safe from merges) - BUILD_SHA="$(git rev-parse HEAD)" - bazel run "${BAZEL_BUILD_OPTIONS[@]}" @envoy_repo//:publish -- --publish-commitish="$BUILD_SHA" - # TODO(phlax): move this to pytooling - mkdir -p linux/amd64 linux/arm64 publish - # linux/amd64 - tar xf /build/bazel.release/release.tar.zst -C ./linux/amd64 - cp -a linux/amd64/envoy "publish/envoy-${version}-linux-x86_64" - cp -a linux/amd64/envoy-contrib "publish/envoy-contrib-${version}-linux-x86_64" - # linux/arm64 - tar xf /build/bazel.release.arm64/release.tar.zst -C ./linux/arm64 - cp -a linux/arm64/envoy "publish/envoy-${version}-linux-aarch_64" - cp -a linux/arm64/envoy-contrib "publish/envoy-contrib-${version}-linux-aarch_64" - "${ENVOY_SRCDIR}/ci/publish_github_assets.sh" "v${version}" "${PWD}/publish" - exit 0 - fi + setup_clang_toolchain + BUILD_SHA="$(git rev-parse HEAD)" + VERSION_DEV="$(cut -d- -f2 < VERSION.txt)" + PUBLISH_ARGS=( + --publish-commitish="$BUILD_SHA" + --publish-assets=/build/release.signed/release.signed.tar.zst) + if [[ "$VERSION_DEV" == "dev" ]]; then + PUBLISH_ARGS+=(--dry-run) fi - echo "Not creating a tag/release for ${version} from ${AZP_BRANCH}" + bazel run "${BAZEL_BUILD_OPTIONS[@]}" \ + @envoy_repo//:publish \ + -- "${PUBLISH_ARGS[@]}" ;; release) @@ -666,6 +652,16 @@ case $CI_TARGET in bazel_envoy_binary_build release ;; + release.signed) + echo "Signing binary packages..." + setup_clang_toolchain + # The default config expects these files + mkdir -p distribution/custom + cp -a /build/bazel.*/*64 distribution/custom/ + bazel build "${BAZEL_BUILD_OPTIONS[@]}" //distribution:signed + cp -a bazel-bin/distribution/release.signed.tar.zst "${BUILD_DIR}/envoy/" + ;; + sizeopt) setup_clang_toolchain echo "Testing ${TEST_TARGETS[*]}" diff --git a/distribution/BUILD b/distribution/BUILD index ad70af90bfe8..611db69eaef7 100644 --- a/distribution/BUILD +++ b/distribution/BUILD @@ -10,6 +10,8 @@ MAINTAINER = "Envoy maintainers " exports_files(glob([ "custom/envoy*", + "custom/arm64/**/*", + "custom/x64/**/*", ])) # Configurable binary flags @@ -73,3 +75,49 @@ sh_binary( "//tools/distribution:verify", ], ) + +label_flag( + name = "x64-packages", + build_setting_default = "//distribution:custom/x64/packages.x64.tar.gz", +) + +label_flag( + name = "arm64-packages", + build_setting_default = "//distribution:custom/arm64/packages.arm64.tar.gz", +) + +label_flag( + name = "x64-release", + build_setting_default = "//distribution:custom/x64/bin/release.tar.zst", +) + +label_flag( + name = "arm64-release", + build_setting_default = "//distribution:custom/arm64/bin/release.tar.zst", +) + +genrule( + name = "signed", + outs = ["release.signed.tar.zst"], + cmd = """ + # Sign the packages + $(location //tools/distribution:sign) \ + "deb.x64:$(location :x64-packages)" \ + "deb.arm64:$(location :arm64-packages)" \ + "x64:$(location :x64-release)" \ + "arm64:$(location :arm64-release)" \ + -m x64/envoy:bin/envoy-x86_64 \ + -m x64/envoy-contrib:bin/envoy-contrib-x86_64 \ + -m arm64/envoy:bin/envoy-aarch_64 \ + -m arm64/envoy-contrib:bin/envoy-contrib-aarch_64 \ + --out $@ + """, + exec_tools = [ + ":arm64-packages", + ":x64-packages", + ":arm64-release", + ":x64-release", + "//tools/distribution:sign", + ], + tags = ["no-remote"], +) diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 68c563b40516..653124e4adcf 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -5,7 +5,7 @@ cffi>=1.15.0 colorama coloredlogs dependatool>=0.2.2 -envoy.base.utils>=0.4.7 +envoy.base.utils>=0.4.10 envoy.code.check>=0.5.0 envoy.dependency.check>=0.1.7 envoy.distribution.release>=0.0.9 From aa5ab8d093996d9c141c9f5f68abecbc79e7183a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 09:06:59 +0100 Subject: [PATCH 067/228] build(deps): bump envoy-base-utils from 0.4.10 to 0.4.11 in /tools/base (#27596) Bumps [envoy-base-utils](https://github.com/envoyproxy/toolshed) from 0.4.10 to 0.4.11. - [Release notes](https://github.com/envoyproxy/toolshed/releases) - [Commits](https://github.com/envoyproxy/toolshed/commits) --- updated-dependencies: - dependency-name: envoy-base-utils dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 8ad6e2ebff2d..05590e525ebc 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -25,9 +25,9 @@ aio-api-bazel==0.0.2 \ --hash=sha256:56e36463d236e477b7e282f2d870185a0b978b50e2c3803c1ebf8b8ac4b18f5b \ --hash=sha256:d3f563b7698e874437d80538a89dd4d79bc37de2e850c846330ae456e3f21dcc # via -r requirements.in -aio-api-github==0.2.2 \ - --hash=sha256:507971a3a90155066a072d24fc40b3890f69b2f671a42c6325370a48cbbd0e06 \ - --hash=sha256:5e67bb397362ad0ccfd6b6680c94a995fdc8fb8cd795b5074dd29c5f875a9d62 +aio-api-github==0.2.4 \ + --hash=sha256:ccbc7c6c61b25994e87474d78c48549e9fbc98c2cc04314b50b80ba1f40fd521 \ + --hash=sha256:eccfccd1503f50384de3f6526bd780ca02107cb440a666b2c1ab978d99c7db5e # via # envoy-base-utils # envoy-dependency-check @@ -420,9 +420,9 @@ docutils==0.19 \ # via # envoy-docs-sphinx-runner # sphinx -envoy-base-utils==0.4.10 \ - --hash=sha256:1cfccb54a3831c5b5a833efdad67752c1ae0a8708532712842726de42c0c413a \ - --hash=sha256:9567d1317a9ed7e97730a664e3105d8a6d46a4fa9e5cc7256951f5564783d8ae +envoy-base-utils==0.4.11 \ + --hash=sha256:5ced696c470b4c3090e6fc3f74e7e33f5fe217e775b1fc1fb56dfc756b781fbe \ + --hash=sha256:97c79177bb89360b7772e58fb20c671c67bf0b6cdee74c0b9f8a80433f0370cc # via # -r requirements.in # envoy-code-check From 52c6d78723ab53f3338bbf23554801d4019e3dc1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 09:07:36 +0100 Subject: [PATCH 068/228] build(deps): bump orjson from 3.8.12 to 3.8.13 in /tools/base (#27595) Bumps [orjson](https://github.com/ijl/orjson) from 3.8.12 to 3.8.13. - [Release notes](https://github.com/ijl/orjson/releases) - [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md) - [Commits](https://github.com/ijl/orjson/compare/3.8.12...3.8.13) --- updated-dependencies: - dependency-name: orjson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 94 ++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 05590e525ebc..33733690523d 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -926,53 +926,53 @@ oauth2client==4.1.3 \ # via # gcs-oauth2-boto-plugin # google-apitools -orjson==3.8.12 \ - --hash=sha256:062e67108c218fdb9475edd5272b1629c05b56c66416fa915de5656adde30e73 \ - --hash=sha256:06e528f9a84fbb4000fd0eee573b5db543ee70ae586fdbc53e740b0ac981701c \ - --hash=sha256:0ba645c92801417933fa74448622ba614a275ea82df05e888095c7742d913bb4 \ - --hash=sha256:135f29cf936283a0cd1b8bce86540ca181108f2a4d4483eedad6b8026865d2a9 \ - --hash=sha256:29706dd8189835bcf1781faed286e99ae54fd6165437d364dfdbf0276bf39b19 \ - --hash=sha256:2ad149ed76dce2bbdfbadd61c35959305e77141badf364a158beb4ef3d88ec37 \ - --hash=sha256:355055e0977c43b0e5325b9312b7208c696fe20cd54eed1d6fc80b0a4d6721f5 \ - --hash=sha256:397670665f94cf5cff779054781d80395084ba97191d82f7b3a86f0a20e6102b \ - --hash=sha256:3fa58ca064c640fa9d823f98fbbc8e71940ecb78cea3ac2507da1cbf49d60b51 \ - --hash=sha256:44f7bb4c995652106276442de1147c9993716d1e2d79b7fd435afa154ff236b9 \ - --hash=sha256:4fd240e736ce52cd757d74142d9933fd35a3184396be887c435f0574e0388654 \ - --hash=sha256:62f999798f2fa55e567d483864ebfc30120fb055c2696a255979439323a5b15c \ - --hash=sha256:6cae2ff288a80e81ce30313e735c5436495ab58cf8d4fbe84900e616d0ee7a78 \ - --hash=sha256:6d1acf52d3a4b9384af09a5c2658c3a7a472a4d62a0ad1fe2c8fab8ef460c9b4 \ - --hash=sha256:6f1b01f641f5e87168b819ac1cbd81aa6278e7572c326f3d27e92dea442a2c0d \ - --hash=sha256:6f568205519bb0197ca91915c5da6058cfbb59993e557b02dfc3b2718b34770a \ - --hash=sha256:710c40c214b753392e46f9275fd795e9630dd737a5ab4ac6e4ee1a02fe83cc0d \ - --hash=sha256:77710774faed337ac4ad919dadc5f3b655b0cd40518e5386e6f1f116de9c6c25 \ - --hash=sha256:7d50d9b1ae409ea15534365fec0ce8a5a5f7dc94aa790aacfb8cfec87ab51aa4 \ - --hash=sha256:7d63f524048825e05950db3b6998c756d5377a5e8c469b2e3bdb9f3217523d74 \ - --hash=sha256:7e405d54c84c30d9b1c918c290bcf4ef484a45c69d5583a95db81ffffba40b44 \ - --hash=sha256:7e549468867991f6f9cfbd9c5bbc977330173bd8f6ceb79973bbd4634e13e1b9 \ - --hash=sha256:82d65e478a21f98107b4eb8390104746bb3024c27084b57edab7d427385f1f70 \ - --hash=sha256:834b50df79f1fe89bbaced3a1c1d8c8c92cc99e84cdcd374d8da4974b3560d2a \ - --hash=sha256:83e8c740a718fa6d511a82e463adc7ab17631c6eea81a716b723e127a9c51d57 \ - --hash=sha256:8682f752c19f6a7d9fc727fd98588b4c8b0dce791b5794bb814c7379ccd64a79 \ - --hash=sha256:8d153b228b6e24f8bccf732a51e01e8e938eef59efed9030c5c257778fbe0804 \ - --hash=sha256:8f00038bf5d07439d13c0c2c5cd6ad48eb86df7dbd7a484013ce6a113c421b14 \ - --hash=sha256:96fb1eb82b578eb6c0e53e3cf950839fe98ea210626f87c8204bd4fc2cc6ba02 \ - --hash=sha256:9a6c1594d5a9ff56e5babc4a87ac372af38d37adef9e06744e9f158431e33f43 \ - --hash=sha256:9f0f042cf002a474a6aea006dd9f8d7a5497e35e5fb190ec78eb4d232ec19955 \ - --hash=sha256:a72b50719bdd6bb0acfca3d4d1c841aa4b191f3ff37268e7aba04e5d6be44ccd \ - --hash=sha256:aff761de5ed5543a0a51e9f703668624749aa2239de5d7d37d9c9693daeaf5dc \ - --hash=sha256:becbd5af6d035a7ec2ee3239d4700929d52d8517806b97dd04efcc37289403f7 \ - --hash=sha256:c6390ce0bce24c107fc275736aa8a4f768ef7eb5df935d7dca0cc99815eb5d99 \ - --hash=sha256:c84046e890e13a119404a83f2e09e622509ed4692846ff94c4ca03654fbc7fb5 \ - --hash=sha256:cd6fbd1413559572e81b5ac64c45388147c3ba85cc3df2eaa11002945e0dbd1f \ - --hash=sha256:d937503e4dfba5edc8d5e0426d3cc97ed55716e93212b2e12a198664487b9965 \ - --hash=sha256:dc27a8ec13f28e92dc1ea89bf1232d77e7d3ebfd5c1ccf4f3729a70561cb63bd \ - --hash=sha256:de3d096dde3e46d01841abc1982b906694ab3c92f338d37a2e6184739dc8a958 \ - --hash=sha256:eb16e0195febd24b44f4db1ab3be85ecf6038f92fd511370cebc004b3d422294 \ - --hash=sha256:ebb03e4c7648f7bb299872002a6120082da018f41ba7a9ebf4ceae8d765443d2 \ - --hash=sha256:ec4f0130d9a27cb400423e09e0f9e46480e9e977f05fdcf663a7a2c68735513e \ - --hash=sha256:efb3a10030462a22c731682434df5c137a67632a8339f821cd501920b169007e \ - --hash=sha256:f480ae7b84369b1860d8867f0baf8d885fede400fda390ce088bfa8edf97ffdc \ - --hash=sha256:f4e22b0aa70c963ac01fcd620de15be21a5027711b0e5d4b96debcdeea43e3ae +orjson==3.8.13 \ + --hash=sha256:0055168bc38c9caf7211e66e7c06d7f127d2c1dd1cd1d806c58f3a81d6074a6c \ + --hash=sha256:05bfef2719d68b44ab38061f9cd2b3a58d9994f7230734ba6d3c16db97c5e94a \ + --hash=sha256:0a3bc7e12f69f7bcefe522c4e4dac33a9b3b450aae0b3170ab61fbce0a6e1b37 \ + --hash=sha256:0ca2aced3fa6ce6d440a2a2e55bb7618fd24fce146068523472f349598e992ee \ + --hash=sha256:0d2e9a8ea45db847864868f7a566bece7d425c06627e5dbdd5fc8399a9c3330b \ + --hash=sha256:11a457fafdd207f361986750a5229fc36911fc9fdfc274d078fdf1654845ef45 \ + --hash=sha256:1234110f782af5e81893b5419b9374ca2559dbd976cbd515e6c3afc292cdfb6a \ + --hash=sha256:1316c60c0f55440e765b0211e94d171ab2c11d00fe8dcf0ac70c9bd1d9818e6b \ + --hash=sha256:14e54713703d5436a7be54ff50d780b6b09358f1a0be6107a3ea4f3537a4f6d8 \ + --hash=sha256:156bd6325a4f4a0c88556b7d774e3e18713c8134b6f807571a3eec14dfcafff6 \ + --hash=sha256:17788155c50f47d9fd037e12ac82a57381c157ea4de50e8946df8519da0f7f02 \ + --hash=sha256:246e22d167ede9ebf09685587187bde9e2440a515bd5eab2e97f029b9de57677 \ + --hash=sha256:24f923cf8d7e2e9a975f4507f93e93c262f26b4a1a4f72e4d6e75eda45de8f40 \ + --hash=sha256:2e362090bdd4261608eceefd8ed127cd2bfc48643601f9c0cf5d162ca6a7c4cd \ + --hash=sha256:305ffd227857cede7318c056020d1a3f3295e8adf8e7f2cbd78c26c530a0f234 \ + --hash=sha256:386e60a09585b2b5db84879ebad6d49427ae5a9677f86a90bff9cbbec42b03be \ + --hash=sha256:41585f90cfe24d0ae7d5bc96968617b8bcebb618e19db5b0bbadce6bc82f3455 \ + --hash=sha256:47cb98386a7ff79d0ace6a7c9d5c49ca2b4ea42e4339c565f5efe7757790dd04 \ + --hash=sha256:4b98fbca0ea0f5e56b3c1d050b78460ca9708419780ec218cef1eca424db2ee5 \ + --hash=sha256:50cfa3449157c4a4ad017a041dbb5fe37091800220fd5e651c0e5fff63bdac61 \ + --hash=sha256:5492a1d9eea5a1cb33ae6d225091c69dc79f16d952885625c00070388489d412 \ + --hash=sha256:59d79e5de4a1de246517b4c92dcf6a7ef1fb12e3ce4bbfc6c0f99d1d905405fd \ + --hash=sha256:59d81f5b9e280ac3ced615e726bfba722785cc5f7fc3aa1e0ea304c5a4114e94 \ + --hash=sha256:5e56ca7bd82b25f40955184df21c977369debe51c4b83fc3113b6427726312f3 \ + --hash=sha256:637d55ba6b48b698973d7e647b9de6bb2b424c445f51c86df4e976e672300b21 \ + --hash=sha256:6b323bb4af76c16636ac1fec403331208f978ae8a2c6bcab904ee1683c05ad7a \ + --hash=sha256:6dcccda35f11f12ebb36db0ebdca9854327530e1fffe02331cde78177851ae7f \ + --hash=sha256:6fe2981bd0f6959d821253604e9ba2c5ffa03c6202d11f0e3c190e5712b6835b \ + --hash=sha256:8075487b7b2e7cc2c44d8ee7950845b6854cd08a04df80b36055cc0236c28edd \ + --hash=sha256:8d2ce41c5992dbe9962ef75db1e70ed33636959f2f4b929f9d8cbb2e30472a08 \ + --hash=sha256:97d8444cf48f8fe2718fd3b99484906c29a909dc3a8177e8751170a9a28bcf33 \ + --hash=sha256:9b5b005841394e563f1ca3314a6884101a1b1f1dd30c569b4a0335e1ebf49fbf \ + --hash=sha256:a4a182e7a58114a81d52d67bdc034eb83571690158c4b8d3f1bf5c5f772f77b1 \ + --hash=sha256:b05ef096362c8a96fdcd85392c68156c9b680271aea350b490c2d0f3ef1b6b6a \ + --hash=sha256:b2325d8471867c99c432c96861d72d8b7336293860ebb17c9d70e1d377cc2b32 \ + --hash=sha256:bf934a036dafe63c3b1d630efaf996b85554e7ab03754019a18cc0fe2bdcc3a9 \ + --hash=sha256:c97be6a6ff4d546579f08f1d67aad92715313a06b214e3f2df9bb9f1b45765c2 \ + --hash=sha256:ce737ddf9d5f960996b63c12dbcc82ae2315c45f19165b2fe14a5b33ab8705bb \ + --hash=sha256:cf79f51a7ca59ac322a1e65430142ab1cb9c9a845e893e0e3958deaefe1c9873 \ + --hash=sha256:d30b8b9fe1ff56fb6ff64d2c2e227d49819b58ae8dac51089f393e31b39a4080 \ + --hash=sha256:e62f14f3eabccdd2108e3d5884fb66197255accc42b9ffa7f04d9dbf7336b479 \ + --hash=sha256:e792d286ad175d36f6b77b7ba77f1654a13f705a7ccfef7819e9b6d49277120d \ + --hash=sha256:ea6899624661d2258a71bde33266c3c08c8d9596865acf0ac19a9552c08fa1a6 \ + --hash=sha256:f084ce58b3fd496429deb3435aa7295ab57e349a33cdb99b3cb5f0a66a610a84 \ + --hash=sha256:f8aa77df01c60b7d8b0ff5501d6b8583a4acb06c4373c59bf769025ff8b8b4cb \ + --hash=sha256:fc42b2006abaa4fb72c9193931a9236dd85ce0483cc74079c315ce8529568ca1 # via # -r requirements.in # envoy-base-utils From 2bfacbdc2782375cd259444439c85a80c2bc458a Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 24 May 2023 11:52:57 +0100 Subject: [PATCH 069/228] ci: Fix latest docs publishing (#27608) Signed-off-by: Ryan Northey --- .azure-pipelines/bazel.yml | 5 +++++ .azure-pipelines/stage/publish.yml | 2 ++ 2 files changed, 7 insertions(+) diff --git a/.azure-pipelines/bazel.yml b/.azure-pipelines/bazel.yml index 79a43fa80107..7a3c701ac8ac 100644 --- a/.azure-pipelines/bazel.yml +++ b/.azure-pipelines/bazel.yml @@ -58,6 +58,9 @@ parameters: type: stepList default: [] +- name: env + type: object + default: {} steps: - checkout: self @@ -179,6 +182,8 @@ steps: BAZEL_REMOTE_INSTANCE_BRANCH: "$(System.PullRequest.TargetBranch)" ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: BAZEL_REMOTE_INSTANCE_BRANCH: "$(Build.SourceBranchName)" + ${{ each var in parameters.env }}: + ${{ var.key }}: ${{ var.value }} displayName: "Run CI script ${{ parameters.ciTarget }}" - bash: | diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml index 248b7400b7ea..d7c79e7cabf4 100644 --- a/.azure-pipelines/stage/publish.yml +++ b/.azure-pipelines/stage/publish.yml @@ -241,6 +241,8 @@ jobs: cacheVersion: $(cacheKeyBazel) publishEnvoy: false publishTestResults: false + env: + AZP_BRANCH: $(Build.SourceBranch) stepsPost: - script: | From 6e6f515295152a260afb5902c291aa965ee428ef Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 24 May 2023 13:53:07 +0100 Subject: [PATCH 070/228] Revert "test: moving ssl utility to use parsed protos (#27585)" (#27606) This reverts commit 9f1aa4330060331bd074be2ee20516252f909d1a. Signed-off-by: Ryan Northey --- test/integration/BUILD | 6 ++-- test/integration/ssl_utility.cc | 53 ++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/test/integration/BUILD b/test/integration/BUILD index cb6be550d383..fbcbfbfaf828 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -1101,14 +1101,12 @@ envoy_cc_test_library( name = "utility_lib", srcs = [ "server.cc", - "ssl_utility.cc", "utility.cc", - ], + ] + envoy_select_enable_yaml(["ssl_utility.cc"]), hdrs = [ "server.h", - "ssl_utility.h", "utility.h", - ], + ] + envoy_select_enable_yaml(["ssl_utility.h"]), data = ["//test/common/runtime:filesystem_test_data"], deps = [ ":server_stats_interface", diff --git a/test/integration/ssl_utility.cc b/test/integration/ssl_utility.cc index be1c9d8a2009..af93ec2c3a48 100644 --- a/test/integration/ssl_utility.cc +++ b/test/integration/ssl_utility.cc @@ -25,30 +25,47 @@ namespace Ssl { void initializeUpstreamTlsContextConfig( const ClientSslTransportOptions& options, envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext& tls_context) { - std::string rundir = TestEnvironment::runfilesDirectory(); - tls_context.mutable_common_tls_context() - ->mutable_validation_context() - ->mutable_trusted_ca() - ->set_filename(rundir + "/test/config/integration/certs/cacert.pem"); - auto* certs = tls_context.mutable_common_tls_context()->add_tls_certificates(); - std::string chain; - std::string key; + std::string yaml_plain = R"EOF( + common_tls_context: + validation_context: + trusted_ca: + filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" +)EOF"; if (options.client_ecdsa_cert_) { - chain = rundir + "/test/config/integration/certs/client_ecdsacert.pem"; - key = rundir + "/test/config/integration/certs/client_ecdsakey.pem"; + yaml_plain += R"EOF( + tls_certificates: + certificate_chain: + filename: "{{ test_rundir }}/test/config/integration/certs/client_ecdsacert.pem" + private_key: + filename: "{{ test_rundir }}/test/config/integration/certs/client_ecdsakey.pem" +)EOF"; } else if (options.use_expired_spiffe_cert_) { - chain = rundir + "/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem"; - key = rundir + "/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_key.pem"; + yaml_plain += R"EOF( + tls_certificates: + certificate_chain: + filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem" + private_key: + filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_key.pem" +)EOF"; } else if (options.client_with_intermediate_cert_) { - chain = rundir + "/test/config/integration/certs/client2_chain.pem"; - key = rundir + "/test/config/integration/certs/client2key.pem"; + yaml_plain += R"EOF( + tls_certificates: + certificate_chain: + filename: "{{ test_rundir }}/test/config/integration/certs/client2_chain.pem" + private_key: + filename: "{{ test_rundir }}/test/config/integration/certs/client2key.pem" +)EOF"; } else { - chain = rundir + "/test/config/integration/certs/clientcert.pem"; - key = rundir + "/test/config/integration/certs/clientkey.pem"; + yaml_plain += R"EOF( + tls_certificates: + certificate_chain: + filename: "{{ test_rundir }}/test/config/integration/certs/clientcert.pem" + private_key: + filename: "{{ test_rundir }}/test/config/integration/certs/clientkey.pem" +)EOF"; } - certs->mutable_certificate_chain()->set_filename(chain); - certs->mutable_private_key()->set_filename(key); + TestUtility::loadFromYaml(TestEnvironment::substitute(yaml_plain), tls_context); auto* common_context = tls_context.mutable_common_tls_context(); if (options.alpn_) { From 932e09c1d826f62a34eead67111a035d95ff243e Mon Sep 17 00:00:00 2001 From: botengyao Date: Wed, 24 May 2023 09:13:38 -0400 Subject: [PATCH 071/228] formatter: add two tests NaN and Infinity (#27589) #26464 removed JsonOrDie function but added ENVOY_BUG in the format call path. The pre-release version of Protobuf includes this change: Expect fail when serialize inf and nan for Value.number_value in json format. fixes #11259 protocolbuffers/protobuf@ca1cb1b If we bump the Protobuf version, there will be an exception & crash using NaN/inf/-inf in protobuf.struct number_value when performing the serialization, while there is no check for this behavior right now. Added 2 tests to catch this behavior change in the future. Signed-off-by: Boteng Yao --- .../formatter/substitution_formatter_test.cc | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index 897a35879de5..c5211b117cc7 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -2248,6 +2248,36 @@ TEST(SubstitutionFormatterTest, DynamicMetadataFormatter) { stream_info, body, AccessLog::AccessLogType::NotSet), ProtoEq(ValueUtil::stringValue("test_value"))); } + + // Add the NaN test for number value. This behavior will be changed in the future Protobuf + // dependency upgrade, and the Json serialization will fail if the number value is NaN or + // Infinity. We need to change the `getJsonStringFromMessage` description, re-evaluate the use + // of ENVOY_BUG in the MetaDataFormatter::format method, and modify the following two tests. + { + ProtobufWkt::Value val; + val.set_number_value(std::numeric_limits::quiet_NaN()); + ProtobufWkt::Struct struct_obj; + (*struct_obj.mutable_fields())["nan_val"] = val; + (*metadata.mutable_filter_metadata())["com.test"] = struct_obj; + + DynamicMetadataFormatter formatter("com.test", {"nan_val"}, absl::optional()); + EXPECT_EQ("\"NaN\"", formatter.format(request_headers, response_headers, response_trailers, + stream_info, body, AccessLog::AccessLogType::NotSet)); + } + + // Add the Infinity test for number value. + { + ProtobufWkt::Value val; + val.set_number_value(std::numeric_limits::infinity()); + ProtobufWkt::Struct struct_obj; + (*struct_obj.mutable_fields())["inf_val"] = val; + (*metadata.mutable_filter_metadata())["com.test"] = struct_obj; + + DynamicMetadataFormatter formatter("com.test", {"inf_val"}, absl::optional()); + EXPECT_EQ("\"Infinity\"", + formatter.format(request_headers, response_headers, response_trailers, stream_info, + body, AccessLog::AccessLogType::NotSet)); + } } TEST(SubstitutionFormatterTest, FilterStateFormatter) { From 0297335b2be793b203990f102d9c12c23198cc8a Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 24 May 2023 15:13:38 +0100 Subject: [PATCH 072/228] ci/fuzz: Update to use `--extensions_fuzzed_count` flag for check (#27610) Signed-off-by: Ryan Northey --- source/docs/network_filter_fuzzing.md | 2 +- .../filters/network/common/fuzz/BUILD | 20 ++++--------------- .../filters/network/common/fuzz/config.bzl | 15 ++++++++++++++ tools/base/requirements.in | 2 +- tools/base/requirements.txt | 6 +++--- tools/code/BUILD | 5 +++++ 6 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 test/extensions/filters/network/common/fuzz/config.bzl diff --git a/source/docs/network_filter_fuzzing.md b/source/docs/network_filter_fuzzing.md index 590b4a94cd87..aa8ffd28e333 100644 --- a/source/docs/network_filter_fuzzing.md +++ b/source/docs/network_filter_fuzzing.md @@ -7,7 +7,7 @@ Before adding the new filter into the fuzzers, please make sure the filter is de # Add a new ReadFilter into Generic Readfilter Fuzzer Only one step is needed to add a new filter to the fuzzer: -* In the file [BUILD](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/BUILD) the name of the filter has to be added to the `READFILTER_FUZZ_FILTERS` list. The fuzz test will figure the available filters from the factories. +* In the file [config.bzl](https://github.com/envoyproxy/envoy/blob/main/test/extensions/filters/network/common/fuzz/config.bzl) the name of the filter has to be added to the `READFILTER_FUZZ_FILTERS` list. The fuzz test will figure the available filters from the factories. ``` READFILTER_FUZZ_FILTERS = [ "envoy.filters.network.client_ssl_auth", diff --git a/test/extensions/filters/network/common/fuzz/BUILD b/test/extensions/filters/network/common/fuzz/BUILD index 6778bee09fd0..edddb378e109 100644 --- a/test/extensions/filters/network/common/fuzz/BUILD +++ b/test/extensions/filters/network/common/fuzz/BUILD @@ -9,6 +9,10 @@ load( "//source/extensions:all_extensions.bzl", "envoy_filters_from_selected", ) +load( + ":config.bzl", + "READFILTER_FUZZ_FILTERS", +) licenses(["notice"]) # Apache 2 @@ -36,22 +40,6 @@ envoy_proto_library( ], ) -# The filters to be fuzzed by the network_readfilter_fuzz_test. Prefer to add only stable filters, -# that do not have a dedicated fuzzer to them. -READFILTER_FUZZ_FILTERS = [ - "envoy.filters.network.client_ssl_auth", - "envoy.filters.network.ext_authz", - "envoy.filters.network.envoy_mobile_http_connection_manager", - # A dedicated http_connection_manager fuzzer can be found in - # test/common/http/conn_manager_impl_fuzz_test.cc - "envoy.filters.network.http_connection_manager", - "envoy.filters.network.local_ratelimit", - "envoy.filters.network.ratelimit", - "envoy.filters.network.rbac", - # TODO(asraa): Remove when fuzzer sets up connections for TcpProxy properly. - # "envoy.filters.network.tcp_proxy", -] - envoy_cc_test_library( name = "vig_anymap_ext_lib", srcs = ["validated_input_generator_any_map_extensions.cc"], diff --git a/test/extensions/filters/network/common/fuzz/config.bzl b/test/extensions/filters/network/common/fuzz/config.bzl new file mode 100644 index 000000000000..c275f3dfed79 --- /dev/null +++ b/test/extensions/filters/network/common/fuzz/config.bzl @@ -0,0 +1,15 @@ +# The filters to be fuzzed by the network_readfilter_fuzz_test. Prefer to add only stable filters, +# that do not have a dedicated fuzzer to them. +READFILTER_FUZZ_FILTERS = [ + "envoy.filters.network.client_ssl_auth", + "envoy.filters.network.ext_authz", + "envoy.filters.network.envoy_mobile_http_connection_manager", + # A dedicated http_connection_manager fuzzer can be found in + # test/common/http/conn_manager_impl_fuzz_test.cc + "envoy.filters.network.http_connection_manager", + "envoy.filters.network.local_ratelimit", + "envoy.filters.network.ratelimit", + "envoy.filters.network.rbac", + # TODO(asraa): Remove when fuzzer sets up connections for TcpProxy properly. + # "envoy.filters.network.tcp_proxy", +] diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 653124e4adcf..361ce48bf0bd 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -6,7 +6,7 @@ colorama coloredlogs dependatool>=0.2.2 envoy.base.utils>=0.4.10 -envoy.code.check>=0.5.0 +envoy.code.check>=0.5.1 envoy.dependency.check>=0.1.7 envoy.distribution.release>=0.0.9 envoy.distribution.repo>=0.0.8 diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 33733690523d..34743052ec71 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -434,9 +434,9 @@ envoy-base-utils==0.4.11 \ # envoy-docs-sphinx-runner # envoy-github-release # envoy-gpg-sign -envoy-code-check==0.5.0 \ - --hash=sha256:326ad3f188705fe7d0652bc707f7bc5eac190ff5c68d21f2fc5ebebc3b100e45 \ - --hash=sha256:46314932f38cab7caf02ff0da1d7a961f94b4ceedb11e19d0552c36481a041e6 +envoy-code-check==0.5.1 \ + --hash=sha256:379162ed8d83c9cb045917269b58f6e59812523359d8b0772b35078ab06dc8c1 \ + --hash=sha256:4b2b11b4fff634f1268b8dfb754c1d99300b8e58f5bc4276c96a8eb30cb9cea6 # via -r requirements.in envoy-dependency-check==0.1.8 \ --hash=sha256:ac9820e446bb44e05121e5c93c210f40ca37076580b0d082da2c63e7784c338a \ diff --git a/tools/code/BUILD b/tools/code/BUILD index 61393c4ac239..1af762c87d1d 100644 --- a/tools/code/BUILD +++ b/tools/code/BUILD @@ -2,6 +2,10 @@ load("//bazel:envoy_build_system.bzl", "envoy_package") load("//tools/base:envoy_python.bzl", "envoy_entry_point") load("@envoy_repo//:path.bzl", "PATH") load("@aspect_bazel_lib//lib:jq.bzl", "jq") +load( + "//test/extensions/filters/network/common/fuzz:config.bzl", + "READFILTER_FUZZ_FILTERS", +) licenses(["notice"]) # Apache 2 @@ -22,6 +26,7 @@ envoy_entry_point( name = "check", args = [ "--extensions_build_config=$(location :extensions_build_config)", + "--extensions_fuzzed_count=%s" % len(READFILTER_FUZZ_FILTERS), "--path=%s" % PATH, "-b shellcheck:$(location @com_github_aignas_rules_shellcheck//:shellcheck)", "-b gofmt:$(location @go_sdk//:bin/gofmt)", From d04c3a406f5d5a896fa35e86a4689e4daca21a0f Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 24 May 2023 10:14:34 -0400 Subject: [PATCH 073/228] http: allowing for mixed case HTTP/1.1 scheme (#27581) Signed-off-by: Alyssa Wilk --- changelogs/current.yaml | 5 ++++ source/common/http/http1/codec_impl.cc | 9 +++++-- source/common/runtime/runtime_features.cc | 1 + test/integration/integration_test.cc | 30 +++++++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index e0205dcb8888..7f7af0bd7f0f 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -25,6 +25,11 @@ minor_behavior_changes: - area: custom response change: | The filter now traverses matchers from most specific to least specific per filter config till a match is found for the response. +- area: http1 + change: | + Allowing mixed case schemes in absolute urls (e.g. HtTp://www.google.com). Mixed case schemes will be normalized to + the lower cased equivalents before being forwarded upstream. This behavior can be reverted by setting runtime flag + ``envoy.reloadable_features.allow_absolute_url_with_mixed_scheme`` to false. - area: http1 change: | The HTTP1 server-side codec no longer considers encoding 1xx headers as diff --git a/source/common/http/http1/codec_impl.cc b/source/common/http/http1/codec_impl.cc index 053f397dd831..00a439c00241 100644 --- a/source/common/http/http1/codec_impl.cc +++ b/source/common/http/http1/codec_impl.cc @@ -1132,8 +1132,13 @@ Status ServerConnectionImpl::handlePath(RequestHeaderMap& headers, absl::string_ // Add the scheme and validate to ensure no https:// // requests are accepted over unencrypted connections by front-line Envoys. if (!is_connect) { - headers.setScheme(absolute_url.scheme()); - if (!HeaderUtility::schemeIsValid(absolute_url.scheme())) { + if (Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.allow_absolute_url_with_mixed_scheme")) { + headers.setScheme(absl::AsciiStrToLower(absolute_url.scheme())); + } else { + headers.setScheme(absolute_url.scheme()); + } + if (!HeaderUtility::schemeIsValid(headers.getSchemeValue())) { RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidScheme)); return codecProtocolError("http/1.1 protocol error: invalid scheme"); } diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 360998402fa3..14e980901d74 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -29,6 +29,7 @@ // If issues are found that require a runtime feature to be disabled, it should be reported // ASAP by filing a bug on github. Overriding non-buggy code is strongly discouraged to avoid the // problem of the bugs being found after the old code path has been removed. +RUNTIME_GUARD(envoy_reloadable_features_allow_absolute_url_with_mixed_scheme); RUNTIME_GUARD(envoy_reloadable_features_allow_compact_maglev); RUNTIME_GUARD(envoy_reloadable_features_append_query_parameters_path_rewriter); RUNTIME_GUARD(envoy_reloadable_features_append_xfh_idempotent); diff --git a/test/integration/integration_test.cc b/test/integration/integration_test.cc index cc08069f481a..7c30ed707159 100644 --- a/test/integration/integration_test.cc +++ b/test/integration/integration_test.cc @@ -1538,6 +1538,36 @@ TEST_P(IntegrationTest, AbsolutePathWithPort) { EXPECT_THAT(response, StartsWith("HTTP/1.1 301")); } +TEST_P(IntegrationTest, AbsolutePathWithMixedScheme) { + // Configure www.namewithport.com:1234 to send a redirect, and ensure the redirect is + // encountered via absolute URL with a port. + auto host = config_helper_.createVirtualHost("www.namewithport.com:1234", "/"); + host.set_require_tls(envoy::config::route::v3::VirtualHost::ALL); + config_helper_.addVirtualHost(host); + initialize(); + std::string response; + sendRawHttpAndWaitForResponse( + lookupPort("http"), "GET hTtp://www.namewithport.com:1234 HTTP/1.1\r\nHost: host\r\n\r\n", + &response, true); + EXPECT_THAT(response, StartsWith("HTTP/1.1 301")); +} + +TEST_P(IntegrationTest, AbsolutePathWithMixedSchemeLegacy) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.allow_absolute_url_with_mixed_scheme", "false"); + + // Mixed scheme requests will be rejected + auto host = config_helper_.createVirtualHost("www.namewithport.com:1234", "/"); + host.set_require_tls(envoy::config::route::v3::VirtualHost::ALL); + config_helper_.addVirtualHost(host); + initialize(); + std::string response; + sendRawHttpAndWaitForResponse( + lookupPort("http"), "GET hTtp://www.namewithport.com:1234 HTTP/1.1\r\nHost: host\r\n\r\n", + &response, true); + EXPECT_THAT(response, StartsWith("HTTP/1.1 400")); +} + TEST_P(IntegrationTest, AbsolutePathWithoutPort) { // Add a restrictive default match, to avoid the request hitting the * / catchall. config_helper_.setDefaultHostAndRoute("foo.com", "/found"); From d9275856a07a7ec312230b9c2c31260229642e50 Mon Sep 17 00:00:00 2001 From: "Dr. Andre Vehreschild" <101638173+vehre-x41@users.noreply.github.com> Date: Wed, 24 May 2023 16:22:08 +0200 Subject: [PATCH 074/228] [fuzz] Use absl::Cleanup to ensure leaveMessage is called (#27609) Signed-off-by: Andre Vehreschild --- test/fuzz/BUILD | 1 + test/fuzz/mutable_visitor.cc | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test/fuzz/BUILD b/test/fuzz/BUILD index 129b42d04bdb..df66c8862a78 100644 --- a/test/fuzz/BUILD +++ b/test/fuzz/BUILD @@ -89,6 +89,7 @@ envoy_cc_test_library( "//source/common/protobuf:visitor_lib", "@com_github_cncf_udpa//udpa/type/v1:pkg_cc_proto", "@com_github_cncf_udpa//xds/type/v3:pkg_cc_proto", + "@com_google_absl//absl/cleanup", ], ) diff --git a/test/fuzz/mutable_visitor.cc b/test/fuzz/mutable_visitor.cc index 4ee7f29b29e8..b011d2caff42 100644 --- a/test/fuzz/mutable_visitor.cc +++ b/test/fuzz/mutable_visitor.cc @@ -5,6 +5,7 @@ #include "source/common/protobuf/utility.h" #include "source/common/protobuf/visitor_helper.h" +#include "absl/cleanup/cleanup.h" #include "udpa/type/v1/typed_struct.pb.h" #include "xds/type/v3/typed_struct.pb.h" @@ -17,6 +18,9 @@ void traverseMessageWorkerExt(ProtoVisitor& visitor, Protobuf::Message& message, bool was_any_or_top_level, bool recurse_into_any, absl::string_view const& field_name) { visitor.onEnterMessage(message, parents, was_any_or_top_level, field_name); + absl::Cleanup message_leaver = [&visitor, &parents, &message, was_any_or_top_level, field_name] { + visitor.onLeaveMessage(message, parents, was_any_or_top_level, field_name); + }; // If told to recurse into Any messages, do that here and skip the rest of the function. if (recurse_into_any) { @@ -71,7 +75,6 @@ void traverseMessageWorkerExt(ProtoVisitor& visitor, Protobuf::Message& message, } } } - visitor.onLeaveMessage(message, parents, was_any_or_top_level, field_name); } } // namespace From fdd36d3893a3282ec06060c2e4523fbd5808e6b1 Mon Sep 17 00:00:00 2001 From: sky Date: Wed, 24 May 2023 22:39:45 +0800 Subject: [PATCH 075/228] Optimize the supportsIpTransparent function to avoid getOriginalDst failure (#27538) Signed-off-by: wangfakang --- envoy/api/os_sys_calls.h | 4 +- envoy/network/socket.h | 120 ++++++++++++++++++ source/common/api/BUILD | 1 + source/common/api/posix/os_sys_calls_impl.cc | 36 +++--- source/common/api/posix/os_sys_calls_impl.h | 2 +- source/common/api/win32/os_sys_calls_impl.cc | 2 +- source/common/api/win32/os_sys_calls_impl.h | 2 +- source/common/network/socket_option_impl.h | 119 ----------------- source/common/network/utility.cc | 2 +- .../filters/udp/udp_proxy/udp_proxy_filter.h | 4 +- test/common/network/utility_test.cc | 8 +- .../udp/udp_proxy/udp_proxy_filter_test.cc | 8 +- test/mocks/api/mocks.h | 2 +- 13 files changed, 156 insertions(+), 154 deletions(-) diff --git a/envoy/api/os_sys_calls.h b/envoy/api/os_sys_calls.h index 44e67c3ef4d9..03509b4eef08 100644 --- a/envoy/api/os_sys_calls.h +++ b/envoy/api/os_sys_calls.h @@ -121,9 +121,9 @@ class OsSysCalls { virtual bool supportsUdpGso() const PURE; /** - * return true if the OS support both IP_TRANSPARENT and IPV6_TRANSPARENT options + * return true if the OS support IP_TRANSPARENT or IPV6_TRANSPARENT options by the ip version. */ - virtual bool supportsIpTransparent() const PURE; + virtual bool supportsIpTransparent(Network::Address::IpVersion version) const PURE; /** * return true if the OS supports multi-path TCP diff --git a/envoy/network/socket.h b/envoy/network/socket.h index 8756457cbdc2..0f2cde06ff19 100644 --- a/envoy/network/socket.h +++ b/envoy/network/socket.h @@ -42,6 +42,126 @@ struct SocketOptionName { #define ENVOY_MAKE_SOCKET_OPTION_NAME(level, option) \ Network::SocketOptionName(level, option, #level "/" #option) +// Moved from source/common/network/socket_option_impl.h to avoid dependency loops. +#ifdef IP_TRANSPARENT +#define ENVOY_SOCKET_IP_TRANSPARENT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, IP_TRANSPARENT) +#else +#define ENVOY_SOCKET_IP_TRANSPARENT Network::SocketOptionName() +#endif + +#ifdef IPV6_TRANSPARENT +#define ENVOY_SOCKET_IPV6_TRANSPARENT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_TRANSPARENT) +#else +#define ENVOY_SOCKET_IPV6_TRANSPARENT Network::SocketOptionName() +#endif + +#ifdef IP_FREEBIND +#define ENVOY_SOCKET_IP_FREEBIND ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, IP_FREEBIND) +#else +#define ENVOY_SOCKET_IP_FREEBIND Network::SocketOptionName() +#endif + +#ifdef IPV6_FREEBIND +#define ENVOY_SOCKET_IPV6_FREEBIND ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_FREEBIND) +#else +#define ENVOY_SOCKET_IPV6_FREEBIND Network::SocketOptionName() +#endif + +#ifdef SO_KEEPALIVE +#define ENVOY_SOCKET_SO_KEEPALIVE ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_KEEPALIVE) +#else +#define ENVOY_SOCKET_SO_KEEPALIVE Network::SocketOptionName() +#endif + +#ifdef SO_MARK +#define ENVOY_SOCKET_SO_MARK ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_MARK) +#else +#define ENVOY_SOCKET_SO_MARK Network::SocketOptionName() +#endif + +#ifdef SO_NOSIGPIPE +#define ENVOY_SOCKET_SO_NOSIGPIPE ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_NOSIGPIPE) +#else +#define ENVOY_SOCKET_SO_NOSIGPIPE Network::SocketOptionName() +#endif + +#ifdef SO_REUSEPORT +#define ENVOY_SOCKET_SO_REUSEPORT ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_REUSEPORT) +#else +#define ENVOY_SOCKET_SO_REUSEPORT Network::SocketOptionName() +#endif + +#ifdef SO_ORIGINAL_DST +#define ENVOY_SOCKET_SO_ORIGINAL_DST ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_IP, SO_ORIGINAL_DST) +#else +#define ENVOY_SOCKET_SO_ORIGINAL_DST Network::SocketOptionName() +#endif + +#ifdef IP6T_SO_ORIGINAL_DST +#define ENVOY_SOCKET_IP6T_SO_ORIGINAL_DST \ + ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_IPV6, IP6T_SO_ORIGINAL_DST) +#else +#define ENVOY_SOCKET_IP6T_SO_ORIGINAL_DST Network::SocketOptionName() +#endif + +#ifdef UDP_GRO +#define ENVOY_SOCKET_UDP_GRO ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_UDP, UDP_GRO) +#else +#define ENVOY_SOCKET_UDP_GRO Network::SocketOptionName() +#endif + +#ifdef TCP_KEEPCNT +#define ENVOY_SOCKET_TCP_KEEPCNT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPCNT) +#else +#define ENVOY_SOCKET_TCP_KEEPCNT Network::SocketOptionName() +#endif + +#ifdef TCP_KEEPIDLE +#define ENVOY_SOCKET_TCP_KEEPIDLE ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPIDLE) +#elif TCP_KEEPALIVE // macOS uses a different name from Linux for just this option. +#define ENVOY_SOCKET_TCP_KEEPIDLE ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPALIVE) +#else +#define ENVOY_SOCKET_TCP_KEEPIDLE Network::SocketOptionName() +#endif + +#ifdef TCP_KEEPINTVL +#define ENVOY_SOCKET_TCP_KEEPINTVL ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPINTVL) +#else +#define ENVOY_SOCKET_TCP_KEEPINTVL Network::SocketOptionName() +#endif + +#ifdef TCP_FASTOPEN +#define ENVOY_SOCKET_TCP_FASTOPEN ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_FASTOPEN) +#else +#define ENVOY_SOCKET_TCP_FASTOPEN Network::SocketOptionName() +#endif + +// Linux uses IP_PKTINFO for both sending source address and receiving destination +// address. +// FreeBSD uses IP_RECVDSTADDR for receiving destination address and IP_SENDSRCADDR for sending +// source address. And these two have same value for convenience purpose. +#ifdef IP_RECVDSTADDR +#ifdef IP_SENDSRCADDR +static_assert(IP_RECVDSTADDR == IP_SENDSRCADDR); +#endif +#define ENVOY_IP_PKTINFO IP_RECVDSTADDR +#elif IP_PKTINFO +#define ENVOY_IP_PKTINFO IP_PKTINFO +#endif + +#define ENVOY_SELF_IP_ADDR ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, ENVOY_IP_PKTINFO) + +// Both Linux and FreeBSD use IPV6_RECVPKTINFO for both sending source address and +// receiving destination address. +#define ENVOY_SELF_IPV6_ADDR ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_RECVPKTINFO) + +#ifdef SO_ATTACH_REUSEPORT_CBPF +#define ENVOY_ATTACH_REUSEPORT_CBPF \ + ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF) +#else +#define ENVOY_ATTACH_REUSEPORT_CBPF Network::SocketOptionName() +#endif + /** * Interfaces for providing a socket's various addresses. This is split into a getters interface * and a getters + setters interface. This is so that only the getters portion can be overridden diff --git a/source/common/api/BUILD b/source/common/api/BUILD index 0ee05a74470d..3230052364e2 100644 --- a/source/common/api/BUILD +++ b/source/common/api/BUILD @@ -57,6 +57,7 @@ envoy_cc_library( }), deps = [ "//envoy/api:os_sys_calls_interface", + "//envoy/network:socket_interface", "//source/common/network:address_lib", "//source/common/singleton:threadsafe_singleton", "//third_party/android:android_lib", diff --git a/source/common/api/posix/os_sys_calls_impl.cc b/source/common/api/posix/os_sys_calls_impl.cc index e6f35422384c..7df7e6384e90 100644 --- a/source/common/api/posix/os_sys_calls_impl.cc +++ b/source/common/api/posix/os_sys_calls_impl.cc @@ -5,6 +5,8 @@ #include #include +#include "envoy/network/socket.h" + #include "source/common/api/os_sys_calls_impl.h" #include "source/common/network/address_impl.h" @@ -138,8 +140,9 @@ bool OsSysCallsImpl::supportsUdpGso() const { #endif } -bool OsSysCallsImpl::supportsIpTransparent() const { -#if !defined(__linux__) || !defined(IPV6_TRANSPARENT) +bool OsSysCallsImpl::supportsIpTransparent(Network::Address::IpVersion ip_version) const { +#if !defined(__linux__) + UNREFERENCED_PARAMETER(ip_version); return false; #else // The linux kernel supports IP_TRANSPARENT by following patch(starting from v2.6.28) : @@ -149,32 +152,27 @@ bool OsSysCallsImpl::supportsIpTransparent() const { // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ipv6/ipv6_sockglue.c?id=6c46862280c5f55eda7750391bc65cd7e08c7535 // // So, almost recent linux kernel supports both IP_TRANSPARENT and IPV6_TRANSPARENT options. + // But there are also has ipv4 only or ipv6 only scenarios. // // And these socket options need CAP_NET_ADMIN capability to be applied. // The CAP_NET_ADMIN capability should be applied by root user before call this function. - static const bool is_supported = [] { - // Check ipv4 case - int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); + + static constexpr auto transparent_supported = [](int family) { + auto opt_tp = family == AF_INET ? ENVOY_SOCKET_IP_TRANSPARENT : ENVOY_SOCKET_IPV6_TRANSPARENT; + int fd = ::socket(family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); if (fd < 0) { return false; } int val = 1; - bool result = (0 == ::setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &val, sizeof(val))); - ::close(fd); - if (!result) { - return false; - } - // Check ipv6 case - fd = ::socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); - if (fd < 0) { - return false; - } - val = 1; - result = (0 == ::setsockopt(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, &val, sizeof(val))); + bool result = (0 == ::setsockopt(fd, opt_tp.level(), opt_tp.option(), &val, sizeof(val))); ::close(fd); return result; - }(); - return is_supported; + }; + // Check ipv4 case + static const bool ipv4_is_supported = transparent_supported(AF_INET); + // Check ipv6 case + static const bool ipv6_is_supported = transparent_supported(AF_INET6); + return ip_version == Network::Address::IpVersion::v4 ? ipv4_is_supported : ipv6_is_supported; #endif } diff --git a/source/common/api/posix/os_sys_calls_impl.h b/source/common/api/posix/os_sys_calls_impl.h index 846fa4b2e115..e3e241be5739 100644 --- a/source/common/api/posix/os_sys_calls_impl.h +++ b/source/common/api/posix/os_sys_calls_impl.h @@ -31,7 +31,7 @@ class OsSysCallsImpl : public OsSysCalls { bool supportsMmsg() const override; bool supportsUdpGro() const override; bool supportsUdpGso() const override; - bool supportsIpTransparent() const override; + bool supportsIpTransparent(Network::Address::IpVersion version) const override; bool supportsMptcp() const override; SysCallIntResult close(os_fd_t fd) override; SysCallIntResult ftruncate(int fd, off_t length) override; diff --git a/source/common/api/win32/os_sys_calls_impl.cc b/source/common/api/win32/os_sys_calls_impl.cc index 30229e3aa3ca..3e1e7780ca49 100644 --- a/source/common/api/win32/os_sys_calls_impl.cc +++ b/source/common/api/win32/os_sys_calls_impl.cc @@ -212,7 +212,7 @@ bool OsSysCallsImpl::supportsUdpGso() const { return false; } -bool OsSysCallsImpl::supportsIpTransparent() const { +bool OsSysCallsImpl::supportsIpTransparent(Network::Address::IpVersion) const { // Windows doesn't support it. return false; } diff --git a/source/common/api/win32/os_sys_calls_impl.h b/source/common/api/win32/os_sys_calls_impl.h index 4a19d8b91bdf..a686b16ca10d 100644 --- a/source/common/api/win32/os_sys_calls_impl.h +++ b/source/common/api/win32/os_sys_calls_impl.h @@ -32,7 +32,7 @@ class OsSysCallsImpl : public OsSysCalls { bool supportsMmsg() const override; bool supportsUdpGro() const override; bool supportsUdpGso() const override; - bool supportsIpTransparent() const override; + bool supportsIpTransparent(Network::Address::IpVersion version) const override; bool supportsMptcp() const override; SysCallIntResult close(os_fd_t fd) override; SysCallIntResult ftruncate(int fd, off_t length) override; diff --git a/source/common/network/socket_option_impl.h b/source/common/network/socket_option_impl.h index 9e2c03ccac33..cea24762ae7f 100644 --- a/source/common/network/socket_option_impl.h +++ b/source/common/network/socket_option_impl.h @@ -11,125 +11,6 @@ namespace Envoy { namespace Network { -#ifdef IP_TRANSPARENT -#define ENVOY_SOCKET_IP_TRANSPARENT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, IP_TRANSPARENT) -#else -#define ENVOY_SOCKET_IP_TRANSPARENT Network::SocketOptionName() -#endif - -#ifdef IPV6_TRANSPARENT -#define ENVOY_SOCKET_IPV6_TRANSPARENT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_TRANSPARENT) -#else -#define ENVOY_SOCKET_IPV6_TRANSPARENT Network::SocketOptionName() -#endif - -#ifdef IP_FREEBIND -#define ENVOY_SOCKET_IP_FREEBIND ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, IP_FREEBIND) -#else -#define ENVOY_SOCKET_IP_FREEBIND Network::SocketOptionName() -#endif - -#ifdef IPV6_FREEBIND -#define ENVOY_SOCKET_IPV6_FREEBIND ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_FREEBIND) -#else -#define ENVOY_SOCKET_IPV6_FREEBIND Network::SocketOptionName() -#endif - -#ifdef SO_KEEPALIVE -#define ENVOY_SOCKET_SO_KEEPALIVE ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_KEEPALIVE) -#else -#define ENVOY_SOCKET_SO_KEEPALIVE Network::SocketOptionName() -#endif - -#ifdef SO_MARK -#define ENVOY_SOCKET_SO_MARK ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_MARK) -#else -#define ENVOY_SOCKET_SO_MARK Network::SocketOptionName() -#endif - -#ifdef SO_NOSIGPIPE -#define ENVOY_SOCKET_SO_NOSIGPIPE ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_NOSIGPIPE) -#else -#define ENVOY_SOCKET_SO_NOSIGPIPE Network::SocketOptionName() -#endif - -#ifdef SO_REUSEPORT -#define ENVOY_SOCKET_SO_REUSEPORT ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_REUSEPORT) -#else -#define ENVOY_SOCKET_SO_REUSEPORT Network::SocketOptionName() -#endif - -#ifdef SO_ORIGINAL_DST -#define ENVOY_SOCKET_SO_ORIGINAL_DST ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_IP, SO_ORIGINAL_DST) -#else -#define ENVOY_SOCKET_SO_ORIGINAL_DST Network::SocketOptionName() -#endif - -#ifdef IP6T_SO_ORIGINAL_DST -#define ENVOY_SOCKET_IP6T_SO_ORIGINAL_DST \ - ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_IPV6, IP6T_SO_ORIGINAL_DST) -#else -#define ENVOY_SOCKET_IP6T_SO_ORIGINAL_DST Network::SocketOptionName() -#endif - -#ifdef UDP_GRO -#define ENVOY_SOCKET_UDP_GRO ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_UDP, UDP_GRO) -#else -#define ENVOY_SOCKET_UDP_GRO Network::SocketOptionName() -#endif - -#ifdef TCP_KEEPCNT -#define ENVOY_SOCKET_TCP_KEEPCNT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPCNT) -#else -#define ENVOY_SOCKET_TCP_KEEPCNT Network::SocketOptionName() -#endif - -#ifdef TCP_KEEPIDLE -#define ENVOY_SOCKET_TCP_KEEPIDLE ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPIDLE) -#elif TCP_KEEPALIVE // macOS uses a different name from Linux for just this option. -#define ENVOY_SOCKET_TCP_KEEPIDLE ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPALIVE) -#else -#define ENVOY_SOCKET_TCP_KEEPIDLE Network::SocketOptionName() -#endif - -#ifdef TCP_KEEPINTVL -#define ENVOY_SOCKET_TCP_KEEPINTVL ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPINTVL) -#else -#define ENVOY_SOCKET_TCP_KEEPINTVL Network::SocketOptionName() -#endif - -#ifdef TCP_FASTOPEN -#define ENVOY_SOCKET_TCP_FASTOPEN ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_FASTOPEN) -#else -#define ENVOY_SOCKET_TCP_FASTOPEN Network::SocketOptionName() -#endif - -// Linux uses IP_PKTINFO for both sending source address and receiving destination -// address. -// FreeBSD uses IP_RECVDSTADDR for receiving destination address and IP_SENDSRCADDR for sending -// source address. And these two have same value for convenience purpose. -#ifdef IP_RECVDSTADDR -#ifdef IP_SENDSRCADDR -static_assert(IP_RECVDSTADDR == IP_SENDSRCADDR); -#endif -#define ENVOY_IP_PKTINFO IP_RECVDSTADDR -#elif IP_PKTINFO -#define ENVOY_IP_PKTINFO IP_PKTINFO -#endif - -#define ENVOY_SELF_IP_ADDR ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, ENVOY_IP_PKTINFO) - -// Both Linux and FreeBSD use IPV6_RECVPKTINFO for both sending source address and -// receiving destination address. -#define ENVOY_SELF_IPV6_ADDR ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_RECVPKTINFO) - -#ifdef SO_ATTACH_REUSEPORT_CBPF -#define ENVOY_ATTACH_REUSEPORT_CBPF \ - ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF) -#else -#define ENVOY_ATTACH_REUSEPORT_CBPF Network::SocketOptionName() -#endif - class SocketOptionImpl : public Socket::Option, Logger::Loggable { public: SocketOptionImpl(envoy::config::core::v3::SocketOption::SocketState in_state, diff --git a/source/common/network/utility.cc b/source/common/network/utility.cc index 08349765fb39..8e244f0a520e 100644 --- a/source/common/network/utility.cc +++ b/source/common/network/utility.cc @@ -392,7 +392,7 @@ Address::InstanceConstSharedPtr Utility::getOriginalDst(Socket& sock) { sock.getSocketOption(opt_dst.level(), opt_dst.option(), &orig_addr, &addr_len).return_value_; if (status != 0) { - if (Api::OsSysCallsSingleton::get().supportsIpTransparent()) { + if (Api::OsSysCallsSingleton::get().supportsIpTransparent(*ipVersion)) { socklen_t flag_len = sizeof(int); int is_tp; status = diff --git a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h index 925dc8453e17..a31b66c25696 100644 --- a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h +++ b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h @@ -82,7 +82,9 @@ class UdpProxyFilterConfig { // Default prefer_gro to true for upstream client traffic. upstream_socket_config_(config.upstream_socket_config(), true), random_(context.api().randomGenerator()) { - if (use_original_src_ip_ && !Api::OsSysCallsSingleton::get().supportsIpTransparent()) { + if (use_original_src_ip_ && + !Api::OsSysCallsSingleton::get().supportsIpTransparent( + context.getServerFactoryContext().options().localAddressIpVersion())) { ExceptionUtil::throwEnvoyException( "The platform does not support either IP_TRANSPARENT or IPV6_TRANSPARENT. Or the envoy " "is not running with the CAP_NET_ADMIN capability."); diff --git a/test/common/network/utility_test.cc b/test/common/network/utility_test.cc index 74d3ccbd9c07..03e7d8c8354b 100644 --- a/test/common/network/utility_test.cc +++ b/test/common/network/utility_test.cc @@ -354,7 +354,7 @@ TEST(NetworkUtility, GetOriginalDst) { // Transparent socket gets original dst from local address while connection tracking disabled EXPECT_CALL(socket, getSocketOption(Eq(SOL_IP), Eq(SO_ORIGINAL_DST), _, _)) .WillOnce(Return(Api::SysCallIntResult{-1, 0})); - EXPECT_CALL(os_sys_calls, supportsIpTransparent()).WillOnce(Return(true)); + EXPECT_CALL(os_sys_calls, supportsIpTransparent(Address::IpVersion::v4)).WillOnce(Return(true)); EXPECT_CALL(socket, getSocketOption(Eq(SOL_IP), Eq(IP_TRANSPARENT), _, _)) .WillOnce(DoAll(SetArg2Int(1), Return(Api::SysCallIntResult{0, 0}))); EXPECT_CALL(os_sys_calls, getsockname(_, _, _)) @@ -364,7 +364,7 @@ TEST(NetworkUtility, GetOriginalDst) { // Non-transparent socket fails to get original dst while connection tracking disabled EXPECT_CALL(socket, getSocketOption(Eq(SOL_IP), Eq(SO_ORIGINAL_DST), _, _)) .WillOnce(Return(Api::SysCallIntResult{-1, 0})); - EXPECT_CALL(os_sys_calls, supportsIpTransparent()).WillOnce(Return(true)); + EXPECT_CALL(os_sys_calls, supportsIpTransparent(Address::IpVersion::v4)).WillOnce(Return(true)); EXPECT_CALL(socket, getSocketOption(Eq(SOL_IP), Eq(IP_TRANSPARENT), _, _)) .WillOnce(DoAll(SetArg2Int(0), Return(Api::SysCallIntResult{0, 0}))); EXPECT_EQ(nullptr, Utility::getOriginalDst(socket)); @@ -383,7 +383,7 @@ TEST(NetworkUtility, GetOriginalDst) { // Transparent socket gets original dst from local address while connection tracking disabled EXPECT_CALL(socket, getSocketOption(Eq(SOL_IPV6), Eq(IP6T_SO_ORIGINAL_DST), _, _)) .WillOnce(Return(Api::SysCallIntResult{-1, 0})); - EXPECT_CALL(os_sys_calls, supportsIpTransparent()).WillOnce(Return(true)); + EXPECT_CALL(os_sys_calls, supportsIpTransparent(Address::IpVersion::v6)).WillOnce(Return(true)); EXPECT_CALL(socket, getSocketOption(Eq(SOL_IPV6), Eq(IPV6_TRANSPARENT), _, _)) .WillOnce(DoAll(SetArg2Int(1), Return(Api::SysCallIntResult{0, 0}))); EXPECT_CALL(os_sys_calls, getsockname(_, _, _)) @@ -393,7 +393,7 @@ TEST(NetworkUtility, GetOriginalDst) { // Non-transparent socket fails to get original dst while connection tracking disabled EXPECT_CALL(socket, getSocketOption(Eq(SOL_IPV6), Eq(IP6T_SO_ORIGINAL_DST), _, _)) .WillOnce(Return(Api::SysCallIntResult{-1, 0})); - EXPECT_CALL(os_sys_calls, supportsIpTransparent()).WillOnce(Return(true)); + EXPECT_CALL(os_sys_calls, supportsIpTransparent(Address::IpVersion::v6)).WillOnce(Return(true)); EXPECT_CALL(socket, getSocketOption(Eq(SOL_IPV6), Eq(IPV6_TRANSPARENT), _, _)) .WillOnce(DoAll(SetArg2Int(0), Return(Api::SysCallIntResult{0, 0}))); EXPECT_EQ(nullptr, Utility::getOriginalDst(socket)); diff --git a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc index 78014ad92105..22876780059d 100644 --- a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc +++ b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc @@ -200,7 +200,7 @@ class UdpProxyFilterTest : public UdpProxyFilterBase { ON_CALL(*factory_context_.access_log_manager_.file_, write(_)) .WillByDefault( Invoke([&](absl::string_view data) { output_.push_back(std::string(data)); })); - ON_CALL(os_sys_calls_, supportsIpTransparent()).WillByDefault(Return(true)); + ON_CALL(os_sys_calls_, supportsIpTransparent(_)).WillByDefault(Return(true)); EXPECT_CALL(os_sys_calls_, supportsUdpGro()).Times(AtLeast(0)).WillRepeatedly(Return(true)); EXPECT_CALL(callbacks_, udpListener()).Times(AtLeast(0)); EXPECT_CALL(*factory_context_.cluster_manager_.thread_local_cluster_.lb_.host_, address()) @@ -917,7 +917,7 @@ TEST_F(UdpProxyFilterTest, SocketOptionForUseOriginalSrcIp) { // The option is not supported on this platform. Just skip the test. GTEST_SKIP(); } - EXPECT_CALL(os_sys_calls_, supportsIpTransparent()); + EXPECT_CALL(os_sys_calls_, supportsIpTransparent(_)); InSequence s; @@ -1142,7 +1142,7 @@ TEST_F(UdpProxyFilterIpv6Test, SocketOptionForUseOriginalSrcIpInCaseOfIpv6) { // The option is not supported on this platform. Just skip the test. GTEST_SKIP(); } - EXPECT_CALL(os_sys_calls_, supportsIpTransparent()); + EXPECT_CALL(os_sys_calls_, supportsIpTransparent(_)); InSequence s; @@ -1199,7 +1199,7 @@ stat_prefix: foo // Make sure exit when use the use_original_src_ip but platform does not support ip // transparent option. TEST_F(UdpProxyFilterTest, ExitIpTransparentNoPlatformSupport) { - EXPECT_CALL(os_sys_calls_, supportsIpTransparent()).WillOnce(Return(false)); + EXPECT_CALL(os_sys_calls_, supportsIpTransparent(_)).WillOnce(Return(false)); InSequence s; diff --git a/test/mocks/api/mocks.h b/test/mocks/api/mocks.h index 0d66fb84f3ed..1496bef7aa19 100644 --- a/test/mocks/api/mocks.h +++ b/test/mocks/api/mocks.h @@ -124,7 +124,7 @@ class MockOsSysCalls : public OsSysCallsImpl { MOCK_METHOD(SysCallBoolResult, socketTcpInfo, (os_fd_t sockfd, EnvoyTcpInfo* tcp_info)); MOCK_METHOD(bool, supportsMmsg, (), (const)); MOCK_METHOD(bool, supportsUdpGro, (), (const)); - MOCK_METHOD(bool, supportsIpTransparent, (), (const)); + MOCK_METHOD(bool, supportsIpTransparent, (Network::Address::IpVersion version), (const)); MOCK_METHOD(bool, supportsMptcp, (), (const)); MOCK_METHOD(bool, supportsGetifaddrs, (), (const)); MOCK_METHOD(SysCallIntResult, getifaddrs, (InterfaceAddressVector & interfaces)); From 332852df3ca261b954c47c699a785850663a0a58 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 24 May 2023 10:43:26 -0400 Subject: [PATCH 076/228] test: allowing bootstrap config in integration tests (#27436) Signed-off-by: Alyssa Wilk --- .../kv_store_xds_delegate_integration_test.cc | 3 +- mobile/library/cc/engine_builder.cc | 13 +---- mobile/library/cc/engine_builder.h | 15 +----- mobile/test/cc/integration/lifetimes_test.cc | 5 +- .../test/cc/integration/send_headers_test.cc | 5 +- .../base_client_integration_test.cc | 14 +++--- .../base_client_integration_test.h | 5 +- .../common/integration/test_engine_builder.cc | 11 ++-- .../common/integration/test_engine_builder.h | 21 ++++++-- test/config/utility.cc | 18 +++++-- test/config/utility.h | 6 ++- .../http_grpc_access_log_integration_test.cc | 3 +- .../internal_listener_integration_test.cc | 9 ++-- .../http/tap/tap_filter_integration_test.cc | 3 +- test/integration/base_integration_test.cc | 30 ++++++++--- test/integration/base_integration_test.h | 4 ++ .../listener_lds_integration_test.cc | 3 +- test/integration/multi_envoy_test.cc | 3 +- .../integration/quic_http_integration_test.cc | 16 ++---- .../tcp_tunneling_integration_test.cc | 3 +- test/integration/xds_integration_test.cc | 50 ++++--------------- 21 files changed, 112 insertions(+), 128 deletions(-) diff --git a/contrib/config/test/kv_store_xds_delegate_integration_test.cc b/contrib/config/test/kv_store_xds_delegate_integration_test.cc index 049d9e727454..18a8836293b6 100644 --- a/contrib/config/test/kv_store_xds_delegate_integration_test.cc +++ b/contrib/config/test/kv_store_xds_delegate_integration_test.cc @@ -248,8 +248,7 @@ class KeyValueStoreXdsDelegateIntegrationTest on_server_init_function_ = nullptr; // Set up a new Envoy, using the previous Envoy's configuration, and create the test server. - ConfigHelper helper(version_, *api_, - MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper helper(version_, config_helper_.bootstrap()); // Close the connection between Envoy and the xDS FakeUpstreams. closeConnection(sds_connection_); diff --git a/mobile/library/cc/engine_builder.cc b/mobile/library/cc/engine_builder.cc index bc4bce48509c..aed3ca25acf6 100644 --- a/mobile/library/cc/engine_builder.cc +++ b/mobile/library/cc/engine_builder.cc @@ -286,11 +286,6 @@ EngineBuilder& EngineBuilder::setRuntimeGuard(std::string guard, bool value) { return *this; } -EngineBuilder& EngineBuilder::setOverrideConfigForTests(std::string config) { - config_override_for_tests_ = std::move(config); - return *this; -} - std::unique_ptr EngineBuilder::generateBootstrap() const { // The yaml utilities have non-relevant thread asserts. Thread::SkipAsserts skip; @@ -885,11 +880,6 @@ EngineSharedPtr EngineBuilder::build() { envoy_event_tracker null_tracker{}; - std::unique_ptr bootstrap; - if (config_override_for_tests_.empty()) { - bootstrap = generateBootstrap(); - } - envoy_engine_t envoy_engine = init_engine(callbacks_->asEnvoyEngineCallbacks(), null_logger, null_tracker); @@ -911,10 +901,9 @@ EngineSharedPtr EngineBuilder::build() { if (auto cast_engine = reinterpret_cast(envoy_engine)) { auto options = std::make_unique(); + std::unique_ptr bootstrap = generateBootstrap(); if (bootstrap) { options->setConfigProto(std::move(bootstrap)); - } else { - options->setConfigYaml(config_override_for_tests_); } options->setLogLevel(options->parseAndValidateLogLevel(logLevelToString(log_level_).c_str())); options->setConcurrency(1); diff --git a/mobile/library/cc/engine_builder.h b/mobile/library/cc/engine_builder.h index 4eedcaac8296..84b8ce489983 100644 --- a/mobile/library/cc/engine_builder.h +++ b/mobile/library/cc/engine_builder.h @@ -37,6 +37,7 @@ struct NodeLocality { class EngineBuilder { public: EngineBuilder(); + virtual ~EngineBuilder() {} EngineBuilder& addLogLevel(LogLevel log_level); EngineBuilder& setOnEngineRunning(std::function closure); @@ -109,21 +110,10 @@ class EngineBuilder { EngineBuilder& addStringAccessor(std::string name, StringAccessorSharedPtr accessor); // This is separated from build() for the sake of testability - std::unique_ptr generateBootstrap() const; + virtual std::unique_ptr generateBootstrap() const; EngineSharedPtr build(); -protected: - // Overrides the EngineBuilder's constructed configuration with the YAML config supplied in the - // `config` parameter. Any prior or subsequent calls to the EngineBuilder's APIs are ignored in - // favor of using the YAML string to construct the Envoy Engine's Bootsrap configuration. - // - // This method is protected so that production code does not rely on it. - // - // Tests that need access to this method should go through the TestEngineBuilder class, which - // provides access to this method. - EngineBuilder& setOverrideConfigForTests(std::string config); - private: struct NativeFilterConfig { NativeFilterConfig(std::string name, std::string typed_config) @@ -149,7 +139,6 @@ class EngineBuilder { std::string app_version_ = "unspecified"; std::string app_id_ = "unspecified"; std::string device_os_ = "unspecified"; - std::string config_override_for_tests_ = ""; int stream_idle_timeout_seconds_ = 15; int per_try_idle_timeout_seconds_ = 15; bool gzip_decompression_filter_ = true; diff --git a/mobile/test/cc/integration/lifetimes_test.cc b/mobile/test/cc/integration/lifetimes_test.cc index 61a0fed765e5..b5fc701c0825 100644 --- a/mobile/test/cc/integration/lifetimes_test.cc +++ b/mobile/test/cc/integration/lifetimes_test.cc @@ -1,4 +1,5 @@ #include "test/common/integration/test_engine_builder.h" +#include "test/test_common/utility.h" #include "absl/synchronization/notification.h" #include "gtest/gtest.h" @@ -90,7 +91,9 @@ void sendRequest(Platform::EngineSharedPtr engine, Status& status, void sendRequestEndToEnd() { TestEngineBuilder engine_builder; - Platform::EngineSharedPtr engine = engine_builder.createEngine(CONFIG); + auto bootstrap = std::make_unique(); + TestUtility::loadFromYaml(CONFIG, *bootstrap); + Platform::EngineSharedPtr engine = engine_builder.createEngine(std::move(bootstrap)); Status status; absl::Notification stream_complete; diff --git a/mobile/test/cc/integration/send_headers_test.cc b/mobile/test/cc/integration/send_headers_test.cc index 3dd1494baa25..b17ec5f9f650 100644 --- a/mobile/test/cc/integration/send_headers_test.cc +++ b/mobile/test/cc/integration/send_headers_test.cc @@ -1,4 +1,5 @@ #include "test/common/integration/test_engine_builder.h" +#include "test/test_common/utility.h" #include "absl/synchronization/notification.h" #include "gtest/gtest.h" @@ -62,7 +63,9 @@ struct Status { TEST(SendHeadersTest, CanSendHeaders) { TestEngineBuilder engine_builder; - Platform::EngineSharedPtr engine = engine_builder.createEngine(CONFIG); + auto bootstrap = std::make_unique(); + TestUtility::loadFromYaml(CONFIG, *bootstrap); + Platform::EngineSharedPtr engine = engine_builder.createEngine(std::move(bootstrap)); Status status; absl::Notification stream_complete; diff --git a/mobile/test/common/integration/base_client_integration_test.cc b/mobile/test/common/integration/base_client_integration_test.cc index dd40c81b12d5..5830b8d82972 100644 --- a/mobile/test/common/integration/base_client_integration_test.cc +++ b/mobile/test/common/integration/base_client_integration_test.cc @@ -79,15 +79,16 @@ Platform::LogLevel getPlatformLogLevelFromOptions() { // Use the Envoy mobile default config as much as possible in this test. // There are some config modifiers below which do result in deltas. // Note: This function is only used to build the Engine if `override_builder_config_` is true. -std::string defaultConfig() { +envoy::config::bootstrap::v3::Bootstrap defaultConfig() { Platform::EngineBuilder builder; std::unique_ptr bootstrap = builder.generateBootstrap(); - return MessageUtil::getYamlStringFromMessage(*bootstrap); + envoy::config::bootstrap::v3::Bootstrap to_return = *bootstrap; + return to_return; } -BaseClientIntegrationTest::BaseClientIntegrationTest(Network::Address::IpVersion ip_version, - const std::string& bootstrap_config) - : BaseIntegrationTest(ip_version, bootstrap_config) { +BaseClientIntegrationTest::BaseClientIntegrationTest(Network::Address::IpVersion ip_version) + : BaseIntegrationTest(BaseIntegrationTest::defaultAddressFunction(ip_version), ip_version, + defaultConfig()) { skip_tag_extraction_rule_check_ = true; full_dispatcher_ = api_->allocateDispatcher("fake_envoy_mobile"); use_lds_ = false; @@ -204,7 +205,8 @@ void BaseClientIntegrationTest::createEnvoy() { finalizeConfigWithPorts(config_helper_, ports, use_lds_); ASSERT_FALSE(config_helper_.bootstrap().has_admin()) << "Bootstrap config should not have `admin` configured in Envoy Mobile"; - builder_.setOverrideConfig(MessageUtil::getYamlStringFromMessage(config_helper_.bootstrap())); + builder_.setOverrideConfig( + std::make_unique(config_helper_.bootstrap())); } else { ENVOY_LOG_MISC(warn, "Using builder config and ignoring config modifiers"); } diff --git a/mobile/test/common/integration/base_client_integration_test.h b/mobile/test/common/integration/base_client_integration_test.h index 31143e94c64f..b52030bfb663 100644 --- a/mobile/test/common/integration/base_client_integration_test.h +++ b/mobile/test/common/integration/base_client_integration_test.h @@ -29,7 +29,7 @@ Http::ResponseHeaderMapPtr toResponseHeaders(envoy_headers headers); // Creates a default bootstrap config from the EngineBuilder. // Only used to build the Engine if `override_builder_config_` is set to true. -std::string defaultConfig(); +envoy::config::bootstrap::v3::Bootstrap defaultConfig(); // A base class for Envoy Mobile client integration tests which interact with Envoy through the // Http::Client class. @@ -38,8 +38,7 @@ std::string defaultConfig(); // into a test lib. class BaseClientIntegrationTest : public BaseIntegrationTest { public: - BaseClientIntegrationTest(Network::Address::IpVersion ip_version, - const std::string& bootstrap_config = defaultConfig()); + BaseClientIntegrationTest(Network::Address::IpVersion ip_version); virtual ~BaseClientIntegrationTest() = default; // Note: This class does not inherit from testing::Test and so this TearDown() method // does not override testing::Test::TearDown(). As a result, it will not be called diff --git a/mobile/test/common/integration/test_engine_builder.cc b/mobile/test/common/integration/test_engine_builder.cc index 2292457fceaf..c81c77166eb2 100644 --- a/mobile/test/common/integration/test_engine_builder.cc +++ b/mobile/test/common/integration/test_engine_builder.cc @@ -4,18 +4,15 @@ namespace Envoy { -Platform::EngineSharedPtr TestEngineBuilder::createEngine(std::string config) { +Platform::EngineSharedPtr +TestEngineBuilder::createEngine(std::unique_ptr config) { absl::Notification engine_running; - Platform::EngineSharedPtr engine = setOverrideConfigForTests(std::move(config)) - .addLogLevel(Platform::LogLevel::debug) + setOverrideConfig(std::move(config)); + Platform::EngineSharedPtr engine = addLogLevel(Platform::LogLevel::debug) .setOnEngineRunning([&]() { engine_running.Notify(); }) .build(); engine_running.WaitForNotification(); return engine; } -void TestEngineBuilder::setOverrideConfig(std::string config) { - setOverrideConfigForTests(std::move(config)); -} - } // namespace Envoy diff --git a/mobile/test/common/integration/test_engine_builder.h b/mobile/test/common/integration/test_engine_builder.h index 3b0f67ce8d57..1c969046249d 100644 --- a/mobile/test/common/integration/test_engine_builder.h +++ b/mobile/test/common/integration/test_engine_builder.h @@ -6,18 +6,33 @@ namespace Envoy { // A wrapper class around EngineBuilder, specifically for mobile tests. // -// Mobile tests often supply their own YAML configuration for convenience, instead of using the +// Mobile tests often supply their own configuration for convenience, instead of using the // EngineBuilder APIs. This wrapper class builds an Envoy Mobile Engine with the ability to // access setOverrideConfigForTests(), which is a protected method inside EngineBuilder. class TestEngineBuilder : public Platform::EngineBuilder { public: + virtual ~TestEngineBuilder() {} + // Creates an Envoy Engine from the provided config and waits until the engine is running before // returning the Engine as a shared_ptr. - Platform::EngineSharedPtr createEngine(std::string config); + Platform::EngineSharedPtr + createEngine(std::unique_ptr config); // Overrides the EngineBuilder's config with the provided string. Calls to the EngineBuilder's // bootstrap modifying APIs do not take effect after this function is called. - void setOverrideConfig(std::string config); + void setOverrideConfig(std::unique_ptr&& config) { + override_bootstrap_ = std::move(config); + } + + std::unique_ptr generateBootstrap() const override { + if (override_bootstrap_ != nullptr) { + return std::make_unique(*override_bootstrap_); + } + return Platform::EngineBuilder::generateBootstrap(); + } + +private: + std::unique_ptr override_bootstrap_; }; } // namespace Envoy diff --git a/test/config/utility.cc b/test/config/utility.cc index e2621357519f..ab1d97d89575 100644 --- a/test/config/utility.cc +++ b/test/config/utility.cc @@ -30,6 +30,13 @@ #include "gtest/gtest.h" namespace Envoy { +namespace { +envoy::config::bootstrap::v3::Bootstrap& +basicBootstrap(envoy::config::bootstrap::v3::Bootstrap& bootstrap, const std::string& config) { + TestUtility::loadFromYaml(config, bootstrap); + return bootstrap; +} +} // namespace std::string ConfigHelper::baseConfigNoListeners() { return fmt::format(R"EOF( @@ -721,11 +728,14 @@ envoy::config::endpoint::v3::Endpoint ConfigHelper::buildEndpoint(const std::str return endpoint; } -ConfigHelper::ConfigHelper(const Network::Address::IpVersion version, Api::Api& api, - const std::string& config) { +ConfigHelper::ConfigHelper(const Network::Address::IpVersion version, Api::Api&, + const std::string& config) + : ConfigHelper(version, basicBootstrap(bootstrap_, config)) {} + +ConfigHelper::ConfigHelper(const Network::Address::IpVersion version, + const envoy::config::bootstrap::v3::Bootstrap& bootstrap) { RELEASE_ASSERT(!finalized_, ""); - std::string filename = TestEnvironment::writeStringToFileForTest("basic_config.yaml", config); - TestUtility::loadFromFile(filename, bootstrap_, api); + bootstrap_ = bootstrap; // Fix up all the socket addresses with the correct version. auto* admin = bootstrap_.mutable_admin(); diff --git a/test/config/utility.h b/test/config/utility.h index dce790b7463f..61c7ee881a75 100644 --- a/test/config/utility.h +++ b/test/config/utility.h @@ -139,12 +139,16 @@ class ConfigHelper { absl::optional max_verify_depth_{absl::nullopt}; }; + // Sets up config with the provided bootstrap. + ConfigHelper(const Network::Address::IpVersion version, + const envoy::config::bootstrap::v3::Bootstrap& bootstrap); + // Set up basic config, using the specified IpVersion for all connections: listeners, upstream, // and admin connections. // // By default, this runs with an L7 proxy config, but config can be set to TCP_PROXY_CONFIG // to test L4 proxying. - ConfigHelper(const Network::Address::IpVersion version, Api::Api& api, + ConfigHelper(const Network::Address::IpVersion version, Api::Api&, const std::string& config = httpProxyConfig(false, false)); static void diff --git a/test/extensions/access_loggers/grpc/http_grpc_access_log_integration_test.cc b/test/extensions/access_loggers/grpc/http_grpc_access_log_integration_test.cc index 07e6d7a5191a..3cd94ec56378 100644 --- a/test/extensions/access_loggers/grpc/http_grpc_access_log_integration_test.cc +++ b/test/extensions/access_loggers/grpc/http_grpc_access_log_integration_test.cc @@ -331,8 +331,7 @@ TEST_P(AccessLogIntegrationTest, GrpcLoggerSurvivesAfterReloadConfig) { test_server_->waitForCounterEq("access_logs.grpc_access_log.logs_written", 2); // Create a new config with HTTP/1.0 proxying. The goal is to trigger a listener update. - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& hcm) { diff --git a/test/extensions/bootstrap/internal_listener/internal_listener_integration_test.cc b/test/extensions/bootstrap/internal_listener/internal_listener_integration_test.cc index 72e54fdc495c..b1a36c24b443 100644 --- a/test/extensions/bootstrap/internal_listener/internal_listener_integration_test.cc +++ b/test/extensions/bootstrap/internal_listener/internal_listener_integration_test.cc @@ -45,8 +45,7 @@ TEST_P(InternalListenerIntegrationTest, BasicConfigUpdate) { initialize(); EXPECT_EQ(1, test_server_->counter("listener_manager.lds.update_success")->value()); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -66,8 +65,7 @@ TEST_P(InternalListenerIntegrationTest, InplaceUpdate) { initialize(); EXPECT_EQ(1, test_server_->counter("listener_manager.lds.update_success")->value()); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -90,8 +88,7 @@ TEST_P(InternalListenerIntegrationTest, DeleteListener) { initialize(); EXPECT_EQ(1, test_server_->counter("listener_manager.lds.update_success")->value()); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { bootstrap.mutable_static_resources()->mutable_listeners()->RemoveLast(); diff --git a/test/extensions/filters/http/tap/tap_filter_integration_test.cc b/test/extensions/filters/http/tap/tap_filter_integration_test.cc index af716d2917da..4fb6ae65c707 100644 --- a/test/extensions/filters/http/tap/tap_filter_integration_test.cc +++ b/test/extensions/filters/http/tap/tap_filter_integration_test.cc @@ -428,8 +428,7 @@ config_id: test_config_id startAdminRequest(admin_request_yaml); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.prependFilter(admin_filter_config_); new_config_helper.renameListener("foo"); new_config_helper.setLds("1"); diff --git a/test/integration/base_integration_test.cc b/test/integration/base_integration_test.cc index 4b45cb7e0f39..a90bf2210a43 100644 --- a/test/integration/base_integration_test.cc +++ b/test/integration/base_integration_test.cc @@ -29,6 +29,12 @@ #include "gtest/gtest.h" namespace Envoy { +envoy::config::bootstrap::v3::Bootstrap configToBootstrap(const std::string& config) { + envoy::config::bootstrap::v3::Bootstrap bootstrap; + TestUtility::loadFromYaml(config, bootstrap); + return bootstrap; +} + using ::testing::_; using ::testing::AssertionFailure; using ::testing::AssertionResult; @@ -40,13 +46,13 @@ using ::testing::ReturnRef; BaseIntegrationTest::BaseIntegrationTest(const InstanceConstSharedPtrFn& upstream_address_fn, Network::Address::IpVersion version, - const std::string& config) + const envoy::config::bootstrap::v3::Bootstrap& bootstrap) : api_(Api::createApiForTest(stats_store_, time_system_)), mock_buffer_factory_(new NiceMock), dispatcher_(api_->allocateDispatcher("test_thread", Buffer::WatermarkFactoryPtr{mock_buffer_factory_})), version_(version), upstream_address_fn_(upstream_address_fn), - config_helper_(version, *api_, config), + config_helper_(version, bootstrap), default_log_level_(TestEnvironment::getOptions().logLevel()) { Envoy::Server::validateProtoDescriptors(); // This is a hack, but there are situations where we disconnect fake upstream connections and @@ -73,14 +79,22 @@ BaseIntegrationTest::BaseIntegrationTest(const InstanceConstSharedPtrFn& upstrea #endif } +BaseIntegrationTest::BaseIntegrationTest(const InstanceConstSharedPtrFn& upstream_address_fn, + Network::Address::IpVersion version, + const std::string& config) + : BaseIntegrationTest(upstream_address_fn, version, configToBootstrap(config)) {} + +const BaseIntegrationTest::InstanceConstSharedPtrFn +BaseIntegrationTest::defaultAddressFunction(Network::Address::IpVersion version) { + return [version](int) { + return Network::Utility::parseInternetAddress(Network::Test::getLoopbackAddressString(version), + 0); + }; +} + BaseIntegrationTest::BaseIntegrationTest(Network::Address::IpVersion version, const std::string& config) - : BaseIntegrationTest( - [version](int) { - return Network::Utility::parseInternetAddress( - Network::Test::getLoopbackAddressString(version), 0); - }, - version, config) {} + : BaseIntegrationTest(defaultAddressFunction(version), version, config) {} Network::ClientConnectionPtr BaseIntegrationTest::makeClientConnection(uint32_t port) { return makeClientConnectionWithOptions(port, nullptr); diff --git a/test/integration/base_integration_test.h b/test/integration/base_integration_test.h index ae18ad704c5e..fddd40fbff4e 100644 --- a/test/integration/base_integration_test.h +++ b/test/integration/base_integration_test.h @@ -66,7 +66,11 @@ struct ApiFilesystemConfig { class BaseIntegrationTest : protected Logger::Loggable { public: using InstanceConstSharedPtrFn = std::function; + static const InstanceConstSharedPtrFn defaultAddressFunction(Network::Address::IpVersion version); + BaseIntegrationTest(const InstanceConstSharedPtrFn& upstream_address_fn, + Network::Address::IpVersion version, + const envoy::config::bootstrap::v3::Bootstrap& bootstrap); // Creates a test fixture with an upstream bound to INADDR_ANY on an unspecified port using the // provided IP |version|. BaseIntegrationTest(Network::Address::IpVersion version, diff --git a/test/integration/listener_lds_integration_test.cc b/test/integration/listener_lds_integration_test.cc index cb34ae5d9dee..d72316ad2fcc 100644 --- a/test/integration/listener_lds_integration_test.cc +++ b/test/integration/listener_lds_integration_test.cc @@ -1718,8 +1718,7 @@ TEST_P(RebalancerTest, BindToPortUpdate) { concurrency_ = 2; initialize(); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { diff --git a/test/integration/multi_envoy_test.cc b/test/integration/multi_envoy_test.cc index d050705f6fe5..3d37290cc474 100644 --- a/test/integration/multi_envoy_test.cc +++ b/test/integration/multi_envoy_test.cc @@ -28,8 +28,7 @@ void MultiEnvoyTest::createL1Envoy() { zero.push_back(0); } } - ConfigHelper l1_helper(version_, *api_, - MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper l1_helper(version_, config_helper_.bootstrap()); l1_helper.setPorts(zero, true); // Zero out ports set by config_helper_'s finalize(); const std::string bootstrap_path = finalizeConfigWithPorts(l1_helper, ports, use_lds_); diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 3fadbfd2af8b..cb506c233f37 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -1489,8 +1489,7 @@ TEST_P(QuicInplaceLdsIntegrationTest, ReloadConfigUpdateNonDefaultFilterChain) { makeHttpConnection(makeClientConnectionWithHost(lookupPort("http"), "lyft.com")); // Remove filter_chain_1. - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -1532,8 +1531,7 @@ TEST_P(QuicInplaceLdsIntegrationTest, ReloadConfigUpdateDefaultFilterChain) { makeHttpConnection(makeClientConnectionWithHost(lookupPort("http"), "www.lyft.com")); // Remove filter_chain_1. - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -1552,8 +1550,7 @@ TEST_P(QuicInplaceLdsIntegrationTest, ReloadConfigUpdateDefaultFilterChain) { makeRequestAndWaitForResponse(*codec_client_0); // Modify the default filter chain. - ConfigHelper new_config_helper1( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(new_config_helper.bootstrap())); + ConfigHelper new_config_helper1(version_, new_config_helper.bootstrap()); new_config_helper1.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto default_filter_chain = @@ -1576,9 +1573,7 @@ TEST_P(QuicInplaceLdsIntegrationTest, ReloadConfigUpdateDefaultFilterChain) { makeRequestAndWaitForResponse(*codec_client_1); // Remove the default filter chain. - ConfigHelper new_config_helper2( - version_, *api_, - MessageUtil::getJsonStringFromMessageOrError(new_config_helper1.bootstrap())); + ConfigHelper new_config_helper2(version_, config_helper_.bootstrap()); new_config_helper2.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -1607,8 +1602,7 @@ TEST_P(QuicInplaceLdsIntegrationTest, EnableAndDisableEarlyData) { codec_client_0->close(); // Modify 1st transport socket factory to disable early data. - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addQuicDownstreamTransportSocketConfig(/*enable_early_data=*/false); new_config_helper.setLds("1"); diff --git a/test/integration/tcp_tunneling_integration_test.cc b/test/integration/tcp_tunneling_integration_test.cc index 742e34eb17d5..2b2220997f72 100644 --- a/test/integration/tcp_tunneling_integration_test.cc +++ b/test/integration/tcp_tunneling_integration_test.cc @@ -955,8 +955,7 @@ TEST_P(TcpTunnelingIntegrationTest, HeaderEvaluatorConfigUpdate) { ASSERT_TRUE(tcp_client_->write("hello", false)); ASSERT_TRUE(upstream_request_->waitForData(*dispatcher_, 5)); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* header = diff --git a/test/integration/xds_integration_test.cc b/test/integration/xds_integration_test.cc index 41ee5759b0ef..c244d1313694 100644 --- a/test/integration/xds_integration_test.cc +++ b/test/integration/xds_integration_test.cc @@ -235,8 +235,7 @@ TEST_P(LdsInplaceUpdateTcpProxyIntegrationTest, ReloadConfigDeletingFilterChain) FakeRawConnectionPtr fake_upstream_connection_1; ASSERT_TRUE(fake_upstreams_[1]->waitForRawConnection(fake_upstream_connection_1)); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -295,8 +294,7 @@ TEST_P(LdsInplaceUpdateTcpProxyIntegrationTest, ReloadConfigAddingFilterChain) { FakeRawConnectionPtr fake_upstream_connection_0; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection_0)); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -520,8 +518,7 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, ReloadConfigDeletingFilterChain) { auto codec_client_0 = createHttpCodec("alpn0"); auto codec_client_default = createHttpCodec("alpndefault"); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -559,8 +556,7 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, ReloadConfigAddingFilterChain) { Cleanup cleanup0([c0 = codec_client_0.get()]() { c0->close(); }); test_server_->waitForGaugeGe("http.hcm0.downstream_cx_active", 1); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -604,8 +600,7 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, ReloadConfigUpdatingDefaultFilterCha auto codec_client_default = createHttpCodec("alpndefault"); Cleanup cleanup0([c_default = codec_client_default.get()]() { c_default->close(); }); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto default_filter_chain = @@ -632,8 +627,7 @@ TEST_P(LdsInplaceUpdateHttpIntegrationTest, OverlappingFilterChainServesNewConne auto codec_client_0 = createHttpCodec("alpn0"); Cleanup cleanup([c0 = codec_client_0.get()]() { c0->close(); }); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -680,8 +674,7 @@ TEST_P(LdsIntegrationTest, ReloadConfig) { EXPECT_TRUE(response.find("HTTP/1.1 426 Upgrade Required\r\n") == 0); // Create a new config with HTTP/1.0 proxying. - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& hcm) { @@ -712,8 +705,7 @@ TEST_P(LdsIntegrationTest, NewListenerWithBadPostListenSocketOption) { // Reserve a port that we can then use on the integration listener with reuse_port. auto addr_socket = Network::Test::bindFreeLoopbackPort(version_, Network::Socket::Type::Stream, true); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* new_listener = bootstrap.mutable_static_resources()->add_listeners(); @@ -764,8 +756,7 @@ TEST_P(LdsStsIntegrationTest, DISABLED_TcpListenerRemoveFilterChainCalledAfterLi FakeRawConnectionPtr fake_upstream_connection_0; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection_0)); - ConfigHelper new_config_helper( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); + ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); new_config_helper.addConfigModifier( [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { auto* listener = bootstrap.mutable_static_resources()->mutable_listeners(0); @@ -775,28 +766,7 @@ TEST_P(LdsStsIntegrationTest, DISABLED_TcpListenerRemoveFilterChainCalledAfterLi // 2. Remove the tcp listener immediately. This listener update should stack in the same poller // cycle so that this listener update has the same time stamp as the first update. - ConfigHelper new_config_helper1( - version_, *api_, MessageUtil::getJsonStringFromMessageOrError(config_helper_.bootstrap())); - new_config_helper1.addConfigModifier( - [&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void { - bootstrap.mutable_static_resources()->mutable_listeners(0)->Swap( - bootstrap.mutable_static_resources()->mutable_listeners(1)); - bootstrap.mutable_static_resources()->mutable_listeners()->RemoveLast(); - }); - new_config_helper1.setLds("2"); - - std::string observed_data_0; - ASSERT_TRUE(fake_upstream_connection_0->waitForData(5, &observed_data_0)); - EXPECT_EQ("hello", observed_data_0); - - ASSERT_TRUE(fake_upstream_connection_0->write("world")); - while (response_0.find("world") == std::string::npos) { - ASSERT_TRUE(client_conn_0->run(Event::Dispatcher::RunType::NonBlock)); - } - // Wait for the filter chain removal start. - test_server_->waitForGaugeEq("listener_manager.total_filter_chains_draining", 1); - - client_conn_0->close(); + ConfigHelper new_config_helper1(version_, config_helper_.bootstrap()); while (!client_conn_0->closed()) { dispatcher_->run(Event::Dispatcher::RunType::NonBlock); } From 19231ba2b311a115ba85391a18dc73370e1f28d3 Mon Sep 17 00:00:00 2001 From: DiazAlan <109677874+DiazAlan@users.noreply.github.com> Date: Wed, 24 May 2023 13:05:33 -0400 Subject: [PATCH 077/228] Add "Internal" flag to Metric::Flags to allow the ForEach loop to ignore or skip metrics with that flag set (#27293) Creates a special flag "hidden" to use in Metrics. This will allow the ForEach Loops for different metrics to check for this flag and skip flags that have this set. Currently only Gauge has this implemented to help close this PR 23921. Signed-off-by: AlanDiaz --- envoy/stats/stats.h | 9 +++ source/common/stats/allocator_impl.cc | 14 +++++ source/common/stats/histogram_impl.h | 2 + source/common/stats/null_counter.h | 1 + source/common/stats/null_gauge.h | 1 + source/common/stats/null_text_readout.h | 1 + source/common/stats/thread_local_store.cc | 12 +++- source/common/stats/thread_local_store.h | 2 + test/common/stats/allocator_impl_test.cc | 17 +++++ test/common/stats/thread_local_store_test.cc | 66 ++++++++++++++++++++ test/integration/server.h | 1 + test/mocks/stats/mocks.cc | 4 ++ test/mocks/stats/mocks.h | 9 +++ 13 files changed, 137 insertions(+), 2 deletions(-) diff --git a/envoy/stats/stats.h b/envoy/stats/stats.h index 9db2c9dbcac9..cdc1ba896c9b 100644 --- a/envoy/stats/stats.h +++ b/envoy/stats/stats.h @@ -92,6 +92,11 @@ class Metric : public RefcountInterface { */ virtual bool used() const PURE; + /** + * Indicates whether this metric is hidden. + */ + virtual bool hidden() const PURE; + /** * Flags: * Used: used by all stats types to figure out whether they have been used. @@ -101,6 +106,7 @@ class Metric : public RefcountInterface { static constexpr uint8_t Used = 0x01; static constexpr uint8_t LogicAccumulate = 0x02; static constexpr uint8_t NeverImport = 0x04; + static constexpr uint8_t Hidden = 0x08; }; virtual SymbolTable& symbolTable() PURE; virtual const SymbolTable& constSymbolTable() const PURE; @@ -129,10 +135,13 @@ using CounterSharedPtr = RefcountPtr; */ class Gauge : public Metric { public: + // TODO(diazalan): Rename ImportMode to more generic name enum class ImportMode { Uninitialized, // Gauge was discovered during hot-restart transfer. NeverImport, // On hot-restart, each process starts with gauge at 0. Accumulate, // Transfers gauge state on hot-restart. + // TODO(Diazalan): Add functionality for Hidden to be ignored by admin/stats-sink + HiddenAccumulate, // Will be transferred on hot-restart and ignored by admin/stats-sink }; ~Gauge() override = default; diff --git a/source/common/stats/allocator_impl.cc b/source/common/stats/allocator_impl.cc index f69166acdcd2..a8c9745461c2 100644 --- a/source/common/stats/allocator_impl.cc +++ b/source/common/stats/allocator_impl.cc @@ -85,6 +85,7 @@ template class StatsSharedImpl : public MetricImpl // Metric SymbolTable& symbolTable() final { return alloc_.symbolTable(); } bool used() const override { return flags_ & Metric::Flags::Used; } + bool hidden() const override { return flags_ & Metric::Flags::Hidden; } // RefcountInterface void incRefCount() override { ++ref_count_; } @@ -183,6 +184,10 @@ class GaugeImpl : public StatsSharedImpl { // an alternate scope. See // https://github.com/envoyproxy/envoy/issues/7227. break; + case ImportMode::HiddenAccumulate: + flags_ |= Flags::Hidden; + flags_ |= Flags::LogicAccumulate; + break; } } @@ -210,15 +215,19 @@ class GaugeImpl : public StatsSharedImpl { } uint64_t value() const override { return child_value_ + parent_value_; } + // TODO(diazalan): Rename importMode and to more generic name ImportMode importMode() const override { if (flags_ & Flags::NeverImport) { return ImportMode::NeverImport; + } else if ((flags_ & Flags::Hidden) && (flags_ & Flags::LogicAccumulate)) { + return ImportMode::HiddenAccumulate; } else if (flags_ & Flags::LogicAccumulate) { return ImportMode::Accumulate; } return ImportMode::Uninitialized; } + // TODO(diazalan): Rename mergeImportMode and to more generic name void mergeImportMode(ImportMode import_mode) override { ImportMode current = importMode(); if (current == import_mode) { @@ -243,6 +252,11 @@ class GaugeImpl : public StatsSharedImpl { flags_ &= ~Flags::Used; flags_ |= Flags::NeverImport; break; + case ImportMode::HiddenAccumulate: + ASSERT(current == ImportMode::Uninitialized); + flags_ |= Flags::Hidden; + flags_ |= Flags::LogicAccumulate; + break; } } diff --git a/source/common/stats/histogram_impl.h b/source/common/stats/histogram_impl.h index da49db9a436f..32a47980735b 100644 --- a/source/common/stats/histogram_impl.h +++ b/source/common/stats/histogram_impl.h @@ -109,6 +109,7 @@ class HistogramImpl : public HistogramImplHelper { void recordValue(uint64_t value) override { parent_.deliverHistogramToSinks(*this, value); } bool used() const override { return true; } + bool hidden() const override { return false; } SymbolTable& symbolTable() final { return parent_.symbolTable(); } private: @@ -129,6 +130,7 @@ class NullHistogramImpl : public HistogramImplHelper { ~NullHistogramImpl() override { MetricImpl::clear(symbol_table_); } bool used() const override { return false; } + bool hidden() const override { return false; } SymbolTable& symbolTable() override { return symbol_table_; } Unit unit() const override { return Unit::Null; }; diff --git a/source/common/stats/null_counter.h b/source/common/stats/null_counter.h index 074349125a3f..ca576310f0d7 100644 --- a/source/common/stats/null_counter.h +++ b/source/common/stats/null_counter.h @@ -31,6 +31,7 @@ class NullCounterImpl : public MetricImpl { // Metric bool used() const override { return false; } + bool hidden() const override { return false; } SymbolTable& symbolTable() override { return symbol_table_; } // RefcountInterface diff --git a/source/common/stats/null_gauge.h b/source/common/stats/null_gauge.h index 2c12f923aeda..5af09aa5999e 100644 --- a/source/common/stats/null_gauge.h +++ b/source/common/stats/null_gauge.h @@ -35,6 +35,7 @@ class NullGaugeImpl : public MetricImpl { // Metric bool used() const override { return false; } + bool hidden() const override { return false; } SymbolTable& symbolTable() override { return symbol_table_; } // RefcountInterface diff --git a/source/common/stats/null_text_readout.h b/source/common/stats/null_text_readout.h index 0cde15ab5611..3073fa8182b4 100644 --- a/source/common/stats/null_text_readout.h +++ b/source/common/stats/null_text_readout.h @@ -28,6 +28,7 @@ class NullTextReadoutImpl : public MetricImpl { // Metric bool used() const override { return false; } + bool hidden() const override { return false; } SymbolTable& symbolTable() override { return symbol_table_; } // RefcountInterface diff --git a/source/common/stats/thread_local_store.cc b/source/common/stats/thread_local_store.cc index aee9013d31d0..387cf8ea89d2 100644 --- a/source/common/stats/thread_local_store.cc +++ b/source/common/stats/thread_local_store.cc @@ -585,7 +585,8 @@ void ThreadLocalStoreImpl::deliverHistogramToSinks(const Histogram& histogram, u Gauge& ThreadLocalStoreImpl::ScopeImpl::gaugeFromStatNameWithTags( const StatName& name, StatNameTagVectorOptConstRef stat_name_tags, Gauge::ImportMode import_mode) { - if (parent_.rejectsAll()) { + // If a gauge is "hidden" it should not be rejected as these are used for deferred stats. + if (parent_.rejectsAll() && import_mode != Gauge::ImportMode::HiddenAccumulate) { return parent_.null_gauge_; } @@ -594,7 +595,12 @@ Gauge& ThreadLocalStoreImpl::ScopeImpl::gaugeFromStatNameWithTags( TagUtility::TagStatNameJoiner joiner(prefix_.statName(), name, stat_name_tags, symbolTable()); StatName final_stat_name = joiner.nameWithTags(); - StatsMatcher::FastResult fast_reject_result = parent_.fastRejects(final_stat_name); + StatsMatcher::FastResult fast_reject_result; + if (import_mode != Gauge::ImportMode::HiddenAccumulate) { + fast_reject_result = parent_.fastRejects(final_stat_name); + } else { + fast_reject_result = StatsMatcher::FastResult::Matches; + } if (fast_reject_result == StatsMatcher::FastResult::Rejects) { return parent_.null_gauge_; } @@ -906,6 +912,8 @@ bool ParentHistogramImpl::used() const { return merged_; } +bool ParentHistogramImpl::hidden() const { return false; } + void ParentHistogramImpl::merge() { Thread::ReleasableLockGuard lock(merge_lock_); if (merged_ || usedLockHeld()) { diff --git a/source/common/stats/thread_local_store.h b/source/common/stats/thread_local_store.h index 46bd0afa1032..081aee90fbe4 100644 --- a/source/common/stats/thread_local_store.h +++ b/source/common/stats/thread_local_store.h @@ -60,6 +60,7 @@ class ThreadLocalHistogramImpl : public HistogramImplHelper { // Stats::Metric SymbolTable& symbolTable() final { return symbol_table_; } bool used() const override { return used_; } + bool hidden() const override { return false; } private: Histogram::Unit unit_; @@ -115,6 +116,7 @@ class ParentHistogramImpl : public MetricImpl { // Stats::Metric SymbolTable& symbolTable() override; bool used() const override; + bool hidden() const override; // RefcountInterface void incRefCount() override; diff --git a/test/common/stats/allocator_impl_test.cc b/test/common/stats/allocator_impl_test.cc index bbb0da55f25e..eea975dcb3ea 100644 --- a/test/common/stats/allocator_impl_test.cc +++ b/test/common/stats/allocator_impl_test.cc @@ -139,6 +139,23 @@ TEST_F(AllocatorImplTest, RefCountDecAllocRaceSynchronized) { EXPECT_FALSE(alloc_.isMutexLockedForTest()); } +TEST_F(AllocatorImplTest, HiddenGauge) { + GaugeSharedPtr hidden_gauge = + alloc_.makeGauge(makeStat("hidden"), StatName(), {}, Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ(hidden_gauge->importMode(), Gauge::ImportMode::HiddenAccumulate); + EXPECT_TRUE(hidden_gauge->hidden()); + + GaugeSharedPtr non_hidden_gauge = + alloc_.makeGauge(makeStat("non_hidden"), StatName(), {}, Gauge::ImportMode::Accumulate); + EXPECT_NE(non_hidden_gauge->importMode(), Gauge::ImportMode::HiddenAccumulate); + EXPECT_FALSE(non_hidden_gauge->hidden()); + + GaugeSharedPtr never_import_hidden_gauge = alloc_.makeGauge( + makeStat("never_import_hidden"), StatName(), {}, Gauge::ImportMode::NeverImport); + EXPECT_NE(never_import_hidden_gauge->importMode(), Gauge::ImportMode::HiddenAccumulate); + EXPECT_FALSE(never_import_hidden_gauge->hidden()); +} + TEST_F(AllocatorImplTest, ForEachCounter) { StatNameHashSet stat_names; std::vector counters; diff --git a/test/common/stats/thread_local_store_test.cc b/test/common/stats/thread_local_store_test.cc index 0363a4cd0219..9cd079074338 100644 --- a/test/common/stats/thread_local_store_test.cc +++ b/test/common/stats/thread_local_store_test.cc @@ -1149,6 +1149,72 @@ TEST_F(StatsMatcherTLSTest, RejectPrefixNoDot) { EXPECT_MEMORY_LE(mem_consumed, 3500000); } +TEST_F(StatsMatcherTLSTest, DoNotRejectHiddenPrefixExclusion) { + envoy::config::metrics::v3::StatsConfig stats_config_; + stats_config_.mutable_stats_matcher()->mutable_exclusion_list()->add_patterns()->set_prefix( + "cluster."); + store_->setStatsMatcher(std::make_unique(stats_config_, symbol_table_)); + + Gauge& accumulate_gauge = + scope_.gaugeFromString("cluster.accumulate_gauge", Gauge::ImportMode::Accumulate); + EXPECT_EQ(accumulate_gauge.name(), ""); + Gauge& hidden_gauge = + scope_.gaugeFromString("cluster.hidden_gauge", Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ(hidden_gauge.name(), "cluster.hidden_gauge"); +} + +TEST_F(StatsMatcherTLSTest, DoNotRejectHiddenPrefixInclusive) { + envoy::config::metrics::v3::StatsConfig stats_config_; + stats_config_.mutable_stats_matcher()->mutable_inclusion_list()->add_patterns()->set_prefix( + "cluster."); + store_->setStatsMatcher(std::make_unique(stats_config_, symbol_table_)); + + Gauge& accumulate_gauge = + scope_.gaugeFromString("accumulate_gauge", Gauge::ImportMode::Accumulate); + EXPECT_EQ(accumulate_gauge.name(), ""); + Gauge& hidden_gauge = scope_.gaugeFromString("hidden_gauge", Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ(hidden_gauge.name(), "hidden_gauge"); +} + +TEST_F(StatsMatcherTLSTest, DoNotRejectHiddenExclusionRegex) { + envoy::config::metrics::v3::StatsConfig stats_config_; + stats_config_.mutable_stats_matcher()->mutable_exclusion_list()->add_patterns()->MergeFrom( + TestUtility::createRegexMatcher(".*")); + store_->setStatsMatcher(std::make_unique(stats_config_, symbol_table_)); + + Gauge& accumulate_gauge = + scope_.gaugeFromString("accumulate_gauge", Gauge::ImportMode::Accumulate); + EXPECT_EQ(accumulate_gauge.name(), ""); + Gauge& hidden_gauge = scope_.gaugeFromString("hidden_gauge", Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ(hidden_gauge.name(), "hidden_gauge"); +} + +TEST_F(StatsMatcherTLSTest, DoNotRejectHiddenInclusionRegex) { + envoy::config::metrics::v3::StatsConfig stats_config_; + // Create inclusion list to only accept names that have at least one capital letter. + stats_config_.mutable_stats_matcher()->mutable_inclusion_list()->add_patterns()->MergeFrom( + TestUtility::createRegexMatcher(".*[A-Z].*")); + store_->setStatsMatcher(std::make_unique(stats_config_, symbol_table_)); + + Gauge& accumulate_gauge = + scope_.gaugeFromString("accumulate_gauge", Gauge::ImportMode::Accumulate); + EXPECT_EQ(accumulate_gauge.name(), ""); + Gauge& hidden_gauge = scope_.gaugeFromString("hidden_gauge", Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ(hidden_gauge.name(), "hidden_gauge"); +} + +TEST_F(StatsMatcherTLSTest, DoNotRejectAllHidden) { + envoy::config::metrics::v3::StatsConfig stats_config_; + stats_config_.mutable_stats_matcher()->set_reject_all(true); + store_->setStatsMatcher(std::make_unique(stats_config_, symbol_table_)); + + Gauge& accumulate_gauge = + scope_.gaugeFromString("accumulate_gauge", Gauge::ImportMode::Accumulate); + EXPECT_EQ(accumulate_gauge.name(), ""); + Gauge& hidden_gauge = scope_.gaugeFromString("hidden_gauge", Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ(hidden_gauge.name(), "hidden_gauge"); +} + // Tests the logic for caching the stats-matcher results, and in particular the // private impl method checkAndRememberRejection(). That method behaves // differently depending on whether TLS is enabled or not, so we parameterize diff --git a/test/integration/server.h b/test/integration/server.h index 657396ccf4eb..78b8e7c8b091 100644 --- a/test/integration/server.h +++ b/test/integration/server.h @@ -193,6 +193,7 @@ class NotifyingCounter : public Stats::Counter { uint32_t use_count() const override { return counter_->use_count(); } StatName tagExtractedStatName() const override { return counter_->tagExtractedStatName(); } bool used() const override { return counter_->used(); } + bool hidden() const override { return counter_->hidden(); } SymbolTable& symbolTable() override { return counter_->symbolTable(); } const SymbolTable& constSymbolTable() const override { return counter_->constSymbolTable(); } diff --git a/test/mocks/stats/mocks.cc b/test/mocks/stats/mocks.cc index b1239195c284..d0108548aaa8 100644 --- a/test/mocks/stats/mocks.cc +++ b/test/mocks/stats/mocks.cc @@ -19,6 +19,7 @@ namespace Stats { MockCounter::MockCounter() { ON_CALL(*this, used()).WillByDefault(ReturnPointee(&used_)); + ON_CALL(*this, hidden()).WillByDefault(ReturnPointee(&hidden_)); ON_CALL(*this, value()).WillByDefault(ReturnPointee(&value_)); ON_CALL(*this, latch()).WillByDefault(ReturnPointee(&latch_)); } @@ -26,6 +27,7 @@ MockCounter::~MockCounter() = default; MockGauge::MockGauge() : used_(false), value_(0), import_mode_(ImportMode::Accumulate) { ON_CALL(*this, used()).WillByDefault(ReturnPointee(&used_)); + ON_CALL(*this, hidden()).WillByDefault(ReturnPointee(&hidden_)); ON_CALL(*this, value()).WillByDefault(ReturnPointee(&value_)); ON_CALL(*this, importMode()).WillByDefault(ReturnPointee(&import_mode_)); } @@ -33,6 +35,7 @@ MockGauge::~MockGauge() = default; MockTextReadout::MockTextReadout() { ON_CALL(*this, used()).WillByDefault(ReturnPointee(&used_)); + ON_CALL(*this, hidden()).WillByDefault(ReturnPointee(&hidden_)); ON_CALL(*this, value()).WillByDefault(ReturnPointee(&value_)); } MockTextReadout::~MockTextReadout() = default; @@ -49,6 +52,7 @@ MockHistogram::~MockHistogram() = default; MockParentHistogram::MockParentHistogram() { ON_CALL(*this, used()).WillByDefault(ReturnPointee(&used_)); + ON_CALL(*this, hidden()).WillByDefault(ReturnPointee(&hidden_)); ON_CALL(*this, unit()).WillByDefault(ReturnPointee(&unit_)); ON_CALL(*this, recordValue(_)).WillByDefault(Invoke([this](uint64_t value) { if (store_ != nullptr) { diff --git a/test/mocks/stats/mocks.h b/test/mocks/stats/mocks.h index 2a145792f50c..008caa3d9f9f 100644 --- a/test/mocks/stats/mocks.h +++ b/test/mocks/stats/mocks.h @@ -142,9 +142,11 @@ class MockCounter : public MockStatWithRefcount { MOCK_METHOD(uint64_t, latch, ()); MOCK_METHOD(void, reset, ()); MOCK_METHOD(bool, used, (), (const)); + MOCK_METHOD(bool, hidden, (), (const)); MOCK_METHOD(uint64_t, value, (), (const)); bool used_; + bool hidden_; uint64_t value_; uint64_t latch_; }; @@ -162,11 +164,13 @@ class MockGauge : public MockStatWithRefcount { MOCK_METHOD(void, sub, (uint64_t amount)); MOCK_METHOD(void, mergeImportMode, (ImportMode)); MOCK_METHOD(bool, used, (), (const)); + MOCK_METHOD(bool, hidden, (), (const)); MOCK_METHOD(uint64_t, value, (), (const)); MOCK_METHOD(absl::optional, cachedShouldImport, (), (const)); MOCK_METHOD(ImportMode, importMode, (), (const)); bool used_; + bool hidden_; uint64_t value_; ImportMode import_mode_; }; @@ -177,6 +181,7 @@ class MockHistogram : public MockMetric { ~MockHistogram() override; MOCK_METHOD(bool, used, (), (const)); + MOCK_METHOD(bool, hidden, (), (const)); MOCK_METHOD(Histogram::Unit, unit, (), (const)); MOCK_METHOD(void, recordValue, (uint64_t value)); @@ -201,6 +206,7 @@ class MockParentHistogram : public MockMetric { std::string quantileSummary() const override { return ""; }; std::string bucketSummary() const override { return ""; }; MOCK_METHOD(bool, used, (), (const)); + MOCK_METHOD(bool, hidden, (), (const)); MOCK_METHOD(Histogram::Unit, unit, (), (const)); MOCK_METHOD(void, recordValue, (uint64_t value)); MOCK_METHOD(const HistogramStatistics&, cumulativeStatistics, (), (const)); @@ -214,6 +220,7 @@ class MockParentHistogram : public MockMetric { uint32_t use_count() const override { return refcount_helper_.use_count(); } bool used_; + bool hidden_; Unit unit_{Histogram::Unit::Unspecified}; Store* store_{}; std::shared_ptr histogram_stats_ = @@ -230,9 +237,11 @@ class MockTextReadout : public MockMetric { MOCK_METHOD(void, set, (absl::string_view value), (override)); MOCK_METHOD(bool, used, (), (const, override)); + MOCK_METHOD(bool, hidden, (), (const)); MOCK_METHOD(std::string, value, (), (const, override)); bool used_; + bool hidden_; std::string value_; }; From 5b270c2f2a14ea4eac609bf855edcb8c051c2a39 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 24 May 2023 21:52:39 +0100 Subject: [PATCH 078/228] ci/fuzz: Ensure fuzz check is included in code check (#27615) Signed-off-by: Ryan Northey --- .../filters/network/common/fuzz/config.bzl | 6 +++++- tools/base/requirements.in | 2 +- tools/base/requirements.txt | 6 +++--- tools/code/BUILD | 15 +++++++++++++-- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/test/extensions/filters/network/common/fuzz/config.bzl b/test/extensions/filters/network/common/fuzz/config.bzl index c275f3dfed79..44682ce1ad72 100644 --- a/test/extensions/filters/network/common/fuzz/config.bzl +++ b/test/extensions/filters/network/common/fuzz/config.bzl @@ -10,6 +10,10 @@ READFILTER_FUZZ_FILTERS = [ "envoy.filters.network.local_ratelimit", "envoy.filters.network.ratelimit", "envoy.filters.network.rbac", +] + +# These are marked as robust to downstream, but not currently fuzzed +READFILTER_NOFUZZ_FILTERS = [ # TODO(asraa): Remove when fuzzer sets up connections for TcpProxy properly. - # "envoy.filters.network.tcp_proxy", + "envoy.filters.network.tcp_proxy", ] diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 361ce48bf0bd..69fd8d5d441f 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -6,7 +6,7 @@ colorama coloredlogs dependatool>=0.2.2 envoy.base.utils>=0.4.10 -envoy.code.check>=0.5.1 +envoy.code.check>=0.5.4 envoy.dependency.check>=0.1.7 envoy.distribution.release>=0.0.9 envoy.distribution.repo>=0.0.8 diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 34743052ec71..ab3a456306a0 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -434,9 +434,9 @@ envoy-base-utils==0.4.11 \ # envoy-docs-sphinx-runner # envoy-github-release # envoy-gpg-sign -envoy-code-check==0.5.1 \ - --hash=sha256:379162ed8d83c9cb045917269b58f6e59812523359d8b0772b35078ab06dc8c1 \ - --hash=sha256:4b2b11b4fff634f1268b8dfb754c1d99300b8e58f5bc4276c96a8eb30cb9cea6 +envoy-code-check==0.5.4 \ + --hash=sha256:b3c338a0e607960ea75eb8298e786548d317655ac4c89d89b259395684eaf134 \ + --hash=sha256:ec919ea1e5523c5ad669f6601bb58c8da77bc1891c8846950add3b563c629ac5 # via -r requirements.in envoy-dependency-check==0.1.8 \ --hash=sha256:ac9820e446bb44e05121e5c93c210f40ca37076580b0d082da2c63e7784c338a \ diff --git a/tools/code/BUILD b/tools/code/BUILD index 1af762c87d1d..1b800c6a6dee 100644 --- a/tools/code/BUILD +++ b/tools/code/BUILD @@ -5,12 +5,18 @@ load("@aspect_bazel_lib//lib:jq.bzl", "jq") load( "//test/extensions/filters/network/common/fuzz:config.bzl", "READFILTER_FUZZ_FILTERS", + "READFILTER_NOFUZZ_FILTERS", ) licenses(["notice"]) # Apache 2 envoy_package() +FUZZ_FILTER_COUNT = ( + len(READFILTER_FUZZ_FILTERS) + + len(READFILTER_NOFUZZ_FILTERS) +) + jq( name = "extensions_build_config", srcs = [ @@ -26,7 +32,7 @@ envoy_entry_point( name = "check", args = [ "--extensions_build_config=$(location :extensions_build_config)", - "--extensions_fuzzed_count=%s" % len(READFILTER_FUZZ_FILTERS), + "--extensions_fuzzed_count=%s" % FUZZ_FILTER_COUNT, "--path=%s" % PATH, "-b shellcheck:$(location @com_github_aignas_rules_shellcheck//:shellcheck)", "-b gofmt:$(location @go_sdk//:bin/gofmt)", @@ -45,14 +51,19 @@ genrule( cmd = """ $(location :check) \ --fix \ + -l warn \ -v warn \ -x mobile/dist/envoy-pom.xml \ --extensions_build_config=$(location :extensions_build_config) \ + --extensions_fuzzed_count=%s \ --path=%s \ -b shellcheck:$(location @com_github_aignas_rules_shellcheck//:shellcheck) \ -b gofmt:$(location @go_sdk//:bin/gofmt) \ > $@ 2>&1 || : - """ % PATH, + """ % ( + FUZZ_FILTER_COUNT, + PATH, + ), tags = ["no-remote-exec"], tools = [ ":check", From eac62b6462c3b4a0e91dffb012ca81ec3df3e92b Mon Sep 17 00:00:00 2001 From: Loong Dai Date: Thu, 25 May 2023 15:05:28 +0800 Subject: [PATCH 079/228] dlb: support virtual DLB devices (#27338) Signed-off-by: Loong --- bazel/foreign_cc/dlb.patch | 22 ---------------- bazel/repositories.bzl | 2 -- bazel/repository_locations.bzl | 8 +++--- .../dlb/source/connection_balancer_impl.cc | 25 +++++++++---------- .../dlb/source/connection_balancer_impl.h | 5 ++-- 5 files changed, 19 insertions(+), 43 deletions(-) delete mode 100644 bazel/foreign_cc/dlb.patch diff --git a/bazel/foreign_cc/dlb.patch b/bazel/foreign_cc/dlb.patch deleted file mode 100644 index ca7649f6a0ee..000000000000 --- a/bazel/foreign_cc/dlb.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/dlb/libdlb/dlb_ops.h b/dlb/libdlb/dlb_ops.h -index 3f384f8..bd621be 100644 ---- a/dlb/libdlb/dlb_ops.h -+++ b/dlb/libdlb/dlb_ops.h -@@ -33,13 +33,13 @@ static void dlb_movntdq(struct dlb_enqueue_qe *qe4, uint64_t *pp_addr) - __v2di srcData1 = (__v2di){_qe[2], _qe[3]}; - __v2di srcData2 = (__v2di){_qe[4], _qe[5]}; - __v2di srcData3 = (__v2di){_qe[6], _qe[7]}; -- __builtin_ia32_movntdq((__v2di *) pp_addr, (__v2di) srcData0); -+ __builtin_nontemporal_store((__v2di) srcData0, (__v2di *) pp_addr); - _mm_sfence(); -- __builtin_ia32_movntdq((__v2di *) pp_addr, (__v2di) srcData1); -+ __builtin_nontemporal_store((__v2di) srcData1, (__v2di *) pp_addr); - _mm_sfence(); -- __builtin_ia32_movntdq((__v2di *) pp_addr, (__v2di) srcData2); -+ __builtin_nontemporal_store((__v2di) srcData2, (__v2di *) pp_addr); - _mm_sfence(); -- __builtin_ia32_movntdq((__v2di *) pp_addr, (__v2di) srcData3); -+ __builtin_nontemporal_store((__v2di) srcData3, (__v2di *) pp_addr); - /* movntdq requires an sfence between writes to the PP MMIO address */ - _mm_sfence(); - } diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index ec0b65060918..c77baa9b132c 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -1260,8 +1260,6 @@ filegroup( visibility = ["@envoy//contrib/network/connection_balance/dlb/source:__pkg__"], ) """, - patch_args = ["-p1"], - patches = ["@envoy//bazel/foreign_cc:dlb.patch"], ) def _rules_fuzzing(): diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index cb8ff5395b5c..387ae12c3aaa 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1350,12 +1350,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Intel Dlb", project_desc = "Dlb", project_url = "https://networkbuilders.intel.com/solutionslibrary/queue-management-and-load-balancing-on-intel-architecture", - version = "7.8.0", - sha256 = "9070388d9a22055ca37c7e1ec6a4b55c6bfd829b1a99b860056af268b68c98b6", - urls = ["https://downloadmirror.intel.com/744007/dlb_linux_src_release_7.8.0_2022_09_20.txz"], + version = "8.0.0", + sha256 = "075533229bb2bd2f945ec8089a707205f3f8e8d87a8030e9208603d997236171", + urls = ["https://downloadmirror.intel.com/763709/dlb_linux_src_release8.0.0.txz"], use_category = ["dataplane_ext"], extensions = ["envoy.network.connection_balance.dlb"], - release_date = "2022-03-30", + release_date = "2022-12-15", cpe = "N/A", ), rules_license = dict( diff --git a/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc b/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc index 1e5fd46d5bb9..03da81765524 100644 --- a/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc +++ b/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc @@ -27,9 +27,9 @@ DlbConnectionBalanceFactory::createConnectionBalancerFromProto( fmt::format("unexpected dlb config: {}", typed_config.DebugString())); } - const int num = context.options().concurrency(); + const uint32_t worker_num = context.options().concurrency(); - if (num > 32) { + if (worker_num > 32) { ExceptionUtil::throwEnvoyException( "Dlb connection balanncer only supports up to 32 worker threads, " "please decrease the number of threads by `--concurrency`"); @@ -67,21 +67,20 @@ DlbConnectionBalanceFactory::createConnectionBalancerFromProto( } ENVOY_LOG(debug, - "dlb available resources: {}, domains: {}, LDB queues: {}, LDB ports: {}, SN slots: {} " - "{}, ES entries: {}, Contig ES entries: {}, LDB credits: {}, Contig LDB cred: {}, LDB " - "credit pls: {}", + "dlb available resources: domains: {}, LDB queues: {}, LDB ports: {}, " + "ES entries: {}, Contig ES entries: {}, LDB credits: {}, Config LDB credits: {}, LDB " + "credit pools: {}", rsrcs.num_sched_domains, rsrcs.num_ldb_queues, rsrcs.num_ldb_ports, - rsrcs.num_sn_slots[0], rsrcs.num_sn_slots[1], rsrcs.num_ldb_event_state_entries, - rsrcs.max_contiguous_ldb_event_state_entries, rsrcs.num_ldb_credits, - rsrcs.max_contiguous_ldb_credits, rsrcs.num_ldb_credit_pools); + rsrcs.num_ldb_event_state_entries, rsrcs.max_contiguous_ldb_event_state_entries, + rsrcs.num_ldb_credits, rsrcs.max_contiguous_ldb_credits, rsrcs.num_ldb_credit_pools); - uint num_seq_numbers; - if (dlb_get_ldb_sequence_number_allocation(dlb, 0, &num_seq_numbers)) { + if (rsrcs.num_ldb_ports < 2 * worker_num) { ExceptionUtil::throwEnvoyException( - fmt::format("dlb_get_ldb_sequence_number_allocation {}", errorDetails(errno))); + fmt::format("no available dlb port resources, request: {}, available: {}", 2 * worker_num, + rsrcs.num_ldb_ports)); } - domain_id = createSchedDomain(dlb, rsrcs, cap); + domain_id = createSchedDomain(dlb, rsrcs, cap, 2 * worker_num); if (domain_id == -1) { ExceptionUtil::throwEnvoyException( fmt::format("dlb_create_sched_domain_ {}", errorDetails(errno))); @@ -127,7 +126,7 @@ DlbConnectionBalanceFactory::createConnectionBalancerFromProto( ExceptionUtil::throwEnvoyException(fmt::format("tx create_ldb_queue {}", errorDetails(errno))); } - for (int i = 0; i < num; i++) { + for (uint i = 0; i < worker_num; i++) { int tx_port_id = createLdbPort(domain, cap, ldb_pool_id, dir_pool_id); if (tx_port_id == -1) { ExceptionUtil::throwEnvoyException( diff --git a/contrib/network/connection_balance/dlb/source/connection_balancer_impl.h b/contrib/network/connection_balance/dlb/source/connection_balancer_impl.h index adeb440b65f9..e046e9cc44e0 100644 --- a/contrib/network/connection_balance/dlb/source/connection_balancer_impl.h +++ b/contrib/network/connection_balance/dlb/source/connection_balancer_impl.h @@ -124,12 +124,13 @@ class DlbConnectionBalanceFactory : public Envoy::Network::ConnectionBalanceFact return dlb_create_ldb_port(domain, &args); } - static int createSchedDomain(dlb_hdl_t dlb, dlb_resources_t rsrcs, dlb_dev_cap_t cap) { + static int createSchedDomain(dlb_hdl_t dlb, dlb_resources_t rsrcs, dlb_dev_cap_t cap, + uint32_t num_ldb_ports) { int p_rsrsc = 100; dlb_create_sched_domain_t args; args.num_ldb_queues = 1; - args.num_ldb_ports = 64; + args.num_ldb_ports = num_ldb_ports; args.num_dir_ports = 0; args.num_ldb_event_state_entries = 2 * args.num_ldb_ports * cq_depth; if (!cap.combined_credits) { From 0953f28aef26021b29654ce3d94d324924dcdea3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 08:16:03 +0100 Subject: [PATCH 080/228] build(deps): bump redis from `47e4e43` to `f972469` in /examples/redis (#27597) Bumps redis from `47e4e43` to `f972469`. --- updated-dependencies: - dependency-name: redis dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/redis/Dockerfile-redis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/redis/Dockerfile-redis b/examples/redis/Dockerfile-redis index e05ddfb56f9f..aa02190f6263 100644 --- a/examples/redis/Dockerfile-redis +++ b/examples/redis/Dockerfile-redis @@ -1 +1 @@ -FROM redis@sha256:47e4e4395af10811cfd893e3e2dcfdf13cf45b0d4feeeafc92842d6902656ede +FROM redis@sha256:f9724694a0b97288d2255ff2b69642dfba7f34c8e41aaf0a59d33d10d8a42687 From df984fde92a34554d45596484a0e7093369076eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 08:21:14 +0100 Subject: [PATCH 081/228] build(deps): bump postgres from `b115fe7` to `31c9342` in /examples/shared/postgres (#27598) build(deps): bump postgres in /examples/shared/postgres Bumps postgres from `b115fe7` to `31c9342`. --- updated-dependencies: - dependency-name: postgres dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/postgres/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/postgres/Dockerfile b/examples/shared/postgres/Dockerfile index 84b2d96a722c..523758fea8e5 100644 --- a/examples/shared/postgres/Dockerfile +++ b/examples/shared/postgres/Dockerfile @@ -1,3 +1,3 @@ -FROM postgres:latest@sha256:b115fe7743919fff0b96f19405ed350017ef9333b3760fc0cc885713eb07f565 +FROM postgres:latest@sha256:31c9342603866f29206a06b77c8fed48b3c3f70d710a4be4e8216b134f92d0df COPY docker-healthcheck.sh /usr/local/bin/ HEALTHCHECK CMD ["docker-healthcheck.sh"] From 268bbf8701f27258882ded520d748fb90d2c9e45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 08:23:07 +0100 Subject: [PATCH 082/228] build(deps): bump python from `6c0b067` to `eaee5f7` in /examples/shared/python (#27602) build(deps): bump python in /examples/shared/python Bumps python from `6c0b067` to `eaee5f7`. --- updated-dependencies: - dependency-name: python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/python/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/python/Dockerfile b/examples/shared/python/Dockerfile index 8a87913da3aa..d64811d72d2d 100644 --- a/examples/shared/python/Dockerfile +++ b/examples/shared/python/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11.3-slim-bullseye@sha256:6c0b067294c78ee6538cc9d6163fd1653797d0f4fd567e55703a5365c7757138 as python-base +FROM python:3.11.3-slim-bullseye@sha256:eaee5f73efa9ae962d2077756292bc4878c04fcbc13dc168bb00cc365f35647e as python-base RUN rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache ARG PYTHON_REQUIREMENTS_FILE=aiohttp/requirements.txt From 0d59221ba32ddefd89903a6344db7ff06f59c36c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 08:30:12 +0100 Subject: [PATCH 083/228] build(deps): bump node from `95a950e` to `dc19067` in /examples/shared/node (#27604) build(deps): bump node in /examples/shared/node Bumps node from `95a950e` to `dc19067`. --- updated-dependencies: - dependency-name: node dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/node/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/node/Dockerfile b/examples/shared/node/Dockerfile index 9ef656782642..eba7faacef82 100644 --- a/examples/shared/node/Dockerfile +++ b/examples/shared/node/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.2-bullseye-slim@sha256:95a950ec61796f4c00f6b208cb51000b8bd127ee53b0c1c52f2539a5ab66f8ef as node-base +FROM node:20.2-bullseye-slim@sha256:dc1906714d1993d291e1e7b5f236291236b0a0b6dfacdb164e4a9ea44d09c52e as node-base FROM node-base as node-http-auth From ffa5f802745b463792dd9ae2d584288764eed451 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 08:34:42 +0100 Subject: [PATCH 084/228] build(deps): bump golang from `2dc5c56` to `918857f` in /examples/shared/golang (#27605) build(deps): bump golang in /examples/shared/golang Bumps golang from `2dc5c56` to `918857f`. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/golang/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/golang/Dockerfile b/examples/shared/golang/Dockerfile index c439916f78ea..17bff24cf5a4 100644 --- a/examples/shared/golang/Dockerfile +++ b/examples/shared/golang/Dockerfile @@ -3,7 +3,7 @@ RUN rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache -FROM golang:1.20.4-bullseye@sha256:2dc5c568c8a314583090e887e8d96d313e081e2c5333d0a7b935906baf77cee9 as golang-base +FROM golang:1.20.4-bullseye@sha256:918857f4064db0fff49799ce5e7c4d43e394f452111cd89cca9af539c18a76a8 as golang-base FROM golang-base as golang-control-plane-builder From 9005e80b33787d850bb4498382aaa5b7aa28f21b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 08:44:00 +0100 Subject: [PATCH 085/228] build(deps): bump otel/opentelemetry-collector from `e5bd89e` to `5c3a03d` in /examples/opentelemetry (#27603) build(deps): bump otel/opentelemetry-collector Bumps otel/opentelemetry-collector from `e5bd89e` to `5c3a03d`. --- updated-dependencies: - dependency-name: otel/opentelemetry-collector dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/opentelemetry/Dockerfile-opentelemetry | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/opentelemetry/Dockerfile-opentelemetry b/examples/opentelemetry/Dockerfile-opentelemetry index 4d05281c3000..177882fbdf92 100644 --- a/examples/opentelemetry/Dockerfile-opentelemetry +++ b/examples/opentelemetry/Dockerfile-opentelemetry @@ -1,7 +1,7 @@ FROM alpine:3.18@sha256:02bb6f428431fbc2809c5d1b41eab5a68350194fb508869a33cb1af4444c9b11 as otelc_curl RUN apk --update add curl -FROM otel/opentelemetry-collector:latest@sha256:e5bd89e5ec7cd5bb3ff01fbd811e3730be75d8725405ae0c0d282cc69b9597e0 +FROM otel/opentelemetry-collector:latest@sha256:5c3a03dac40b1f37069c63a2ee75d7bd8c7ba81fc42831085053b1c70e528349 COPY --from=otelc_curl / / From 9231baba699a58b04db10a6fb804cf06fb9f04e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 09:08:34 +0100 Subject: [PATCH 086/228] build(deps): bump actions/setup-python from 4.6.0 to 4.6.1 (#27627) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.6.0 to 4.6.1. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/57ded4d7d5e986d7296eab16560982c6dd7c923b...bd6b4b6205c4dbad673328db7b31b7fab9e241c0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-deps.yml | 2 +- .github/workflows/pr_notifier.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-deps.yml b/.github/workflows/check-deps.yml index 8754308add19..1744e3fa332e 100644 --- a/.github/workflows/check-deps.yml +++ b/.github/workflows/check-deps.yml @@ -21,7 +21,7 @@ jobs: with: ref: ${{ github.head_ref }} - name: Set up Python (3.10) - uses: actions/setup-python@57ded4d7d5e986d7296eab16560982c6dd7c923b + uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 with: python-version: "3.10" diff --git a/.github/workflows/pr_notifier.yml b/.github/workflows/pr_notifier.yml index dab80b2579f2..782ad94075da 100644 --- a/.github/workflows/pr_notifier.yml +++ b/.github/workflows/pr_notifier.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Python 3.8 - uses: actions/setup-python@57ded4d7d5e986d7296eab16560982c6dd7c923b + uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 with: python-version: '3.8' architecture: 'x64' From c80665747981281ea0d0897f718f3542ec45cfd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 09:28:16 +0100 Subject: [PATCH 087/228] build(deps): bump github/codeql-action from 2.3.3 to 2.3.4 (#27625) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.3 to 2.3.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/29b1f65c5e92e24fe6b6647da1eaabe529cec70f...f0e3dfb30302f8a0881bb509b044e0de4f6ef589) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-daily.yml | 4 ++-- .github/workflows/codeql-push.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 78225d327520..660eec1f12a5 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -33,7 +33,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@29b1f65c5e92e24fe6b6647da1eaabe529cec70f + uses: github/codeql-action/init@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -64,4 +64,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@29b1f65c5e92e24fe6b6647da1eaabe529cec70f + uses: github/codeql-action/analyze@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 183c47767366..fcb710edb6e4 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@29b1f65c5e92e24fe6b6647da1eaabe529cec70f + uses: github/codeql-action/init@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -78,4 +78,4 @@ jobs: - name: Perform CodeQL Analysis if: env.BUILD_TARGETS != '' - uses: github/codeql-action/analyze@29b1f65c5e92e24fe6b6647da1eaabe529cec70f + uses: github/codeql-action/analyze@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 From acc3baed11a610db97bf8aab6df34934ace469ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 09:53:52 +0100 Subject: [PATCH 088/228] build(deps): bump mysql from `a43f6e7` to `d6164ff` in /examples/mysql (#27628) Bumps mysql from `a43f6e7` to `d6164ff`. --- updated-dependencies: - dependency-name: mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/mysql/Dockerfile-mysql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/mysql/Dockerfile-mysql b/examples/mysql/Dockerfile-mysql index eb0333f639fa..de8c80df6a3e 100644 --- a/examples/mysql/Dockerfile-mysql +++ b/examples/mysql/Dockerfile-mysql @@ -1 +1 @@ -FROM mysql:8.0.33@sha256:a43f6e7e7f3a5e5b90f857fbed4e3103ece771b19f0f75880f767cf66bbb6577 +FROM mysql:8.0.33@sha256:d6164ff4855b9b3f2c7748c6ec564ccff841f79a7023db0f9293143481a44b6e From d4e8e0bff6fd76e76bf4a4073b2cdfe9fa579dcc Mon Sep 17 00:00:00 2001 From: StarryNight Date: Thu, 25 May 2023 19:39:26 +0800 Subject: [PATCH 089/228] add go extension filter state set api (#27513) * add go extension filter state set api Signed-off-by: wangkai19 * fix review comments Signed-off-by: wangkai19 * fix format Signed-off-by: wangkai19 * optimize string copy Signed-off-by: wangkai19 --------- Signed-off-by: wangkai19 --- contrib/golang/filters/http/source/cgo.cc | 13 ++++++ .../filters/http/source/go/pkg/api/api.h | 3 ++ .../filters/http/source/go/pkg/api/capi.go | 2 + .../filters/http/source/go/pkg/api/filter.go | 30 ++++++++++++++ .../http/source/go/pkg/http/capi_impl.go | 5 +++ .../filters/http/source/go/pkg/http/filter.go | 14 +++++++ .../filters/http/source/golang_filter.cc | 41 +++++++++++++++++++ .../filters/http/source/golang_filter.h | 11 +++++ .../http/test/golang_integration_test.cc | 2 + .../http/test/test_data/basic/filter.go | 3 ++ 10 files changed, 124 insertions(+) diff --git a/contrib/golang/filters/http/source/cgo.cc b/contrib/golang/filters/http/source/cgo.cc index 9b263471e55b..56742609932a 100644 --- a/contrib/golang/filters/http/source/cgo.cc +++ b/contrib/golang/filters/http/source/cgo.cc @@ -200,6 +200,19 @@ CAPIStatus envoyGoFilterHttpSendPanicReply(void* r, void* details) { }); } +CAPIStatus envoyGoFilterHttpSetStringFilterState(void* r, void* key, void* value, int state_type, + int life_span, int stream_sharing) { + return envoyGoFilterHandlerWrapper(r, + [key, value, state_type, life_span, stream_sharing]( + std::shared_ptr& filter) -> CAPIStatus { + auto key_str = referGoString(key); + auto value_str = referGoString(value); + return filter->setStringFilterState(key_str, value_str, + state_type, life_span, + stream_sharing); + }); +} + #ifdef __cplusplus } #endif diff --git a/contrib/golang/filters/http/source/go/pkg/api/api.h b/contrib/golang/filters/http/source/go/pkg/api/api.h index 76e61903051f..3673e458d5c8 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/api.h +++ b/contrib/golang/filters/http/source/go/pkg/api/api.h @@ -68,6 +68,9 @@ void envoyGoFilterHttpLog(uint32_t level, void* message); void envoyGoFilterHttpFinalize(void* r, int reason); +CAPIStatus envoyGoFilterHttpSetStringFilterState(void* r, void* key, void* value, int state_type, + int life_span, int stream_sharing); + #ifdef __cplusplus } // extern "C" #endif diff --git a/contrib/golang/filters/http/source/go/pkg/api/capi.go b/contrib/golang/filters/http/source/go/pkg/api/capi.go index 60b95d49aac8..764cf3845431 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/capi.go +++ b/contrib/golang/filters/http/source/go/pkg/api/capi.go @@ -48,4 +48,6 @@ type HttpCAPI interface { HttpLog(level LogType, message string) HttpFinalize(r unsafe.Pointer, reason int) + + HttpSetStringFilterState(r unsafe.Pointer, key string, value string, stateType StateType, lifeSpan LifeSpan, streamSharing StreamSharing) } diff --git a/contrib/golang/filters/http/source/go/pkg/api/filter.go b/contrib/golang/filters/http/source/go/pkg/api/filter.go index 8c2e12093bc4..1979fc2935f0 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/filter.go +++ b/contrib/golang/filters/http/source/go/pkg/api/filter.go @@ -77,6 +77,8 @@ type StreamInfo interface { UpstreamHostAddress() (string, bool) // UpstreamClusterName return the upstream host cluster. UpstreamClusterName() (string, bool) + // FilterState return the filter state interface. + FilterState() FilterState } type StreamFilterCallbacks interface { @@ -102,3 +104,31 @@ type DynamicMetadata interface { // TODO: Get(filterName string) map[string]interface{} Set(filterName string, key string, value interface{}) } + +type StateType int + +const ( + StateTypeReadOnly StateType = 0 + StateTypeMutable StateType = 1 +) + +type LifeSpan int + +const ( + LifeSpanFilterChain LifeSpan = 0 + LifeSpanRequest LifeSpan = 1 + LifeSpanConnection LifeSpan = 2 + LifeSpanTopSpan LifeSpan = 3 +) + +type StreamSharing int + +const ( + None StreamSharing = 0 + SharedWithUpstreamConnection StreamSharing = 1 + SharedWithUpstreamConnectionOnce StreamSharing = 2 +) + +type FilterState interface { + SetString(key, value string, stateType StateType, lifeSpan LifeSpan, streamSharing StreamSharing) +} diff --git a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go index b559ddaea20b..f043b5671224 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go +++ b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go @@ -265,3 +265,8 @@ var cAPI api.HttpCAPI = &httpCApiImpl{} func SetHttpCAPI(api api.HttpCAPI) { cAPI = api } + +func (c *httpCApiImpl) HttpSetStringFilterState(r unsafe.Pointer, key string, value string, stateType api.StateType, lifeSpan api.LifeSpan, streamSharing api.StreamSharing) { + res := C.envoyGoFilterHttpSetStringFilterState(r, unsafe.Pointer(&key), unsafe.Pointer(&value), C.int(stateType), C.int(lifeSpan), C.int(streamSharing)) + handleCApiStatus(res) +} diff --git a/contrib/golang/filters/http/source/go/pkg/http/filter.go b/contrib/golang/filters/http/source/go/pkg/http/filter.go index 039b041b03ba..881b2825b1b7 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/filter.go +++ b/contrib/golang/filters/http/source/go/pkg/http/filter.go @@ -196,3 +196,17 @@ func (s *streamInfo) UpstreamHostAddress() (string, bool) { func (s *streamInfo) UpstreamClusterName() (string, bool) { return cAPI.HttpGetStringValue(unsafe.Pointer(s.request.req), ValueUpstreamClusterName) } + +type filterState struct { + request *httpRequest +} + +func (s *streamInfo) FilterState() api.FilterState { + return &filterState{ + request: s.request, + } +} + +func (f *filterState) SetString(key, value string, stateType api.StateType, lifeSpan api.LifeSpan, streamSharing api.StreamSharing) { + cAPI.HttpSetStringFilterState(unsafe.Pointer(f.request.req), key, value, stateType, lifeSpan, streamSharing) +} diff --git a/contrib/golang/filters/http/source/golang_filter.cc b/contrib/golang/filters/http/source/golang_filter.cc index 9e7e2eb5a7ca..8dfd65f14ca6 100644 --- a/contrib/golang/filters/http/source/golang_filter.cc +++ b/contrib/golang/filters/http/source/golang_filter.cc @@ -1065,6 +1065,47 @@ void Filter::setDynamicMetadataInternal(ProcessorState& state, std::string filte state.streamInfo().setDynamicMetadata(filter_name, value); } +CAPIStatus Filter::setStringFilterState(absl::string_view key, absl::string_view value, + int state_type, int life_span, int stream_sharing) { + // lock until this function return since it may running in a Go thread. + Thread::LockGuard lock(mutex_); + if (has_destroyed_) { + ENVOY_LOG(debug, "golang filter has been destroyed"); + return CAPIStatus::CAPIFilterIsDestroy; + } + + auto& state = getProcessorState(); + if (!state.isProcessingInGo()) { + ENVOY_LOG(debug, "golang filter is not processing Go"); + return CAPIStatus::CAPINotInGo; + } + + if (state.isThreadSafe()) { + state.streamInfo().filterState()->setData( + key, std::make_shared(value), + static_cast(state_type), + static_cast(life_span), + static_cast(stream_sharing)); + } else { + auto key_str = std::string(key); + auto filter_state = std::make_shared(value); + auto weak_ptr = weak_from_this(); + state.getDispatcher().post( + [this, &state, weak_ptr, key_str, filter_state, state_type, life_span, stream_sharing] { + if (!weak_ptr.expired() && !hasDestroyed()) { + Thread::LockGuard lock(mutex_); + state.streamInfo().filterState()->setData( + key_str, filter_state, static_cast(state_type), + static_cast(life_span), + static_cast(stream_sharing)); + } else { + ENVOY_LOG(info, "golang filter has gone or destroyed in setStringFilterState"); + } + }); + } + return CAPIStatus::CAPIOK; +} + /* ConfigId */ uint64_t Filter::getMergedConfigId(ProcessorState& state) { diff --git a/contrib/golang/filters/http/source/golang_filter.h b/contrib/golang/filters/http/source/golang_filter.h index 888c8b544c90..af1423103c15 100644 --- a/contrib/golang/filters/http/source/golang_filter.h +++ b/contrib/golang/filters/http/source/golang_filter.h @@ -181,6 +181,8 @@ class Filter : public Http::StreamFilter, CAPIStatus getStringValue(int id, GoString* value_str); CAPIStatus getIntegerValue(int id, uint64_t* value); CAPIStatus setDynamicMetadata(std::string filter_name, std::string key, absl::string_view buf); + CAPIStatus setStringFilterState(absl::string_view key, absl::string_view value, int state_type, + int life_span, int stream_sharing); private: bool hasDestroyed() { @@ -259,6 +261,15 @@ class FilterLogger : Logger::Loggable { void log(uint32_t level, absl::string_view message) const; }; +class GoStringFilterState : public StreamInfo::FilterState::Object { +public: + GoStringFilterState(absl::string_view value) : value_(value) {} + const std::string& value() const { return value_; } + +private: + const std::string value_; +}; + } // namespace Golang } // namespace HttpFilters } // namespace Extensions diff --git a/contrib/golang/filters/http/test/golang_integration_test.cc b/contrib/golang/filters/http/test/golang_integration_test.cc index 0ec933742933..71c8f8fee378 100644 --- a/contrib/golang/filters/http/test/golang_integration_test.cc +++ b/contrib/golang/filters/http/test/golang_integration_test.cc @@ -34,6 +34,8 @@ class RetrieveDynamicMetadataFilter : public Http::StreamEncoderFilter { const auto& fields = filter_it->second.fields(); std::string val = fields.at("foo").string_value(); EXPECT_EQ(val, "bar"); + EXPECT_TRUE( + decoder_callbacks_->streamInfo().filterState()->hasDataWithName("go_state_test_key")); return Http::FilterHeadersStatus::Continue; } diff --git a/contrib/golang/filters/http/test/test_data/basic/filter.go b/contrib/golang/filters/http/test/test_data/basic/filter.go index 91d6d80ac200..93870973acd2 100644 --- a/contrib/golang/filters/http/test/test_data/basic/filter.go +++ b/contrib/golang/filters/http/test/test_data/basic/filter.go @@ -111,6 +111,9 @@ func (f *filter) decodeHeaders(header api.RequestHeaderMap, endStream bool) api. md.Set("filter.go", "foo", "bar") } + fs := f.callbacks.StreamInfo().FilterState() + fs.SetString("go_state_test_key", "go_state_test_value", api.StateTypeReadOnly, api.LifeSpanRequest, api.SharedWithUpstreamConnection) + if strings.Contains(f.localreplay, "decode-header") { return f.sendLocalReply("decode-header") } From 2419cff0a333d0f19ecfccb1517985b1157d8956 Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Thu, 25 May 2023 10:20:28 -0400 Subject: [PATCH 090/228] matcher: Introduce abstract interface `CustomMatchData` to matching API (#27587) * Introduce `CustomMatchData` to matching API Signed-off-by: tyxia --- envoy/matcher/matcher.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/envoy/matcher/matcher.h b/envoy/matcher/matcher.h index 32fdd76e2065..44f49681965a 100644 --- a/envoy/matcher/matcher.h +++ b/envoy/matcher/matcher.h @@ -25,7 +25,16 @@ class ServerFactoryContext; namespace Matcher { -using MatchingDataType = absl::variant; +// Abstract interface for custom matching data. +// Overrides this interface to provide custom matcher specific implementation. +class CustomMatchData { +public: + virtual ~CustomMatchData() = default; +}; + +using MatchingDataType = + absl::variant>; + inline constexpr absl::string_view DefaultMatchingDataType = "string"; // This file describes a MatchTree, which traverses a tree of matches until it From 2b3fbe5fe10e6e2e406def953558779d36df28cf Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Thu, 25 May 2023 10:21:25 -0400 Subject: [PATCH 091/228] Assert(valid) when ext_proc filter apply header mutations (#27547) * ASSERT(valid()) when ext_proc filter apply header mutations. Signed-off-by: Yanjun Xiang --- .../filters/http/ext_proc/ext_proc.cc | 5 ++- .../filters/http/ext_proc/mutation_utils.cc | 13 ++++++ .../ext_proc/ext_proc_integration_test.cc | 15 +++++++ .../http/ext_proc/mutation_utils_test.cc | 40 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index fd45f89921c8..1b2a4c10f9db 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -775,7 +775,10 @@ void Filter::sendImmediateResponse(const ImmediateResponse& response) { const auto mut_status = MutationUtils::applyHeaderMutations( response.headers(), headers, false, immediateResponseChecker().checker(), stats_.rejected_header_mutations_); - ENVOY_BUG(mut_status.ok(), "Immediate response mutations should not fail"); + if (!mut_status.ok()) { + ENVOY_LOG_EVERY_POW_2(error, "Immediate response mutations failed with {}", + mut_status.message()); + } } }; diff --git a/source/extensions/filters/http/ext_proc/mutation_utils.cc b/source/extensions/filters/http/ext_proc/mutation_utils.cc index 08dbcd6eedf9..6ac7297004ec 100644 --- a/source/extensions/filters/http/ext_proc/mutation_utils.cc +++ b/source/extensions/filters/http/ext_proc/mutation_utils.cc @@ -40,6 +40,11 @@ absl::Status MutationUtils::applyHeaderMutations(const HeaderMutation& mutation, const Checker& checker, Counter& rejected_mutations) { for (const auto& hdr : mutation.remove_headers()) { + if (!Http::HeaderUtility::headerNameIsValid(hdr)) { + ENVOY_LOG(debug, "remove_headers contain invalid character, may not be removed."); + rejected_mutations.inc(); + return absl::InvalidArgumentError("Invalid character in remove_headers mutation."); + } const LowerCaseString remove_header(hdr); switch (checker.check(CheckOperation::REMOVE, remove_header, "")) { case CheckResult::OK: @@ -62,6 +67,13 @@ absl::Status MutationUtils::applyHeaderMutations(const HeaderMutation& mutation, if (!sh.has_header()) { continue; } + if (!Http::HeaderUtility::headerNameIsValid(sh.header().key()) || + !Http::HeaderUtility::headerValueIsValid(sh.header().value())) { + ENVOY_LOG(debug, + "set_headers contain invalid character in key or value, may not be appended."); + rejected_mutations.inc(); + return absl::InvalidArgumentError("Invalid character in set_headers mutation."); + } const LowerCaseString header_name(sh.header().key()); const bool append = PROTOBUF_GET_WRAPPED_OR_DEFAULT(sh, append, false); const auto check_op = (append && !headers.get(header_name).empty()) ? CheckOperation::APPEND @@ -87,6 +99,7 @@ absl::Status MutationUtils::applyHeaderMutations(const HeaderMutation& mutation, break; case CheckResult::FAIL: ENVOY_LOG(debug, "Header {} may not be modified. Returning error", header_name); + rejected_mutations.inc(); return absl::InvalidArgumentError( absl::StrCat("Invalid attempt to modify ", static_cast(header_name))); } diff --git a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc index 3c488aaa0e27..d137b3e5cda8 100644 --- a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc +++ b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc @@ -1079,6 +1079,21 @@ TEST_P(ExtProcIntegrationTest, GetAndRespondImmediately) { EXPECT_EQ("{\"reason\": \"Not authorized\"}", response->body()); } +TEST_P(ExtProcIntegrationTest, GetAndRespondImmediatelyWithInvalidCharacter) { + initializeConfig(); + HttpIntegrationTest::initialize(); + auto response = sendDownstreamRequest(absl::nullopt); + + processAndRespondImmediately(*grpc_upstreams_[0], true, [](ImmediateResponse& immediate) { + immediate.mutable_status()->set_code(envoy::type::v3::StatusCode::Unauthorized); + auto* hdr = immediate.mutable_headers()->add_set_headers(); + hdr->mutable_header()->set_key("x-failure-reason\n"); + hdr->mutable_header()->set_value("testing"); + }); + + verifyDownstreamResponse(*response, 401); +} + // Test the filter using the default configuration by connecting to // an ext_proc server that responds to the request_headers message // by sending back an immediate_response message after the diff --git a/test/extensions/filters/http/ext_proc/mutation_utils_test.cc b/test/extensions/filters/http/ext_proc/mutation_utils_test.cc index 09dc91254794..669dcbd28b60 100644 --- a/test/extensions/filters/http/ext_proc/mutation_utils_test.cc +++ b/test/extensions/filters/http/ext_proc/mutation_utils_test.cc @@ -188,6 +188,46 @@ TEST(MutationUtils, TestNonAppendableHeaders) { EXPECT_THAT(&headers, HeaderMapEqualIgnoreOrder(&expected_headers)); } +TEST(MutationUtils, TestSetHeaderWithInvalidCharacter) { + Http::TestRequestHeaderMapImpl headers{ + {":method", "GET"}, + {"host", "localhost:1000"}, + }; + Checker checker(HeaderMutationRules::default_instance()); + Envoy::Stats::MockCounter rejections; + envoy::service::ext_proc::v3::HeaderMutation mutation; + auto* s = mutation.add_set_headers(); + // Test header key contains invalid character. + s->mutable_header()->set_key("x-append-this\n"); + s->mutable_header()->set_value("value"); + EXPECT_CALL(rejections, inc()); + EXPECT_FALSE( + MutationUtils::applyHeaderMutations(mutation, headers, false, checker, rejections).ok()); + + mutation.Clear(); + s = mutation.add_set_headers(); + // Test header value contains invalid character. + s->mutable_header()->set_key("x-append-this"); + s->mutable_header()->set_value("value\r"); + EXPECT_CALL(rejections, inc()); + EXPECT_FALSE( + MutationUtils::applyHeaderMutations(mutation, headers, false, checker, rejections).ok()); +} + +TEST(MutationUtils, TestRemoveHeaderWithInvalidCharacter) { + Http::TestRequestHeaderMapImpl headers{ + {":method", "GET"}, + {"host", "localhost:1000"}, + }; + envoy::service::ext_proc::v3::HeaderMutation mutation; + mutation.add_remove_headers("host\n"); + Checker checker(HeaderMutationRules::default_instance()); + Envoy::Stats::MockCounter rejections; + EXPECT_CALL(rejections, inc()); + EXPECT_FALSE( + MutationUtils::applyHeaderMutations(mutation, headers, false, checker, rejections).ok()); +} + // Ensure that we actually replace the body TEST(MutationUtils, TestBodyMutationReplace) { Buffer::OwnedImpl buf; From 058db60ba54c3791193d2264a848d7295bb4e521 Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Thu, 25 May 2023 10:22:41 -0400 Subject: [PATCH 092/228] http: Ensure that multiple referer header entries are added (#27532) * Ensure that there are multiple entries created with referer header Signed-off-by: tyxia --- test/common/http/conn_manager_utility_test.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/common/http/conn_manager_utility_test.cc b/test/common/http/conn_manager_utility_test.cc index de2306e0a813..9d6aadb157be 100644 --- a/test/common/http/conn_manager_utility_test.cc +++ b/test/common/http/conn_manager_utility_test.cc @@ -260,6 +260,11 @@ TEST_F(ConnectionManagerUtilityTest, RemoveRefererIfMultipleEntriesAreFound) { ON_CALL(config_, useRemoteAddress()).WillByDefault(Return(true)); TestRequestHeaderMapImpl headers{{"referer", "https://example.com/"}, {"referer", "https://google.com/"}}; + + // If the referer header is registered with `CustomInlineHeaderRegistry` somewhere else already, + // multiple headers will be placed into same slot. (i.e., single entry). Thus, assert here + // to ensure that two entries are created before proceeding to test multiple entries removal. + ASSERT_EQ(headers.size(), 2); EXPECT_EQ((MutateRequestRet{"10.0.0.1:0", true, Tracing::Reason::NotTraceable}), callMutateRequestHeaders(headers, Protocol::Http2)); EXPECT_TRUE(headers.get(Http::CustomHeaders::get().Referer).empty()); From 547ef8858f71ce7e997b53eadf5fd75b32395ea6 Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Thu, 25 May 2023 10:36:44 -0400 Subject: [PATCH 093/228] Implement ext_proc header allow list feature (#27524) * Implement ext_proc header scrubbing feature. Signed-off-by: Yanjun Xiang --- .../filters/http/ext_proc/v3/ext_proc.proto | 2 +- changelogs/current.yaml | 5 ++ .../filters/http/ext_proc/ext_proc.cc | 6 +- .../filters/http/ext_proc/ext_proc.h | 17 +++++- .../filters/http/ext_proc/mutation_utils.cc | 19 +++++-- .../filters/http/ext_proc/mutation_utils.h | 8 ++- .../ext_proc/ext_proc_integration_test.cc | 57 +++++++++++++++++++ .../http/ext_proc/mutation_utils_test.cc | 52 ++++++++++++++++- 8 files changed, 155 insertions(+), 11 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 02fa12d7455c..38feceb22706 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -187,7 +187,6 @@ message ExternalProcessor { // field is set in an external processor response. bool disable_clear_route_cache = 11; - // [#not-implemented-hide:] // Allow headers matching the ``forward_rules`` to be forwarded to the external processing server. // If not set, all headers are forwarded to the external processing server. HeaderForwardingRules forward_rules = 12; @@ -209,6 +208,7 @@ message ExternalProcessor { // The HeaderForwardingRules structure specifies what headers are // allowed to be forwarded to the external processing server. message HeaderForwardingRules { + // If not set, all headers are forwarded to the external processing server. type.matcher.v3.ListStringMatcher allowed_headers = 1; } diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 7f7af0bd7f0f..f868184568ec 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -203,6 +203,11 @@ new_features: :ref:`disable_clear_route_cache ` to force the ext_proc filter from clearing the route cache. Failures to clear from setting this field will be counted under the clear_route_cache_disabled stat. +- area: ext_proc + change: | + added new configuration field + :ref:`forward_rules ` + to only allow headers matchinging the forward rules to be forwarded to the external processing server. - area: redis_proxy change: | added new field :ref:`connection_rate_limit diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 1b2a4c10f9db..deb93c625667 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -179,7 +179,8 @@ FilterHeadersStatus Filter::onHeaders(ProcessorState& state, state.setHasNoBody(end_stream); ProcessingRequest req; auto* headers_req = state.mutableHeaders(req); - MutationUtils::headersToProto(headers, *headers_req->mutable_headers()); + MutationUtils::headersToProto(headers, config_->headerMatchers(), + *headers_req->mutable_headers()); headers_req->set_end_of_stream(end_stream); state.onStartProcessorCall(std::bind(&Filter::onMessageTimeout, this), config_->messageTimeout(), ProcessorState::CallbackState::HeadersCallback); @@ -551,7 +552,8 @@ void Filter::sendBufferedData(ProcessorState& state, ProcessorState::CallbackSta void Filter::sendTrailers(ProcessorState& state, const Http::HeaderMap& trailers) { ProcessingRequest req; auto* trailers_req = state.mutableTrailers(req); - MutationUtils::headersToProto(trailers, *trailers_req->mutable_trailers()); + MutationUtils::headersToProto(trailers, config_->headerMatchers(), + *trailers_req->mutable_trailers()); state.onStartProcessorCall(std::bind(&Filter::onMessageTimeout, this), config_->messageTimeout(), ProcessorState::CallbackState::TrailersCallback); ENVOY_LOG(debug, "Sending trailers message"); diff --git a/source/extensions/filters/http/ext_proc/ext_proc.h b/source/extensions/filters/http/ext_proc/ext_proc.h index f3a380547a8b..ecbf61dcaae8 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.h +++ b/source/extensions/filters/http/ext_proc/ext_proc.h @@ -19,6 +19,7 @@ #include "envoy/upstream/upstream.h" #include "source/common/common/logger.h" +#include "source/common/common/matchers.h" #include "source/common/protobuf/protobuf.h" #include "source/extensions/filters/common/mutation_rules/mutation_rules.h" #include "source/extensions/filters/http/common/pass_through_filter.h" @@ -110,7 +111,7 @@ class FilterConfig { message_timeout_(message_timeout), max_message_timeout_ms_(max_message_timeout_ms), stats_(generateStats(stats_prefix, config.stat_prefix(), scope)), processing_mode_(config.processing_mode()), mutation_checker_(config.mutation_rules()), - filter_metadata_(config.filter_metadata()) {} + filter_metadata_(config.filter_metadata()), header_matchers_(initHeaderMatchers(config)) {} bool failureModeAllow() const { return failure_mode_allow_; } @@ -130,6 +131,8 @@ class FilterConfig { bool disableClearRouteCache() const { return disable_clear_route_cache_; } + const std::vector& headerMatchers() const { return header_matchers_; } + const Envoy::ProtobufWkt::Struct& filterMetadata() const { return filter_metadata_; } private: @@ -138,6 +141,16 @@ class FilterConfig { const std::string final_prefix = absl::StrCat(prefix, "ext_proc.", filter_stats_prefix); return {ALL_EXT_PROC_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix))}; } + const std::vector initHeaderMatchers( + const envoy::extensions::filters::http::ext_proc::v3::ExternalProcessor& config) { + std::vector header_matchers; + for (const auto& matcher : config.forward_rules().allowed_headers().patterns()) { + header_matchers.push_back( + std::make_unique>( + matcher)); + } + return header_matchers; + } const bool failure_mode_allow_; const bool disable_clear_route_cache_; @@ -148,6 +161,8 @@ class FilterConfig { const envoy::extensions::filters::http::ext_proc::v3::ProcessingMode processing_mode_; const Filters::Common::MutationRules::Checker mutation_checker_; const Envoy::ProtobufWkt::Struct filter_metadata_; + // Empty header_matchers_ means allow all. + const std::vector header_matchers_; }; using FilterConfigSharedPtr = std::shared_ptr; diff --git a/source/extensions/filters/http/ext_proc/mutation_utils.cc b/source/extensions/filters/http/ext_proc/mutation_utils.cc index 6ac7297004ec..390e6b139e78 100644 --- a/source/extensions/filters/http/ext_proc/mutation_utils.cc +++ b/source/extensions/filters/http/ext_proc/mutation_utils.cc @@ -24,13 +24,22 @@ using Stats::Counter; using envoy::service::ext_proc::v3::BodyMutation; using envoy::service::ext_proc::v3::HeaderMutation; +bool MutationUtils::headerInAllowList( + absl::string_view key, const std::vector& header_matchers) { + return std::any_of(header_matchers.begin(), header_matchers.end(), + [&key](auto& matcher) { return matcher->match(key); }); +} + void MutationUtils::headersToProto(const Http::HeaderMap& headers_in, + const std::vector& header_matchers, envoy::config::core::v3::HeaderMap& proto_out) { - headers_in.iterate([&proto_out](const Http::HeaderEntry& e) -> Http::HeaderMap::Iterate { - auto* new_header = proto_out.add_headers(); - new_header->set_key(std::string(e.key().getStringView())); - new_header->set_value(MessageUtil::sanitizeUtf8String(e.value().getStringView())); - + headers_in.iterate([&proto_out, + &header_matchers](const Http::HeaderEntry& e) -> Http::HeaderMap::Iterate { + if (header_matchers.empty() || headerInAllowList(e.key().getStringView(), header_matchers)) { + auto* new_header = proto_out.add_headers(); + new_header->set_key(std::string(e.key().getStringView())); + new_header->set_value(MessageUtil::sanitizeUtf8String(e.value().getStringView())); + } return Http::HeaderMap::Iterate::Continue; }); } diff --git a/source/extensions/filters/http/ext_proc/mutation_utils.h b/source/extensions/filters/http/ext_proc/mutation_utils.h index ff328ba7e9a1..767973458a8f 100644 --- a/source/extensions/filters/http/ext_proc/mutation_utils.h +++ b/source/extensions/filters/http/ext_proc/mutation_utils.h @@ -17,8 +17,9 @@ namespace ExternalProcessing { class MutationUtils : public Logger::Loggable { public: - // Convert a header map until a protobuf + // Convert a header map into a protobuf static void headersToProto(const Http::HeaderMap& headers_in, + const std::vector& header_matchers, envoy::config::core::v3::HeaderMap& proto_out); // Modify header map based on a set of mutations from a protobuf. An error will be @@ -38,6 +39,11 @@ class MutationUtils : public Logger::Loggable { // Determine if a particular HTTP status code is valid. static bool isValidHttpStatus(int code); + +private: + // Check whether header:key is in header_matchers. + static bool headerInAllowList(absl::string_view key, + const std::vector& header_matchers); }; } // namespace ExternalProcessing diff --git a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc index d137b3e5cda8..74f011c3a541 100644 --- a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc +++ b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc @@ -2029,4 +2029,61 @@ TEST_P(ExtProcIntegrationTest, SendHeaderAndTrailerInBufferedMode) { verifyDownstreamResponse(*response, 200); } +// Test the filter with header allow list configured and verify only the allowed headers +// in request or response headers and trailers are sent to the ext_proc server. +TEST_P(ExtProcIntegrationTest, GetAndSetHeadersAndTrailersWithHeaderScrubbing) { + auto* forward_rules = proto_config_.mutable_forward_rules(); + auto* list = forward_rules->mutable_allowed_headers(); + list->add_patterns()->set_exact(":method"); + list->add_patterns()->set_exact(":authority"); + list->add_patterns()->set_exact(":status"); + list->add_patterns()->set_exact("x-test-trailers"); + proto_config_.mutable_processing_mode()->set_request_header_mode(ProcessingMode::SEND); + proto_config_.mutable_processing_mode()->set_request_trailer_mode(ProcessingMode::SEND); + proto_config_.mutable_processing_mode()->set_response_header_mode(ProcessingMode::SEND); + proto_config_.mutable_processing_mode()->set_response_trailer_mode(ProcessingMode::SEND); + + initializeConfig(); + HttpIntegrationTest::initialize(); + codec_client_ = makeHttpConnection(lookupPort("http")); + Http::TestRequestHeaderMapImpl headers; + HttpTestUtility::addDefaultHeaders(headers); + auto encoder_decoder = codec_client_->startRequest(headers); + request_encoder_ = &encoder_decoder.first; + IntegrationStreamDecoderPtr response = std::move(encoder_decoder.second); + Http::TestRequestTrailerMapImpl request_trailers{{"x-trailer-foo", "yes"}}; + codec_client_->sendTrailers(*request_encoder_, request_trailers); + + processRequestHeadersMessage( + *grpc_upstreams_[0], true, [](const HttpHeaders& headers, HeadersResponse&) { + Http::TestRequestHeaderMapImpl expected_request_headers{{":method", "GET"}, + {":authority", "host"}}; + // Verify only allowed request headers is received by ext_proc server. + EXPECT_THAT(headers.headers(), HeaderProtosEqual(expected_request_headers)); + return true; + }); + processRequestTrailersMessage(*grpc_upstreams_[0], false, + [](const HttpTrailers& trailers, TrailersResponse&) { + // The request trailer header is not in the allow list. + EXPECT_EQ(trailers.trailers().headers_size(), 0); + return true; + }); + // Send back response with :status 200 and trailer header: x-test-trailers. + handleUpstreamRequestWithTrailer(); + processResponseHeadersMessage( + *grpc_upstreams_[0], false, [](const HttpHeaders& headers, HeadersResponse&) { + Http::TestRequestHeaderMapImpl expected_response_headers{{":status", "200"}}; + EXPECT_THAT(headers.headers(), HeaderProtosEqual(expected_response_headers)); + return true; + }); + processResponseTrailersMessage( + *grpc_upstreams_[0], false, [](const HttpTrailers& trailers, TrailersResponse&) { + // The response trailer header is in the allow list. + Http::TestResponseTrailerMapImpl expected_trailers{{"x-test-trailers", "Yes"}}; + EXPECT_THAT(trailers.trailers(), HeaderProtosEqual(expected_trailers)); + return true; + }); + verifyDownstreamResponse(*response, 200); +} + } // namespace Envoy diff --git a/test/extensions/filters/http/ext_proc/mutation_utils_test.cc b/test/extensions/filters/http/ext_proc/mutation_utils_test.cc index 669dcbd28b60..bc8d36d9d77e 100644 --- a/test/extensions/filters/http/ext_proc/mutation_utils_test.cc +++ b/test/extensions/filters/http/ext_proc/mutation_utils_test.cc @@ -34,7 +34,8 @@ TEST(MutationUtils, TestBuildHeaders) { headers.addCopy(LowerCaseString("x-number"), 9999); envoy::config::core::v3::HeaderMap proto_headers; - MutationUtils::headersToProto(headers, proto_headers); + std::vector header_matchers; + MutationUtils::headersToProto(headers, header_matchers, proto_headers); Http::TestRequestHeaderMapImpl expected{{":method", "GET"}, {":path", "/foo/the/bar?size=123"}, @@ -284,6 +285,55 @@ TEST(MutationUtils, TestBodyMutationNothing) { EXPECT_TRUE(TestUtility::buffersEqual(buf, bufCopy)); } +TEST(MutationUtils, TestAllowHeadersExactCaseSensitive) { + Http::TestRequestHeaderMapImpl headers{ + {":method", "GET"}, + {":path", "/foo/the/bar?size=123"}, + {"content-type", "text/plain; encoding=UTF8"}, + {"x-something-else", "yes"}, + }; + + envoy::config::core::v3::HeaderMap proto_headers; + std::vector header_matchers; + envoy::type::matcher::v3::StringMatcher string_matcher; + string_matcher.set_exact(":method"); + header_matchers.push_back( + std::make_unique>( + string_matcher)); + string_matcher.set_exact(":Path"); + header_matchers.push_back( + std::make_unique>( + string_matcher)); + MutationUtils::headersToProto(headers, header_matchers, proto_headers); + + Http::TestRequestHeaderMapImpl expected{{":method", "GET"}}; + EXPECT_THAT(proto_headers, HeaderProtosEqual(expected)); +} + +TEST(MutationUtils, TestAllowHeadersExactIgnoreCase) { + Http::TestRequestHeaderMapImpl headers{ + {":method", "GET"}, + {":path", "/foo/the/bar?size=123"}, + {"content-type", "text/plain; encoding=UTF8"}, + {"x-something-else", "yes"}, + }; + envoy::config::core::v3::HeaderMap proto_headers; + std::vector header_matchers; + envoy::type::matcher::v3::StringMatcher string_matcher; + string_matcher.set_exact(":method"); + header_matchers.push_back( + std::make_unique>( + string_matcher)); + string_matcher.set_exact(":Path"); + string_matcher.set_ignore_case(true); + header_matchers.push_back( + std::make_unique>( + string_matcher)); + MutationUtils::headersToProto(headers, header_matchers, proto_headers); + Http::TestRequestHeaderMapImpl expected{{":method", "GET"}, {":path", "/foo/the/bar?size=123"}}; + EXPECT_THAT(proto_headers, HeaderProtosEqual(expected)); +} + } // namespace } // namespace ExternalProcessing } // namespace HttpFilters From 881bc030a8f1cdc904311de6c1cdba38ef8cc98a Mon Sep 17 00:00:00 2001 From: botengyao Date: Thu, 25 May 2023 10:40:54 -0400 Subject: [PATCH 094/228] hc: add health event sink interface and file sink implementation (#27419) * add access log to health check Signed-off-by: Boteng Yao --- CODEOWNERS | 2 + api/BUILD | 1 + api/envoy/config/core/v3/health_check.proto | 18 ++- .../health_check/event_sinks/file/v3/BUILD | 9 ++ .../event_sinks/file/v3/file.proto | 22 ++++ api/versioning/BUILD | 1 + changelogs/current.yaml | 4 + docs/root/api-v3/config/config.rst | 1 + .../health_check_event_sinks.rst | 10 ++ .../upstream/health_checking.rst | 9 +- envoy/server/health_checker_config.h | 12 ++ envoy/upstream/BUILD | 9 ++ envoy/upstream/health_check_event_sink.h | 38 +++++++ source/common/upstream/BUILD | 7 ++ .../upstream/health_checker_event_logger.cc | 8 ++ .../upstream/health_checker_event_logger.h | 28 ++++- source/common/upstream/health_checker_impl.cc | 46 ++------ source/common/upstream/health_checker_impl.h | 37 ++++++ source/extensions/extensions_build_config.bzl | 6 + source/extensions/extensions_metadata.yaml | 7 ++ .../health_check/event_sinks/file/BUILD | 25 +++++ .../event_sinks/file/file_sink_impl.cc | 31 +++++ .../event_sinks/file/file_sink_impl.h | 43 +++++++ test/common/upstream/BUILD | 2 + ...se-health_check_fuzz_test-5704648171978752 | 1 - ...ed-health_check_fuzz_test-5678121129607168 | 1 - ...ed-health_check_fuzz_test-5748071634567168 | 1 - .../health_check_corpus/custom_health_check | 1 - .../health_check_corpus/grpc_double_reset | 1 - .../grpc_generalized-crash | 1 - ...h-449c4bf2d000d6e56b782fdd26a86e20a7f87b4f | 1 - .../health_check_corpus/tcp_crash-test | 1 - .../health_check_corpus/tcp_crash-test-1 | 1 - .../upstream/health_checker_impl_test.cc | 88 ++++++++++++++- .../health_check/event_sinks/file/BUILD | 26 +++++ .../event_sinks/file/file_sink_impl_test.cc | 106 ++++++++++++++++++ test/mocks/server/BUILD | 1 + .../server/health_checker_factory_context.cc | 1 + .../server/health_checker_factory_context.h | 5 + ...testcase-config_fuzz_test-4788023076847616 | 1 - ...inimized-config_fuzz_test-5666128418832384 | 1 - ...inimized-server_fuzz_test-5733243234811904 | 1 - tools/code_format/config.yaml | 1 + tools/extensions/extensions_schema.yaml | 1 + 44 files changed, 560 insertions(+), 57 deletions(-) create mode 100644 api/envoy/extensions/health_check/event_sinks/file/v3/BUILD create mode 100644 api/envoy/extensions/health_check/event_sinks/file/v3/file.proto create mode 100644 docs/root/api-v3/config/health_check_event_sinks/health_check_event_sinks.rst create mode 100644 envoy/upstream/health_check_event_sink.h create mode 100644 source/extensions/health_check/event_sinks/file/BUILD create mode 100644 source/extensions/health_check/event_sinks/file/file_sink_impl.cc create mode 100644 source/extensions/health_check/event_sinks/file/file_sink_impl.h create mode 100644 test/extensions/health_check/event_sinks/file/BUILD create mode 100644 test/extensions/health_check/event_sinks/file/file_sink_impl_test.cc diff --git a/CODEOWNERS b/CODEOWNERS index efa25078addf..e9a63bb15179 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -309,6 +309,8 @@ extensions/filters/http/oauth2 @derekargueta @snowp /*/extensions/health_checkers/grpc @snowp @zuercher /*/extensions/health_checkers/http @snowp @zuercher /*/extensions/health_checkers/tcp @snowp @zuercher +# Health check event sinks +/*/extensions/health_check/event_sinks/file @botengyao @yanavlasov # IP Geolocation /*/extensions/filters/http/geoip @nezdolik @ravenblackx diff --git a/api/BUILD b/api/BUILD index cc3a5068531d..0a9934e0207b 100644 --- a/api/BUILD +++ b/api/BUILD @@ -235,6 +235,7 @@ proto_library( "//envoy/extensions/formatter/cel/v3:pkg", "//envoy/extensions/formatter/metadata/v3:pkg", "//envoy/extensions/formatter/req_without_query/v3:pkg", + "//envoy/extensions/health_check/event_sinks/file/v3:pkg", "//envoy/extensions/health_checkers/redis/v3:pkg", "//envoy/extensions/health_checkers/thrift/v3:pkg", "//envoy/extensions/http/cache/file_system_http_cache/v3:pkg", diff --git a/api/envoy/config/core/v3/health_check.proto b/api/envoy/config/core/v3/health_check.proto index f4c9d857b459..2ec258d8ac09 100644 --- a/api/envoy/config/core/v3/health_check.proto +++ b/api/envoy/config/core/v3/health_check.proto @@ -4,6 +4,7 @@ package envoy.config.core.v3; import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/event_service_config.proto"; +import "envoy/config/core/v3/extension.proto"; import "envoy/type/matcher/v3/string.proto"; import "envoy/type/v3/http.proto"; import "envoy/type/v3/range.proto"; @@ -13,6 +14,7 @@ import "google/protobuf/duration.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/wrappers.proto"; +import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; import "validate/validate.proto"; @@ -60,7 +62,7 @@ message HealthStatusSet { [(validate.rules).repeated = {items {enum {defined_only: true}}}]; } -// [#next-free-field: 25] +// [#next-free-field: 26] message HealthCheck { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.core.HealthCheck"; @@ -366,9 +368,19 @@ message HealthCheck { // The default value for "healthy edge interval" is the same as the default interval. google.protobuf.Duration healthy_edge_interval = 16 [(validate.rules).duration = {gt {}}]; + // .. attention:: + // This field is deprecated in favor of the extension + // :ref:`event_logger ` and + // :ref:`event_log_path ` + // in the file sink extension. + // // Specifies the path to the :ref:`health check event log `. - // If empty, no event log will be written. - string event_log_path = 17; + string event_log_path = 17 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; + + // A list of event log sinks to process the health check event. + // [#extension-category: envoy.health_check.event_sinks] + repeated TypedExtensionConfig event_logger = 25; // [#not-implemented-hide:] // The gRPC service for the health check event service. diff --git a/api/envoy/extensions/health_check/event_sinks/file/v3/BUILD b/api/envoy/extensions/health_check/event_sinks/file/v3/BUILD new file mode 100644 index 000000000000..ee92fb652582 --- /dev/null +++ b/api/envoy/extensions/health_check/event_sinks/file/v3/BUILD @@ -0,0 +1,9 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"], +) diff --git a/api/envoy/extensions/health_check/event_sinks/file/v3/file.proto b/api/envoy/extensions/health_check/event_sinks/file/v3/file.proto new file mode 100644 index 000000000000..d436474a729a --- /dev/null +++ b/api/envoy/extensions/health_check/event_sinks/file/v3/file.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package envoy.extensions.health_check.event_sinks.file.v3; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.health_check.event_sinks.file.v3"; +option java_outer_classname = "FileProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/health_check/event_sinks/file/v3;filev3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Health Check Log File Sink] +// [#extension: envoy.health_check.event_sinks.file] + +// Health check event file sink. +// The health check event will be converted to JSON. +message HealthCheckEventFileSink { + // Specifies the path to the health check event log. + string event_log_path = 1 [(validate.rules).string = {min_len: 1}]; +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 4f4a25d60e82..a256f1a4cada 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -173,6 +173,7 @@ proto_library( "//envoy/extensions/formatter/cel/v3:pkg", "//envoy/extensions/formatter/metadata/v3:pkg", "//envoy/extensions/formatter/req_without_query/v3:pkg", + "//envoy/extensions/health_check/event_sinks/file/v3:pkg", "//envoy/extensions/health_checkers/redis/v3:pkg", "//envoy/extensions/health_checkers/thrift/v3:pkg", "//envoy/extensions/http/cache/file_system_http_cache/v3:pkg", diff --git a/changelogs/current.yaml b/changelogs/current.yaml index f868184568ec..f537a751f08d 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -241,3 +241,7 @@ deprecated: change: | deprecated (1.25.0) :ref:`intermediate_log_entry ` in favour of :ref:`access_log_type `. +- area: health_check + change: | + deprecated the :ref:`HealthCheck event_log_path ` in favor of + :ref:`HealthCheck event_logger extension `. diff --git a/docs/root/api-v3/config/config.rst b/docs/root/api-v3/config/config.rst index 10a4752b2640..ca859c388e68 100644 --- a/docs/root/api-v3/config/config.rst +++ b/docs/root/api-v3/config/config.rst @@ -19,6 +19,7 @@ Extensions endpoint/endpoint filter/filter grpc_credential/grpc_credential + health_check_event_sinks/health_check_event_sinks health_checker/health_checker http/early_header_mutation http/custom_response diff --git a/docs/root/api-v3/config/health_check_event_sinks/health_check_event_sinks.rst b/docs/root/api-v3/config/health_check_event_sinks/health_check_event_sinks.rst new file mode 100644 index 000000000000..b05bea13b7fd --- /dev/null +++ b/docs/root/api-v3/config/health_check_event_sinks/health_check_event_sinks.rst @@ -0,0 +1,10 @@ +.. _api_v3_health_check_event_sinks: + +Health check event sinks +======================== + +.. toctree:: + :glob: + :maxdepth: 2 + + ../../extensions/health_check/event_sinks/*/v3/* diff --git a/docs/root/intro/arch_overview/upstream/health_checking.rst b/docs/root/intro/arch_overview/upstream/health_checking.rst index c3d674d4d019..9fbc8e126c6f 100644 --- a/docs/root/intro/arch_overview/upstream/health_checking.rst +++ b/docs/root/intro/arch_overview/upstream/health_checking.rst @@ -85,10 +85,17 @@ Health check event logging -------------------------- A per-healthchecker log of ejection and addition events can optionally be produced by Envoy by -specifying a log file path in :ref:`the HealthCheck config `. +specifying a log file path in :ref:`the HealthCheck config event_log_path `. The log is structured as JSON dumps of :ref:`HealthCheckEvent messages `. +Note: :ref:`the HealthCheck config event_log_path ` is deperated in favor of +:ref:`HealthCheck event_logger extension `. +The :ref:`event_log_path ` is used in the file sink extension for the JSON dumps. + +A new event sink extension catalog +`envoy.health_check.event_sinks` is created, and APIs can be found :ref:`here `. + Envoy can be configured to log all health check failure events by setting the :ref:`always_log_health_check_failures flag ` to true. diff --git a/envoy/server/health_checker_config.h b/envoy/server/health_checker_config.h index 82f27123db8c..9ee5477420fa 100644 --- a/envoy/server/health_checker_config.h +++ b/envoy/server/health_checker_config.h @@ -46,6 +46,18 @@ class HealthCheckerFactoryContext { * @return Api::Api& the API used by the server. */ virtual Api::Api& api() PURE; + + /** + * @return AccessLogManager for use by the entire server. + */ + virtual AccessLog::AccessLogManager& accessLogManager() PURE; + + /** + * Set the event logger to the context, nullptr is accepted since + * the default in the context is nullptr. + * @param event_logger the health check event logger. + */ + virtual void setEventLogger(Upstream::HealthCheckEventLoggerPtr event_logger) PURE; }; /** diff --git a/envoy/upstream/BUILD b/envoy/upstream/BUILD index fb52a403c2f7..8178b9d494e8 100644 --- a/envoy/upstream/BUILD +++ b/envoy/upstream/BUILD @@ -41,6 +41,15 @@ envoy_cc_library( ], ) +envoy_cc_library( + name = "health_check_event_sink_interface", + hdrs = ["health_check_event_sink.h"], + deps = [ + "//envoy/config:typed_config_interface", + "//envoy/server:health_checker_config_interface", + ], +) + envoy_cc_library( name = "health_checker_interface", hdrs = ["health_checker.h"], diff --git a/envoy/upstream/health_check_event_sink.h b/envoy/upstream/health_check_event_sink.h new file mode 100644 index 000000000000..aed7792d057d --- /dev/null +++ b/envoy/upstream/health_check_event_sink.h @@ -0,0 +1,38 @@ +#include "envoy/config/typed_config.h" +#include "envoy/server/health_checker_config.h" + +namespace Envoy { +namespace Upstream { + +/** + * Sink for health check event. + */ +class HealthCheckEventSink { +public: + virtual ~HealthCheckEventSink() = default; + + virtual void log(envoy::data::core::v3::HealthCheckEvent event) PURE; +}; + +using HealthCheckEventSinkPtr = std::unique_ptr; +using HealthCheckEventSinkSharedPtr = std::shared_ptr; + +/** + * A factory abstract class for creating instances of HealthCheckEventSink. + */ +class HealthCheckEventSinkFactory : public Config::TypedFactory { +public: + ~HealthCheckEventSinkFactory() override = default; + + /** + * Creates an HealthCheckEventSink using the given config. + */ + virtual HealthCheckEventSinkPtr + createHealthCheckEventSink(const ProtobufWkt::Any& config, + Server::Configuration::HealthCheckerFactoryContext& context) PURE; + + std::string category() const override { return "envoy.health_check.event_sinks"; } +}; + +} // namespace Upstream +} // namespace Envoy diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index 23562f7aaa7f..86daa4417864 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -209,8 +209,14 @@ envoy_cc_library( srcs = ["health_checker_event_logger.cc"], hdrs = ["health_checker_event_logger.h"], deps = [ + "//envoy/server:factory_context_interface", + "//envoy/server:health_checker_config_interface", + "//envoy/upstream:health_check_event_sink_interface", "//envoy/upstream:health_checker_interface", + "//source/common/access_log:access_log_lib", "//source/common/network:utility_lib", + "//source/common/protobuf:utility_lib", + "@envoy_api//envoy/config/accesslog/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/data/core/v3:pkg_cc_proto", "@envoy_api//envoy/type/matcher:pkg_cc_proto", @@ -231,6 +237,7 @@ envoy_cc_library( "@envoy_api//envoy/type/v3:pkg_cc_proto", # TODO(dio): Remove dependency to server. "//envoy/server:health_checker_config_interface", + "//envoy/server:factory_context_interface", "//source/common/grpc:codec_lib", "//source/common/router:router_lib", "//source/common/http:codec_client_lib", diff --git a/source/common/upstream/health_checker_event_logger.cc b/source/common/upstream/health_checker_event_logger.cc index d4ed440c61d6..a293bcaa3be3 100644 --- a/source/common/upstream/health_checker_event_logger.cc +++ b/source/common/upstream/health_checker_event_logger.cc @@ -65,13 +65,21 @@ void HealthCheckEventLoggerImpl::createHealthCheckEvent( TimestampUtil::systemClockToTimestamp(time_source_.systemTime(), *event.mutable_timestamp()); callback(event); + for (const auto& event_sink : event_sinks_) { + event_sink->log(event); + } + #ifdef ENVOY_ENABLE_YAML + if (file_ == nullptr) { + return; + } // Make sure the type enums make it into the JSON const auto json = MessageUtil::getJsonStringFromMessageOrError(event, /* pretty_print */ false, /* always_print_primitive_fields */ true); file_->write(fmt::format("{}\n", json)); + #endif } } // namespace Upstream diff --git a/source/common/upstream/health_checker_event_logger.h b/source/common/upstream/health_checker_event_logger.h index d26be58d56cd..fe67cd9a8f87 100644 --- a/source/common/upstream/health_checker_event_logger.h +++ b/source/common/upstream/health_checker_event_logger.h @@ -2,15 +2,23 @@ #include "envoy/access_log/access_log.h" #include "envoy/common/callback.h" +#include "envoy/config/accesslog/v3/accesslog.pb.h" +#include "envoy/config/accesslog/v3/accesslog.pb.validate.h" #include "envoy/config/core/v3/health_check.pb.h" #include "envoy/data/core/v3/health_check_event.pb.h" #include "envoy/event/timer.h" #include "envoy/runtime/runtime.h" +#include "envoy/server/factory_context.h" +#include "envoy/server/health_checker_config.h" #include "envoy/stats/scope.h" #include "envoy/type/matcher/string.pb.h" +#include "envoy/upstream/health_check_event_sink.h" #include "envoy/upstream/health_checker.h" +#include "source/common/access_log/access_log_impl.h" #include "source/common/common/logger.h" +#include "source/common/config/utility.h" +#include "source/common/protobuf/utility.h" namespace Envoy { namespace Upstream { @@ -18,9 +26,22 @@ namespace Upstream { class HealthCheckEventLoggerImpl : public HealthCheckEventLogger { public: HealthCheckEventLoggerImpl(AccessLog::AccessLogManager& log_manager, TimeSource& time_source, - const std::string& file_name) - : time_source_(time_source), file_(log_manager.createAccessLog(Filesystem::FilePathAndType{ - Filesystem::DestinationType::File, file_name})) {} + const envoy::config::core::v3::HealthCheck& health_check_config, + Server::Configuration::HealthCheckerFactoryContext& context) + : time_source_(time_source) { + + // TODO(botengyao): Remove the file_ creation here into the file based health check + // event sink. In this way you can remove the file_ based code from the createHealthCheckEvent + if (!health_check_config.event_log_path().empty() /* deprecated */) { + file_ = log_manager.createAccessLog(Filesystem::FilePathAndType{ + Filesystem::DestinationType::File, health_check_config.event_log_path()}); + } + + for (const auto& config : health_check_config.event_logger()) { + auto& factory = Config::Utility::getAndCheckFactory(config); + event_sinks_.push_back(factory.createHealthCheckEventSink(config.typed_config(), context)); + } + } void logEjectUnhealthy(envoy::data::core::v3::HealthCheckerType health_checker_type, const HostDescriptionConstSharedPtr& host, @@ -42,6 +63,7 @@ class HealthCheckEventLoggerImpl : public HealthCheckEventLogger { std::function callback) const; TimeSource& time_source_; AccessLog::AccessLogFileSharedPtr file_; + std::vector event_sinks_; }; } // namespace Upstream diff --git a/source/common/upstream/health_checker_impl.cc b/source/common/upstream/health_checker_impl.cc index 6b97ecc0c3a8..3ccae085a020 100644 --- a/source/common/upstream/health_checker_impl.cc +++ b/source/common/upstream/health_checker_impl.cc @@ -47,44 +47,11 @@ const std::string& HealthCheckerFactory::getHostname(const HostSharedPtr& host, return cluster->name(); } -class HealthCheckerFactoryContextImpl : public Server::Configuration::HealthCheckerFactoryContext { -public: - HealthCheckerFactoryContextImpl(Upstream::Cluster& cluster, Envoy::Runtime::Loader& runtime, - Event::Dispatcher& dispatcher, - HealthCheckEventLoggerPtr&& event_logger, - ProtobufMessage::ValidationVisitor& validation_visitor, - Api::Api& api) - : cluster_(cluster), runtime_(runtime), dispatcher_(dispatcher), - event_logger_(std::move(event_logger)), validation_visitor_(validation_visitor), api_(api) { - } - Upstream::Cluster& cluster() override { return cluster_; } - Envoy::Runtime::Loader& runtime() override { return runtime_; } - Event::Dispatcher& mainThreadDispatcher() override { return dispatcher_; } - HealthCheckEventLoggerPtr eventLogger() override { return std::move(event_logger_); } - ProtobufMessage::ValidationVisitor& messageValidationVisitor() override { - return validation_visitor_; - } - Api::Api& api() override { return api_; } - -private: - Upstream::Cluster& cluster_; - Envoy::Runtime::Loader& runtime_; - Event::Dispatcher& dispatcher_; - HealthCheckEventLoggerPtr event_logger_; - ProtobufMessage::ValidationVisitor& validation_visitor_; - Api::Api& api_; -}; - HealthCheckerSharedPtr HealthCheckerFactory::create( const envoy::config::core::v3::HealthCheck& health_check_config, Upstream::Cluster& cluster, Runtime::Loader& runtime, Event::Dispatcher& dispatcher, AccessLog::AccessLogManager& log_manager, ProtobufMessage::ValidationVisitor& validation_visitor, Api::Api& api) { - HealthCheckEventLoggerPtr event_logger; - if (!health_check_config.event_log_path().empty()) { - event_logger = std::make_unique( - log_manager, dispatcher.timeSource(), health_check_config.event_log_path()); - } Server::Configuration::CustomHealthCheckerFactory* factory = nullptr; switch (health_check_config.health_checker_case()) { @@ -112,9 +79,18 @@ HealthCheckerSharedPtr HealthCheckerFactory::create( health_check_config.custom_health_check()); } } + std::unique_ptr context( - new HealthCheckerFactoryContextImpl(cluster, runtime, dispatcher, std::move(event_logger), - validation_visitor, api)); + new HealthCheckerFactoryContextImpl(cluster, runtime, dispatcher, validation_visitor, api, + log_manager)); + + if (!health_check_config.event_log_path().empty() /* deprecated */ || + !health_check_config.event_logger().empty()) { + HealthCheckEventLoggerPtr event_logger; + event_logger = std::make_unique( + log_manager, dispatcher.timeSource(), health_check_config, *context); + context->setEventLogger(std::move(event_logger)); + } return factory->createCustomHealthChecker(health_check_config, *context); } diff --git a/source/common/upstream/health_checker_impl.h b/source/common/upstream/health_checker_impl.h index 32bcc69d557e..e6233a9b5773 100644 --- a/source/common/upstream/health_checker_impl.h +++ b/source/common/upstream/health_checker_impl.h @@ -9,9 +9,11 @@ #include "envoy/data/core/v3/health_check_event.pb.h" #include "envoy/grpc/status.h" #include "envoy/network/socket.h" +#include "envoy/server/factory_context.h" #include "envoy/server/health_checker_config.h" #include "envoy/type/v3/http.pb.h" #include "envoy/type/v3/range.pb.h" +#include "envoy/upstream/health_checker.h" #include "source/common/common/dump_state_utils.h" #include "source/common/common/logger.h" @@ -45,6 +47,41 @@ struct HealthCheckerEqualTo { } }; +/** + * Health checker factory context. + */ +class HealthCheckerFactoryContextImpl : public Server::Configuration::HealthCheckerFactoryContext { +public: + HealthCheckerFactoryContextImpl(Upstream::Cluster& cluster, Envoy::Runtime::Loader& runtime, + Event::Dispatcher& dispatcher, + ProtobufMessage::ValidationVisitor& validation_visitor, + Api::Api& api, AccessLog::AccessLogManager& log_manager) + : cluster_(cluster), runtime_(runtime), dispatcher_(dispatcher), + validation_visitor_(validation_visitor), log_manager_(log_manager), api_(api) {} + Upstream::Cluster& cluster() override { return cluster_; } + Envoy::Runtime::Loader& runtime() override { return runtime_; } + Event::Dispatcher& mainThreadDispatcher() override { return dispatcher_; } + HealthCheckEventLoggerPtr eventLogger() override { return std::move(event_logger_); } + ProtobufMessage::ValidationVisitor& messageValidationVisitor() override { + return validation_visitor_; + } + Api::Api& api() override { return api_; } + + AccessLog::AccessLogManager& accessLogManager() override { return log_manager_; } + void setEventLogger(HealthCheckEventLoggerPtr event_logger) override { + event_logger_ = std::move(event_logger); + } + +private: + Upstream::Cluster& cluster_; + Envoy::Runtime::Loader& runtime_; + Event::Dispatcher& dispatcher_; + ProtobufMessage::ValidationVisitor& validation_visitor_; + AccessLog::AccessLogManager& log_manager_; + Api::Api& api_; + HealthCheckEventLoggerPtr event_logger_; +}; + /** * Factory for creating health checker implementations. */ diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index e0370c799dc2..1cccfe090b8b 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -66,6 +66,12 @@ EXTENSIONS = { "envoy.health_checkers.http": "//source/extensions/health_checkers/http:health_checker_lib", "envoy.health_checkers.grpc": "//source/extensions/health_checkers/grpc:health_checker_lib", + # + # Health check event sinks + # + + "envoy.health_check.event_sinks.file": "//source/extensions/health_check/event_sinks/file:file_sink_lib", + # # Input Matchers # diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index c0113843a8dd..0a19fb24bfbc 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -795,6 +795,13 @@ envoy.health_checkers.thrift: status: alpha type_urls: - envoy.extensions.health_checkers.thrift.v3.Thrift +envoy.health_check.event_sinks.file: + categories: + - envoy.health_check.event_sinks + security_posture: robust_to_untrusted_downstream_and_upstream + status: stable + type_urls: + - envoy.extensions.health_check.event_sinks.file.v3.HealthCheckEventFileSink envoy.http.original_ip_detection.custom_header: categories: - envoy.http.original_ip_detection diff --git a/source/extensions/health_check/event_sinks/file/BUILD b/source/extensions/health_check/event_sinks/file/BUILD new file mode 100644 index 000000000000..4aa9f785662c --- /dev/null +++ b/source/extensions/health_check/event_sinks/file/BUILD @@ -0,0 +1,25 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_extension( + name = "file_sink_lib", + srcs = ["file_sink_impl.cc"], + hdrs = ["file_sink_impl.h"], + extra_visibility = [ + # previously considered core code. + "//test:__subpackages__", + ], + deps = [ + "//envoy/registry", + "//envoy/upstream:health_check_event_sink_interface", + "//source/common/protobuf:utility_lib", + "@envoy_api//envoy/extensions/health_check/event_sinks/file/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/health_check/event_sinks/file/file_sink_impl.cc b/source/extensions/health_check/event_sinks/file/file_sink_impl.cc new file mode 100644 index 000000000000..61f0113c75c4 --- /dev/null +++ b/source/extensions/health_check/event_sinks/file/file_sink_impl.cc @@ -0,0 +1,31 @@ +#include "source/extensions/health_check/event_sinks/file/file_sink_impl.h" + +#include "envoy/registry/registry.h" + +#include "source/common/protobuf/utility.h" + +namespace Envoy { +namespace Upstream { + +void HealthCheckEventFileSink::log(envoy::data::core::v3::HealthCheckEvent event) { +#ifdef ENVOY_ENABLE_YAML + // Make sure the type enums make it into the JSON + const auto json = + MessageUtil::getJsonStringFromMessageOrError(event, /* pretty_print */ false, + /* always_print_primitive_fields */ true); + file_->write(fmt::format("{}\n", json)); +#endif +}; + +HealthCheckEventSinkPtr HealthCheckEventFileSinkFactory::createHealthCheckEventSink( + const ProtobufWkt::Any& config, Server::Configuration::HealthCheckerFactoryContext& context) { + const auto& validator_config = Envoy::MessageUtil::anyConvertAndValidate< + envoy::extensions::health_check::event_sinks::file::v3::HealthCheckEventFileSink>( + config, context.messageValidationVisitor()); + return std::make_unique(validator_config, context.accessLogManager()); +} + +REGISTER_FACTORY(HealthCheckEventFileSinkFactory, HealthCheckEventSinkFactory); + +} // namespace Upstream +} // namespace Envoy diff --git a/source/extensions/health_check/event_sinks/file/file_sink_impl.h b/source/extensions/health_check/event_sinks/file/file_sink_impl.h new file mode 100644 index 000000000000..79e8652157eb --- /dev/null +++ b/source/extensions/health_check/event_sinks/file/file_sink_impl.h @@ -0,0 +1,43 @@ +#pragma once + +#include "envoy/access_log/access_log.h" +#include "envoy/extensions/health_check/event_sinks/file/v3/file.pb.h" +#include "envoy/extensions/health_check/event_sinks/file/v3/file.pb.validate.h" +#include "envoy/upstream/health_check_event_sink.h" + +namespace Envoy { +namespace Upstream { + +class HealthCheckEventFileSink : public HealthCheckEventSink { +public: + explicit HealthCheckEventFileSink( + const envoy::extensions::health_check::event_sinks::file::v3::HealthCheckEventFileSink& + config, + AccessLog::AccessLogManager& log_manager) + : file_(log_manager.createAccessLog(Filesystem::FilePathAndType{ + Filesystem::DestinationType::File, config.event_log_path()})) {} + + void log(envoy::data::core::v3::HealthCheckEvent event) override; + +private: + AccessLog::AccessLogFileSharedPtr file_; +}; + +class HealthCheckEventFileSinkFactory : public HealthCheckEventSinkFactory { +public: + HealthCheckEventFileSinkFactory() = default; + + HealthCheckEventSinkPtr + createHealthCheckEventSink(const ProtobufWkt::Any& config, + Server::Configuration::HealthCheckerFactoryContext& context) override; + + std::string name() const override { return "envoy.health_check.event_sink.file"; } + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return ProtobufTypes::MessagePtr{ + new envoy::extensions::health_check::event_sinks::file::v3::HealthCheckEventFileSink()}; + } +}; + +} // namespace Upstream +} // namespace Envoy diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index d52e677e5fec..341abe8ab9f0 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -182,6 +182,7 @@ envoy_cc_test( "//source/common/protobuf:utility_lib", "//source/common/upstream:health_checker_lib", "//source/common/upstream:upstream_lib", + "//source/extensions/health_check/event_sinks/file:file_sink_lib", "//source/extensions/health_checkers/grpc:health_checker_lib", "//source/extensions/health_checkers/http:health_checker_lib", "//source/extensions/health_checkers/tcp:health_checker_lib", @@ -204,6 +205,7 @@ envoy_cc_test( "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto", "@envoy_api//envoy/data/core/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/health_check/event_sinks/file/v3:pkg_cc_proto", ], ) diff --git a/test/common/upstream/health_check_corpus/clusterfuzz-testcase-health_check_fuzz_test-5704648171978752 b/test/common/upstream/health_check_corpus/clusterfuzz-testcase-health_check_fuzz_test-5704648171978752 index 31117664f39d..5d505878716a 100644 --- a/test/common/upstream/health_check_corpus/clusterfuzz-testcase-health_check_fuzz_test-5704648171978752 +++ b/test/common/upstream/health_check_corpus/clusterfuzz-testcase-health_check_fuzz_test-5704648171978752 @@ -20,7 +20,6 @@ health_check_config { unhealthy_interval { seconds: 4227858432 } - event_log_path: "?(" tls_options { } } diff --git a/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5678121129607168 b/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5678121129607168 index b1530f2bc1d2..f48a0a08bd75 100644 --- a/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5678121129607168 +++ b/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5678121129607168 @@ -14,7 +14,6 @@ health_check_config { http_health_check { path: "\003" } - event_log_path: "(" interval_jitter_percent: 654311422 } actions { diff --git a/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5748071634567168 b/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5748071634567168 index 05ce7426fbec..bac5a09e0e7e 100644 --- a/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5748071634567168 +++ b/test/common/upstream/health_check_corpus/clusterfuzz-testcase-minimized-health_check_fuzz_test-5748071634567168 @@ -15,7 +15,6 @@ health_check_config { http_health_check { path: "(" } - event_log_path: "(" } actions { raise_event: 355888746 diff --git a/test/common/upstream/health_check_corpus/custom_health_check b/test/common/upstream/health_check_corpus/custom_health_check index d994dc6033bf..742f06b206c9 100644 --- a/test/common/upstream/health_check_corpus/custom_health_check +++ b/test/common/upstream/health_check_corpus/custom_health_check @@ -36,7 +36,6 @@ health_check_config { seconds: 131072 nanos: 128 } - event_log_path: "A(" interval_jitter_percent: 641007544 initial_jitter { seconds: 8960 diff --git a/test/common/upstream/health_check_corpus/grpc_double_reset b/test/common/upstream/health_check_corpus/grpc_double_reset index aaeca5b1d548..601ad42a77e5 100644 --- a/test/common/upstream/health_check_corpus/grpc_double_reset +++ b/test/common/upstream/health_check_corpus/grpc_double_reset @@ -15,7 +15,6 @@ health_check_config { service_name: "service" authority: "wwnvoyproxy.io" } - event_log_path: "200" } actions { respond { diff --git a/test/common/upstream/health_check_corpus/grpc_generalized-crash b/test/common/upstream/health_check_corpus/grpc_generalized-crash index 0336f7d7e42e..2943aafd2d6c 100644 --- a/test/common/upstream/health_check_corpus/grpc_generalized-crash +++ b/test/common/upstream/health_check_corpus/grpc_generalized-crash @@ -20,7 +20,6 @@ health_check_config { unhealthy_interval { seconds: 4227858432 } - event_log_path: "?(" tls_options { } } diff --git a/test/common/upstream/health_check_corpus/tcp_crash-449c4bf2d000d6e56b782fdd26a86e20a7f87b4f b/test/common/upstream/health_check_corpus/tcp_crash-449c4bf2d000d6e56b782fdd26a86e20a7f87b4f index 77bff0079e8d..271c8fbacbb4 100644 --- a/test/common/upstream/health_check_corpus/tcp_crash-449c4bf2d000d6e56b782fdd26a86e20a7f87b4f +++ b/test/common/upstream/health_check_corpus/tcp_crash-449c4bf2d000d6e56b782fdd26a86e20a7f87b4f @@ -19,7 +19,6 @@ health_check_config { no_traffic_interval { seconds: 1 } - event_log_path: "200" initial_jitter { seconds: 1 } diff --git a/test/common/upstream/health_check_corpus/tcp_crash-test b/test/common/upstream/health_check_corpus/tcp_crash-test index 77bff0079e8d..271c8fbacbb4 100644 --- a/test/common/upstream/health_check_corpus/tcp_crash-test +++ b/test/common/upstream/health_check_corpus/tcp_crash-test @@ -19,7 +19,6 @@ health_check_config { no_traffic_interval { seconds: 1 } - event_log_path: "200" initial_jitter { seconds: 1 } diff --git a/test/common/upstream/health_check_corpus/tcp_crash-test-1 b/test/common/upstream/health_check_corpus/tcp_crash-test-1 index 5f7c0bdf7bc3..06be75b1fa7e 100644 --- a/test/common/upstream/health_check_corpus/tcp_crash-test-1 +++ b/test/common/upstream/health_check_corpus/tcp_crash-test-1 @@ -25,7 +25,6 @@ health_check_config { no_traffic_interval { seconds: 1 } - event_log_path: "200" initial_jitter { seconds: 1 } diff --git a/test/common/upstream/health_checker_impl_test.cc b/test/common/upstream/health_checker_impl_test.cc index dfc6177cdcc7..8e97475b2e73 100644 --- a/test/common/upstream/health_checker_impl_test.cc +++ b/test/common/upstream/health_checker_impl_test.cc @@ -8,6 +8,7 @@ #include "envoy/config/core/v3/health_check.pb.validate.h" #include "envoy/config/endpoint/v3/endpoint_components.pb.h" #include "envoy/data/core/v3/health_check_event.pb.h" +#include "envoy/extensions/health_check/event_sinks/file/v3/file.pb.h" #include "envoy/upstream/health_check_host_monitor.h" #include "source/common/buffer/buffer_impl.h" @@ -6392,15 +6393,27 @@ TEST(HealthCheckEventLoggerImplTest, All) { Filesystem::DestinationType::File, "foo"})) .WillOnce(Return(file)); + envoy::config::core::v3::HealthCheck health_check_config; + health_check_config.set_event_log_path("foo"); + + NiceMock cluster; + Runtime::MockLoader runtime; + Event::MockDispatcher dispatcher; + NiceMock validation_visitor; + NiceMock api; + std::shared_ptr host(new NiceMock()); - NiceMock cluster; - ON_CALL(*host, cluster()).WillByDefault(ReturnRef(cluster)); + NiceMock cluster_info; + ON_CALL(*host, cluster()).WillByDefault(ReturnRef(cluster_info)); + + HealthCheckerFactoryContextImpl context(cluster, runtime, dispatcher, validation_visitor, api, + log_manager); Event::SimulatedTimeSystem time_system; // This is rendered as "2009-02-13T23:31:31.234Z".a time_system.setSystemTime(std::chrono::milliseconds(1234567891234)); - HealthCheckEventLoggerImpl event_logger(log_manager, time_system, "foo"); + HealthCheckEventLoggerImpl event_logger(log_manager, time_system, health_check_config, context); EXPECT_CALL(*file, write(absl::string_view{ "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" @@ -6445,6 +6458,75 @@ TEST(HealthCheckEventLoggerImplTest, All) { event_logger.logNoLongerDegraded(envoy::data::core::v3::HTTP, host); } +TEST(HealthCheckEventLoggerImplTest, OneEventLogger) { + envoy::config::core::v3::HealthCheck health_check_config; + auto event_log = health_check_config.mutable_event_logger()->Add(); + envoy::extensions::health_check::event_sinks::file::v3::HealthCheckEventFileSink config; + config.set_event_log_path("foo"); + event_log->mutable_typed_config()->PackFrom(config); + + NiceMock log_manager; + StringViewSaver file_log_data; + ON_CALL(*log_manager.file_, write(_)).WillByDefault(SaveArg<0>(&file_log_data)); + + NiceMock cluster; + Runtime::MockLoader runtime; + Event::MockDispatcher dispatcher; + NiceMock validation_visitor; + NiceMock api; + + std::shared_ptr host(new NiceMock()); + NiceMock cluster_info; + ON_CALL(*host, cluster()).WillByDefault(ReturnRef(cluster_info)); + + HealthCheckerFactoryContextImpl context(cluster, runtime, dispatcher, validation_visitor, api, + log_manager); + + Event::SimulatedTimeSystem time_system; + // This is rendered as "2009-02-13T23:31:31.234Z".a + time_system.setSystemTime(std::chrono::milliseconds(1234567891234)); + + HealthCheckEventLoggerImpl event_logger(log_manager, time_system, health_check_config, context); + + event_logger.logEjectUnhealthy(envoy::data::core::v3::HTTP, host, envoy::data::core::v3::ACTIVE); + EXPECT_EQ(file_log_data, "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" + "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\"," + "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_" + "cluster\",\"eject_unhealthy_event\":{\"failure_type\":\"ACTIVE\"}," + "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"); + + event_logger.logAddHealthy(envoy::data::core::v3::HTTP, host, false); + EXPECT_EQ(file_log_data, "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" + "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\"," + "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_" + "cluster\",\"add_healthy_event\":{\"first_check\":false},\"timestamp\":" + "\"2009-02-13T23:31:31.234Z\"}\n"); + + event_logger.logUnhealthy(envoy::data::core::v3::HTTP, host, envoy::data::core::v3::ACTIVE, + false); + EXPECT_EQ(file_log_data.value(), + "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" + "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\"," + "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_" + "cluster\",\"health_check_failure_event\":{\"failure_type\":\"ACTIVE\"," + "\"first_check\":false}," + "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"); + + event_logger.logDegraded(envoy::data::core::v3::HTTP, host); + EXPECT_EQ(file_log_data, "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" + "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\"," + "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_" + "cluster\",\"degraded_healthy_host\":{}," + "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"); + + event_logger.logNoLongerDegraded(envoy::data::core::v3::HTTP, host); + EXPECT_EQ(file_log_data, "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" + "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\"," + "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_" + "cluster\",\"no_longer_degraded_host\":{}," + "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"); +} + // Validate that the proto constraints don't allow zero length edge durations. TEST(HealthCheckProto, Validation) { { diff --git a/test/extensions/health_check/event_sinks/file/BUILD b/test/extensions/health_check/event_sinks/file/BUILD new file mode 100644 index 000000000000..34a4e41306c7 --- /dev/null +++ b/test/extensions/health_check/event_sinks/file/BUILD @@ -0,0 +1,26 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_extension_cc_test( + name = "file_sink_impl_test", + srcs = ["file_sink_impl_test.cc"], + extension_names = ["envoy.health_check.event_sinks.file"], + deps = [ + "//source/extensions/health_check/event_sinks/file:file_sink_lib", + "//test/mocks/access_log:access_log_mocks", + "//test/mocks/server:health_checker_factory_context_mocks", + "//test/test_common:environment_lib", + "//test/test_common:utility_lib", + "@envoy_api//envoy/extensions/health_check/event_sinks/file/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/health_check/event_sinks/file/file_sink_impl_test.cc b/test/extensions/health_check/event_sinks/file/file_sink_impl_test.cc new file mode 100644 index 000000000000..a7945dcb6951 --- /dev/null +++ b/test/extensions/health_check/event_sinks/file/file_sink_impl_test.cc @@ -0,0 +1,106 @@ +#include "envoy/extensions/health_check/event_sinks/file/v3/file.pb.h" +#include "envoy/extensions/health_check/event_sinks/file/v3/file.pb.validate.h" +#include "envoy/registry/registry.h" + +#include "source/common/protobuf/message_validator_impl.h" +#include "source/extensions/health_check/event_sinks/file/file_sink_impl.h" + +#include "test/mocks/access_log/mocks.h" +#include "test/mocks/event/mocks.h" +#include "test/mocks/server/health_checker_factory_context.h" +#include "test/mocks/stats/mocks.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using testing::SaveArg; + +namespace Envoy { +namespace Upstream { + +TEST(HealthCheckEventFileSinkFactory, createHealthCheckEventSink) { + auto factory = Envoy::Registry::FactoryRegistry::getFactory( + "envoy.health_check.event_sink.file"); + EXPECT_NE(factory, nullptr); + + envoy::extensions::health_check::event_sinks::file::v3::HealthCheckEventFileSink config; + config.set_event_log_path("test_path"); + Envoy::ProtobufWkt::Any typed_config; + typed_config.PackFrom(config); + + NiceMock context; + EXPECT_NE(factory->createHealthCheckEventSink(typed_config, context), nullptr); +} + +TEST(HealthCheckEventFileSinkFactory, createEmptyHealthCheckEventSink) { + auto factory = Envoy::Registry::FactoryRegistry::getFactory( + "envoy.health_check.event_sink.file"); + EXPECT_NE(factory, nullptr); + auto empty_proto = factory->createEmptyConfigProto(); + auto config = *dynamic_cast< + envoy::extensions::health_check::event_sinks::file::v3::HealthCheckEventFileSink*>( + empty_proto.get()); + EXPECT_TRUE(config.event_log_path().empty()); +} + +TEST(HealthCheckEventFileSink, logTest) { + envoy::extensions::health_check::event_sinks::file::v3::HealthCheckEventFileSink config; + config.set_event_log_path("test_path"); + NiceMock log_manager; + StringViewSaver file_log_data; + ON_CALL(*log_manager.file_, write(_)).WillByDefault(SaveArg<0>(&file_log_data)); + + HealthCheckEventFileSink file_sink(config, log_manager); + + envoy::data::core::v3::HealthCheckEvent event; + TestUtility::loadFromYaml(R"EOF( + health_checker_type: HTTP + host: + socket_address: + protocol: TCP + address: 10.0.0.1 + resolver_name: '' + ipv4_compat: false + port_value: 443 + cluster_name: fake_cluster + eject_unhealthy_event: + failure_type: ACTIVE + timestamp: '2009-02-13T23:31:31.234Z' + )EOF", + event); + + file_sink.log(event); + EXPECT_EQ(file_log_data, "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" + "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\"," + "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_" + "cluster\",\"eject_unhealthy_event\":{\"failure_type\":\"ACTIVE\"}," + "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"); + + envoy::data::core::v3::HealthCheckEvent add_event; + TestUtility::loadFromYaml(R"EOF( + health_checker_type: HTTP + host: + socket_address: + protocol: TCP + address: 10.0.0.1 + resolver_name: '' + ipv4_compat: false + port_value: 443 + cluster_name: fake_cluster + add_healthy_event: + first_check: false + timestamp: '2009-02-13T23:31:31.234Z' + )EOF", + add_event); + + file_sink.log(add_event); + EXPECT_EQ(file_log_data, "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{" + "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\"," + "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_" + "cluster\",\"add_healthy_event\":{\"first_check\":false},\"timestamp\":" + "\"2009-02-13T23:31:31.234Z\"}\n"); +} + +} // namespace Upstream +} // namespace Envoy diff --git a/test/mocks/server/BUILD b/test/mocks/server/BUILD index 6ee47f2e1d7c..8ebe31e1ec73 100644 --- a/test/mocks/server/BUILD +++ b/test/mocks/server/BUILD @@ -275,6 +275,7 @@ envoy_cc_mock( deps = [ "//envoy/server:health_checker_config_interface", "//test/mocks:common_lib", + "//test/mocks/access_log:access_log_mocks", "//test/mocks/api:api_mocks", "//test/mocks/event:event_mocks", "//test/mocks/protobuf:protobuf_mocks", diff --git a/test/mocks/server/health_checker_factory_context.cc b/test/mocks/server/health_checker_factory_context.cc index 45d2de4315a1..f8a3ed362352 100644 --- a/test/mocks/server/health_checker_factory_context.cc +++ b/test/mocks/server/health_checker_factory_context.cc @@ -19,6 +19,7 @@ MockHealthCheckerFactoryContext::MockHealthCheckerFactoryContext() { ON_CALL(*this, messageValidationVisitor()) .WillByDefault(ReturnRef(ProtobufMessage::getStrictValidationVisitor())); ON_CALL(*this, api()).WillByDefault(ReturnRef(api_)); + ON_CALL(*this, accessLogManager()).WillByDefault(ReturnRef(access_log_manager_)); } MockHealthCheckerFactoryContext::~MockHealthCheckerFactoryContext() = default; diff --git a/test/mocks/server/health_checker_factory_context.h b/test/mocks/server/health_checker_factory_context.h index d4bc31b438d2..85d8af23b9bd 100644 --- a/test/mocks/server/health_checker_factory_context.h +++ b/test/mocks/server/health_checker_factory_context.h @@ -2,6 +2,7 @@ #include "envoy/server/health_checker_config.h" +#include "test/mocks/access_log/mocks.h" #include "test/mocks/api/mocks.h" #include "test/mocks/common.h" #include "test/mocks/event/mocks.h" @@ -29,6 +30,9 @@ class MockHealthCheckerFactoryContext : public virtual HealthCheckerFactoryConte MOCK_METHOD(Envoy::Runtime::Loader&, runtime, ()); MOCK_METHOD(ProtobufMessage::ValidationVisitor&, messageValidationVisitor, ()); MOCK_METHOD(Api::Api&, api, ()); + MOCK_METHOD(AccessLog::AccessLogManager&, accessLogManager, ()); + MOCK_METHOD(void, setEventLogger, (Upstream::HealthCheckEventLoggerPtr)); + Upstream::HealthCheckEventLoggerPtr eventLogger() override { if (!event_logger_) { event_logger_ = std::make_unique>(); @@ -41,6 +45,7 @@ class MockHealthCheckerFactoryContext : public virtual HealthCheckerFactoryConte testing::NiceMock random_; testing::NiceMock runtime_; testing::NiceMock api_{}; + testing::NiceMock access_log_manager_; std::unique_ptr> event_logger_; }; diff --git a/test/server/server_corpus/clusterfuzz-testcase-config_fuzz_test-4788023076847616 b/test/server/server_corpus/clusterfuzz-testcase-config_fuzz_test-4788023076847616 index 37d9bdc530f1..60c47ab5943c 100644 --- a/test/server/server_corpus/clusterfuzz-testcase-config_fuzz_test-4788023076847616 +++ b/test/server/server_corpus/clusterfuzz-testcase-config_fuzz_test-4788023076847616 @@ -46,7 +46,6 @@ static_resources { seconds: 2559 nanos: 16384 } - event_log_path: "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" interval_jitter_percent: 524288 tls_options { alpn_protocols: "/" diff --git a/test/server/server_corpus/clusterfuzz-testcase-minimized-config_fuzz_test-5666128418832384 b/test/server/server_corpus/clusterfuzz-testcase-minimized-config_fuzz_test-5666128418832384 index 70e8a1ecb3eb..59693aa628f5 100644 --- a/test/server/server_corpus/clusterfuzz-testcase-minimized-config_fuzz_test-5666128418832384 +++ b/test/server/server_corpus/clusterfuzz-testcase-minimized-config_fuzz_test-5666128418832384 @@ -85,7 +85,6 @@ node { id: " " cluster: " " build_version: " " } static_resou service_name: "0" use_http2: true } - event_log_path: "c" } tls_context { common_tls_context { diff --git a/test/server/server_corpus/clusterfuzz-testcase-minimized-server_fuzz_test-5733243234811904 b/test/server/server_corpus/clusterfuzz-testcase-minimized-server_fuzz_test-5733243234811904 index a66f1e06095d..d58632ba4e42 100644 --- a/test/server/server_corpus/clusterfuzz-testcase-minimized-server_fuzz_test-5733243234811904 +++ b/test/server/server_corpus/clusterfuzz-testcase-minimized-server_fuzz_test-5733243234811904 @@ -49,7 +49,6 @@ static_resources { seconds: 2299 nanos: 16384 } - event_log_path: "%" always_log_health_check_failures: true } typed_extension_protocol_options { diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index 0aff6d44d5ae..fed59e924743 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -436,6 +436,7 @@ visibility_excludes: - source/extensions/quic/server_preferred_address/BUILD - source/extensions/listener_managers/listener_manager/BUILD - source/extensions/upstreams/tcp/BUILD +- source/extensions/health_check/event_sinks/BUILD - source/extensions/health_checkers/BUILD - source/extensions/health_checkers/BUILD - source/extensions/health_checkers/BUILD diff --git a/tools/extensions/extensions_schema.yaml b/tools/extensions/extensions_schema.yaml index 7558fb7f8068..030939c667b9 100644 --- a/tools/extensions/extensions_schema.yaml +++ b/tools/extensions/extensions_schema.yaml @@ -76,6 +76,7 @@ categories: - envoy.grpc_credentials - envoy.guarddog_actions - envoy.health_checkers +- envoy.health_check.event_sinks - envoy.http.cache - envoy.http.header_validators - envoy.http.stateful_header_formatters From c6292584f59eac45bf43f3dba7b0f8c36b3ab0bc Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 25 May 2023 15:55:34 +0100 Subject: [PATCH 095/228] ci: Add github workflow for verify examples (#27371) Signed-off-by: Ryan Northey --- .azure-pipelines/stage/verify.yml | 81 ++++++++++++----------- .azure-pipelines/stages.yml | 6 ++ .github/workflows/check-deps.yml | 8 ++- .github/workflows/envoy-verify.yml | 88 +++++++++++++++++++++++++ .github/workflows/mobile_release.yml | 7 +- .github/workflows/pr_notifier.yml | 7 +- .github/workflows/stale.yml | 7 +- .github/workflows/workflow-complete.yml | 61 +++++++++++++++++ .github/workflows/workflow-start.yml | 38 +++++++++++ bazel/repositories.bzl | 10 +++ ci/do_ci.sh | 33 ++++++++++ ci/run_envoy_docker.sh | 6 ++ ci/upload_gcs_artifact.sh | 4 +- tools/base/requirements.in | 2 +- 14 files changed, 312 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/envoy-verify.yml create mode 100644 .github/workflows/workflow-complete.yml create mode 100644 .github/workflows/workflow-start.yml diff --git a/.azure-pipelines/stage/verify.yml b/.azure-pipelines/stage/verify.yml index 5f7ddabe3d02..238d7b4da974 100644 --- a/.azure-pipelines/stage/verify.yml +++ b/.azure-pipelines/stage/verify.yml @@ -9,55 +9,59 @@ parameters: - name: authGCP type: string default: "" +- name: authGithubWorkflow + type: string + default: "" +- name: authGithubWorkflowAppId + type: string + default: "" +- name: authGithubWorkflowInstallId + type: string + default: "" + +- name: runDocker + displayName: "Run Docker" + type: string + default: true + +# TODO(phlax): improve docker publishing job and move this there jobs: - job: examples displayName: Examples (Docker/x64) - condition: and(not(canceled()), succeeded(), ne(stageDependencies.env.repo.outputs['changed.mobileOnly'], 'true'), ne(stageDependencies.env.repo.outputs['changed.docsOnly'], 'true')) + condition: | + and(not(canceled()), + eq(${{ parameters.runDocker }}, 'true')) + timeoutInMinutes: 120 pool: vmImage: "ubuntu-20.04" steps: - - bash: .azure-pipelines/cleanup.sh - displayName: "Removing tools from agent" - - bash: | - set -e - - if [[ "$BUILD_REASON" == "PullRequest" ]]; then - DOWNLOAD_PATH="$(git rev-parse HEAD | head -c7)" - else - DOWNLOAD_PATH="${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER:-${BUILD_SOURCEBRANCHNAME}}" - fi - - tmpdir=$(mktemp -d) - cd "$tmpdir" - images=("" "contrib" "google-vrp") - for image in "${images[@]}"; do - if [[ -n "$image" ]]; then - variant="${image}-dev" - filename="envoy-${image}.tar" - else - variant=dev - filename="envoy.tar" - fi - echo "Download docker image (https://storage.googleapis.com/${{ parameters.bucketGCP }}/${DOWNLOAD_PATH}/docker/${filename}) ..." - curl -sLO "https://storage.googleapis.com/${{ parameters.bucketGCP }}/${DOWNLOAD_PATH}/docker/${filename}" - echo "Copy oci image: oci-archive:${filename} docker-daemon:envoyproxy/envoy:${variant}" - skopeo copy -q "oci-archive:${filename}" "docker-daemon:envoyproxy/envoy:${variant}" - rm "$filename" - done - docker images | grep envoy + - task: DownloadSecureFile@1 + name: WorkflowTriggerKey + displayName: 'Download workflow trigger key' + inputs: + secureFile: '${{ parameters.authGithubWorkflow }}' - bash: | set -e - export DEBIAN_FRONTEND=noninteractive - sudo apt-get -qq update -y - sudo apt-get -qq install -y --no-install-recommends expect + KEY="$(cat $(WorkflowTriggerKey.secureFilePath) | base64 -w0)" + echo "##vso[task.setvariable variable=value;isoutput=true]$KEY" + name: key - - bash: ./ci/do_ci.sh verify_examples - env: - ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) - NO_BUILD_SETUP: 1 - # ENVOY_EXAMPLES_DEBUG: 1 + - template: ../bazel.yml + parameters: + ciTarget: verify.trigger + authGithub: "$(key.value)" + # Please see `ci/do_ci.sh` for notes on required vars. + env: + ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: + ENVOY_BRANCH: "$(System.PullRequest.TargetBranch)" + ENVOY_COMMIT: "$(System.PullRequest.SourceCommitId)" + ENVOY_HEAD_REF: "$(Build.SourceBranch)" + ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: + ENVOY_BRANCH: "$(Build.SourceBranch)" + GITHUB_APP_ID: ${{ parameters.authGithubWorkflowAppId }} + GITHUB_INSTALL_ID: ${{ parameters.authGithubWorkflowInstallId }} - job: packages_x64 displayName: Debs (x64) @@ -83,6 +87,7 @@ jobs: BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} displayName: "Verify packages" + - job: packages_arm64 displayName: Debs (arm64) condition: and(not(canceled()), succeeded(), ne(stageDependencies.env.repo.outputs['changed.mobileOnly'], 'true'), ne(stageDependencies.env.repo.outputs['changed.docsOnly'], 'true'), ne(stageDependencies.env.repo.outputs['changed.examplesOnly'], 'true')) diff --git a/.azure-pipelines/stages.yml b/.azure-pipelines/stages.yml index 6a36bb8da161..e678f892e541 100644 --- a/.azure-pipelines/stages.yml +++ b/.azure-pipelines/stages.yml @@ -169,11 +169,17 @@ stages: - stage: verify displayName: Verify dependsOn: ["env", "publish"] + variables: + RUN_DOCKER: $[stageDependencies.env.repo.outputs['run.docker']] jobs: - template: stage/verify.yml parameters: authGCP: $(GcpServiceAccountKey) bucketGCP: $(GcsArtifactBucket) + authGithubWorkflow: $(GitHubPublicRepoWorkflowKey) + authGithubWorkflowAppId: $(GitHubPublicRepoWorkflowAppId) + authGithubWorkflowInstallId: $(GitHubPublicRepoWorkflowInstallId) + runDocker: variables['RUN_DOCKER'] - stage: macos displayName: macOS diff --git a/.github/workflows/check-deps.yml b/.github/workflows/check-deps.yml index 1744e3fa332e..bb98ec2f36d7 100644 --- a/.github/workflows/check-deps.yml +++ b/.github/workflows/check-deps.yml @@ -3,7 +3,6 @@ name: Check dependencies on: schedule: - cron: '0 8 * * *' - workflow_dispatch: permissions: read-all @@ -11,7 +10,12 @@ permissions: read-all jobs: build: runs-on: ubuntu-20.04 - if: github.repository == 'envoyproxy/envoy' + if: | + ${{ + github.repository == 'envoyproxy/envoy' + && (github.event.schedule + || !contains(github.actor, '[bot]')) + }} permissions: contents: read # to fetch code (actions/checkout) issues: write # required to open/close dependency issues diff --git a/.github/workflows/envoy-verify.yml b/.github/workflows/envoy-verify.yml new file mode 100644 index 000000000000..be10ceb57304 --- /dev/null +++ b/.github/workflows/envoy-verify.yml @@ -0,0 +1,88 @@ +name: Verify/examples + +on: + # This runs untrusted code, do not expose secrets in the verify job + workflow_dispatch: + inputs: + ref: + description: "Git SHA ref to checkout" + sha: + description: "Git SHA of commit HEAD (ie last commit of PR)" + head_ref: + description: "Ref for grouping PRs" + +concurrency: + group: ${{ github.event.inputs.head_ref || github.run_id }}-${{ github.workflow }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + check: + if: | + ${{ + github.repository == 'envoyproxy/envoy' + && (!contains(github.actor, '[bot]') + || github.actor == trigger-workflow-envoy[bot]) + }} + uses: ./.github/workflows/workflow-start.yml + permissions: + contents: read + statuses: write + with: + workflowName: ${{ github.workflow }} + + # Runs untrusted code + verify-examples: + runs-on: ubuntu-20.04 + needs: check + steps: + # Checkout the repo at provided commit + - name: 'Checkout Repository' + uses: actions/checkout@v3 + with: + ref: "${{ inputs.ref }}" + + - run: | + set -e + + BUCKET="envoy-postsubmit" + PULL_REGEX="^refs/pull/*" + if [[ "${{ inputs.head_ref }}" =~ ${PULL_REGEX} ]]; then + BUCKET="envoy-pr" + fi + + DOWNLOAD_PATH="$(echo "${{ github.event.inputs.sha }}" | head -c 7)" + + tmpdir=$(mktemp -d) + cd "$tmpdir" + images=("" "contrib" "google-vrp") + for image in "${images[@]}"; do + if [[ -n "$image" ]]; then + variant="${image}-dev" + filename="envoy-${image}.tar" + else + variant=dev + filename="envoy.tar" + fi + fileurl="https://storage.googleapis.com/${BUCKET}/${DOWNLOAD_PATH}/docker/${filename}" + echo "Download docker image (${fileurl}) ..." + curl -sLO "$fileurl" + echo "Copy oci image: oci-archive:${filename} docker-daemon:envoyproxy/envoy:${variant}" + skopeo copy -q "oci-archive:${filename}" "docker-daemon:envoyproxy/envoy:${variant}" + rm "$filename" + done + docker images | grep envoy + + - run: | + set -e + export DEBIAN_FRONTEND=noninteractive + sudo apt-get -qq update -y + sudo apt-get -qq install -y --no-install-recommends expect + + - run: | + ./ci/do_ci.sh verify_examples + env: + NO_BUILD_SETUP: 1 + # ENVOY_EXAMPLES_DEBUG: 1 diff --git a/.github/workflows/mobile_release.yml b/.github/workflows/mobile_release.yml index 8beed1ab6268..df91222186e8 100644 --- a/.github/workflows/mobile_release.yml +++ b/.github/workflows/mobile_release.yml @@ -8,7 +8,12 @@ on: jobs: android_release_artifacts: - if: github.repository == 'envoyproxy/envoy' + if: | + ${{ + github.repository == 'envoyproxy/envoy' + && (github.event.schedule + || !contains(github.actor, '[bot]')) + }} name: android_release_artifacts runs-on: ubuntu-20.04 timeout-minutes: 120 diff --git a/.github/workflows/pr_notifier.yml b/.github/workflows/pr_notifier.yml index 782ad94075da..ac913f34f2e1 100644 --- a/.github/workflows/pr_notifier.yml +++ b/.github/workflows/pr_notifier.yml @@ -14,7 +14,12 @@ jobs: pull-requests: read # for pr_notifier.py name: PR Notifier runs-on: ubuntu-20.04 - if: github.repository == 'envoyproxy/envoy' + if: | + ${{ + github.repository == 'envoyproxy/envoy' + && (github.event.schedule + || !contains(github.actor, '[bot]')) + }} steps: - uses: actions/checkout@v3 - name: Set up Python 3.8 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c544b7374e6f..faec7e043697 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,12 @@ jobs: pull-requests: write # for actions/stale to close stale PRs name: Prune Stale runs-on: ubuntu-20.04 - if: github.repository == 'envoyproxy/envoy' + if: | + ${{ + github.repository == 'envoyproxy/envoy' + && (github.event.schedule + || !contains(github.actor, '[bot]')) + }} steps: - name: Prune Stale diff --git a/.github/workflows/workflow-complete.yml b/.github/workflows/workflow-complete.yml new file mode 100644 index 000000000000..8b0d7f8c98d1 --- /dev/null +++ b/.github/workflows/workflow-complete.yml @@ -0,0 +1,61 @@ +name: Workflow complete +# This workflow is only required for externally triggered jobs that have manually +# set the check status for a commit/PR + +on: + # Do not run untrusted code here + workflow_run: + workflows: + - Verify/examples + types: + - completed + +permissions: + contents: read + +jobs: + complete: + runs-on: ubuntu-20.04 + permissions: + statuses: write + steps: + - name: 'Download artifact' + uses: actions/github-script@v6 + with: + script: | + let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name == "state_sha" + })[0]; + let download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + let fs = require('fs'); + fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/state_sha.zip`, Buffer.from(download.data)); + + - run: | + set -e + unzip state_sha.zip + STATE_SHA="$(cat state_sha)" + echo "state_sha=$STATE_SHA" >> "$GITHUB_OUTPUT" + STATE="${{ github.event.workflow_run.conclusion }}" + if [[ ${STATE} != "success" ]]; then + STATE=failure + fi + echo "state=${STATE}" >> "$GITHUB_OUTPUT" + id: job + - name: Complete status check + uses: envoyproxy/toolshed/gh-actions/status@a6e1c951217efae1ac6b2bf32c5a9729976442b8 + with: + authToken: ${{ secrets.GITHUB_TOKEN }} + context: ${{ github.event.workflow.name }} + state: ${{ steps.job.outputs.state }} + sha: ${{ steps.job.outputs.state_sha }} + target_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }} diff --git a/.github/workflows/workflow-start.yml b/.github/workflows/workflow-start.yml new file mode 100644 index 000000000000..64c2999c1201 --- /dev/null +++ b/.github/workflows/workflow-start.yml @@ -0,0 +1,38 @@ +name: Workflow start +# This workflow is only required for externally triggered jobs that need to manually +# set the check status for a commit/PR + +on: + workflow_call: + inputs: + workflowName: + required: true + type: string + +permissions: + contents: read + +jobs: + start: + runs-on: ubuntu-20.04 + permissions: + statuses: write + steps: + - name: Start status check + uses: envoyproxy/toolshed/gh-actions/status@a6e1c951217efae1ac6b2bf32c5a9729976442b8 + with: + authToken: ${{ secrets.GITHUB_TOKEN }} + context: ${{ inputs.workflowName }} + state: 'pending' + sha: ${{ inputs.sha }} + target_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + - name: Save the SHA + env: + STATE_SHA: ${{ inputs.sha }} + run: | + mkdir -p ./sha + echo $STATE_SHA > ./sha/state_sha + - uses: actions/upload-artifact@v3 + with: + name: state_sha + path: sha/ diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index c77baa9b132c..c52716a570cd 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -164,6 +164,16 @@ envoy_entry_point( script = "envoy.project", ) +envoy_entry_point( + name = "trigger", + args = [ + "trigger", + PATH, + ], + pkg = "envoy.base.utils", + script = "envoy.project", +) + ''') _envoy_repo = repository_rule( diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 4d516321753c..21fd47eae66d 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -717,6 +717,39 @@ case $CI_TARGET in run_ci_verify "*" "win32-front-proxy|shared" ;; + verify.trigger) + setup_clang_toolchain + WORKFLOW="envoy-verify.yml" + # * Note on vars * + # `ENVOY_REPO`: Should always be envoyproxy/envoy unless testing + # `ENVOY_BRANCH`: Target branch for PRs, source branch for others + # `COMMIT`: This may be a merge commit in a PR + # `ENVOY_COMMIT`: The actual last commit of branch/PR + # `ENVOY_HEAD_REF`: must also be set in PRs to provide a unique key for job grouping, + # cancellation, and to discriminate from other branch CI + COMMIT="$(git rev-parse HEAD)" + ENVOY_COMMIT="${ENVOY_COMMIT:-${COMMIT}}" + ENVOY_REPO="${ENVOY_REPO:-envoyproxy/envoy}" + echo "Trigger workflow (${WORKFLOW})" + echo " Repo: ${ENVOY_REPO}" + echo " Branch: ${ENVOY_BRANCH}" + echo " Ref: ${COMMIT}" + echo " Inputs:" + echo " sha: ${ENVOY_COMMIT}" + echo " head_ref: ${ENVOY_HEAD_REF}" + GITHUB_APP_KEY="$(echo "$GITHUB_TOKEN" | base64 -d -w0)" + export GITHUB_APP_KEY + INPUTS="{\"ref\":\"$COMMIT\",\"sha\":\"$ENVOY_COMMIT\",\"head_ref\":\"$ENVOY_HEAD_REF\"}" + bazel run "${BAZEL_BUILD_OPTIONS[@]}" \ + @envoy_repo//:trigger \ + -- --repo="$ENVOY_REPO" \ + --trigger-app-id="$GITHUB_APP_ID" \ + --trigger-installation-id="$GITHUB_INSTALL_ID" \ + --trigger-ref="$ENVOY_BRANCH" \ + --trigger-workflow="$WORKFLOW" \ + --trigger-inputs="$INPUTS" + ;; + *) echo "Invalid do_ci.sh target (${CI_TARGET}), see ci/README.md for valid targets." exit 1 diff --git a/ci/run_envoy_docker.sh b/ci/run_envoy_docker.sh index 30cbe0094613..7fd9bac73335 100755 --- a/ci/run_envoy_docker.sh +++ b/ci/run_envoy_docker.sh @@ -124,15 +124,21 @@ docker run --rm \ -e GOOGLE_BES_PROJECT_ID \ -e GCP_SERVICE_ACCOUNT_KEY \ -e NUM_CPUS \ + -e ENVOY_BRANCH \ -e ENVOY_RBE \ -e ENVOY_BUILD_IMAGE \ -e ENVOY_SRCDIR \ -e ENVOY_BUILD_TARGET \ -e ENVOY_BUILD_DEBUG_INFORMATION \ -e ENVOY_BUILD_FILTER_EXAMPLE \ + -e ENVOY_COMMIT \ + -e ENVOY_HEAD_REF \ + -e ENVOY_REPO \ -e SYSTEM_PULLREQUEST_PULLREQUESTNUMBER \ -e GCS_ARTIFACT_BUCKET \ -e GITHUB_TOKEN \ + -e GITHUB_APP_ID \ + -e GITHUB_INSTALL_ID \ -e NETLIFY_TRIGGER_URL \ -e BUILD_SOURCEBRANCHNAME \ -e BAZELISK_BASE_URL \ diff --git a/ci/upload_gcs_artifact.sh b/ci/upload_gcs_artifact.sh index 43c0032cc936..2c54feb13528 100755 --- a/ci/upload_gcs_artifact.sh +++ b/ci/upload_gcs_artifact.sh @@ -38,9 +38,9 @@ if [ ! -d "${SOURCE_DIRECTORY}" ]; then exit 1 fi -if [[ "$BUILD_REASON" == "PullRequest" ]] || [[ "$TARGET_SUFFIX" == "docs" ]]; then +if [[ "$BUILD_REASON" == "PullRequest" ]] || [[ "$TARGET_SUFFIX" == "docs" ]] || [[ "$TARGET_SUFFIX" == "docker" ]]; then # upload to the last commit sha (first 7 chars), either - # - docs build on main + # - docs/docker build on main, eg docs # -> https://storage.googleapis.com/envoy-postsubmit/$UPLOAD_PATH/docs/envoy-docs-rst.tar.gz # - PR build (commit sha from the developers branch) # -> https://storage.googleapis.com/envoy-pr/$UPLOAD_PATH/$TARGET_SUFFIX diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 69fd8d5d441f..75ee140ce992 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -5,7 +5,7 @@ cffi>=1.15.0 colorama coloredlogs dependatool>=0.2.2 -envoy.base.utils>=0.4.10 +envoy.base.utils>=0.4.11 envoy.code.check>=0.5.4 envoy.dependency.check>=0.1.7 envoy.distribution.release>=0.0.9 From 649057d0e138fcfed035e35959e2197fcb809c48 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 25 May 2023 12:30:13 -0400 Subject: [PATCH 096/228] test: reducing yaml in e2e tests (#27545) Signed-off-by: Alyssa Wilk --- .../integration/cds_integration_test.cc | 2 +- test/config/utility.cc | 243 ++++++++---------- test/config/utility.h | 18 +- test/integration/ads_integration.cc | 9 +- test/integration/ads_integration.h | 5 +- test/integration/ads_integration_test.cc | 10 +- test/integration/cds_integration_test.cc | 22 +- .../xds_config_tracker_integration_test.cc | 4 +- test/server/config_validation/xds_fuzz.cc | 2 +- 9 files changed, 143 insertions(+), 172 deletions(-) diff --git a/mobile/test/common/integration/cds_integration_test.cc b/mobile/test/common/integration/cds_integration_test.cc index f1a8c794e6d5..0720e4a9ce9c 100644 --- a/mobile/test/common/integration/cds_integration_test.cc +++ b/mobile/test/common/integration/cds_integration_test.cc @@ -41,7 +41,7 @@ class CdsIntegrationTest : public XdsIntegrationTest { use_xdstp_ ? cds_namespace_ + "/my_cluster?xds.node.cluster=envoy-mobile" : "my_cluster"; envoy::config::cluster::v3::Cluster cluster1 = ConfigHelper::buildStaticCluster( cluster_name, fake_upstreams_[0]->localAddress()->ip()->port(), - Network::Test::getLoopbackAddressString(ipVersion()), "ROUND_ROBIN"); + Network::Test::getLoopbackAddressString(ipVersion())); initializeXdsStream(); int cluster_count = getGaugeValue("cluster_manager.active_clusters"); // Do the initial compareDiscoveryRequest / sendDiscoveryResponse for cluster_1. diff --git a/test/config/utility.cc b/test/config/utility.cc index ab1d97d89575..ca33b39059f4 100644 --- a/test/config/utility.cc +++ b/test/config/utility.cc @@ -490,140 +490,109 @@ std::string ConfigHelper::adsBootstrap(const std::string& api_type) { } // TODO(samflattery): bundle this up with buildCluster -envoy::config::cluster::v3::Cluster ConfigHelper::buildStaticCluster(const std::string& name, - int port, - const std::string& address, - const std::string& lb_policy) { - return TestUtility::parseYaml( - fmt::format(R"EOF( - name: {} - connect_timeout: 5s - type: STATIC - load_assignment: - cluster_name: {} - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: {} - port_value: {} - health_check_config: - address: - socket_address: - address: {} - port_value: {} - lb_policy: {} - typed_extension_protocol_options: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicit_http_config: - http2_protocol_options: {{}} - )EOF", - name, name, address, port, address, port, lb_policy)); +envoy::config::cluster::v3::Cluster +ConfigHelper::buildStaticCluster(const std::string& name, int port, const std::string& address, + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { + envoy::config::cluster::v3::Cluster cluster; + cluster.mutable_connect_timeout()->set_seconds(5); + cluster.set_type(envoy::config::cluster::v3::Cluster::STATIC); + cluster.set_name(name); + cluster.mutable_load_assignment()->set_cluster_name(name); + auto* endpoint = + cluster.mutable_load_assignment()->add_endpoints()->add_lb_endpoints()->mutable_endpoint(); + auto* addr = endpoint->mutable_address(); + addr->mutable_socket_address()->set_address(address); + addr->mutable_socket_address()->set_port_value(port); + addr = endpoint->mutable_health_check_config()->mutable_address(); + addr->mutable_socket_address()->set_address(address); + addr->mutable_socket_address()->set_port_value(port); + cluster.set_lb_policy(lb_policy); + envoy::extensions::upstreams::http::v3::HttpProtocolOptions protocol_options; + protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options(); + + (*cluster.mutable_typed_extension_protocol_options()) + ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] + .PackFrom(protocol_options); + + return cluster; } envoy::config::cluster::v3::Cluster ConfigHelper::buildH1ClusterWithHighCircuitBreakersLimits( - const std::string& name, int port, const std::string& address, const std::string& lb_policy) { - return TestUtility::parseYaml( - fmt::format(R"EOF( - name: {} - connect_timeout: 50s - type: STATIC - circuit_breakers: - thresholds: - - priority: DEFAULT - max_connections: 10000 - max_pending_requests: 10000 - max_requests: 10000 - max_retries: 10000 - load_assignment: - cluster_name: {} - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: {} - port_value: {} - lb_policy: {} - )EOF", - name, name, address, port, lb_policy)); + const std::string& name, int port, const std::string& address, + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { + envoy::config::cluster::v3::Cluster cluster; + cluster.set_name(name); + cluster.mutable_connect_timeout()->set_seconds(50); + cluster.set_type(envoy::config::cluster::v3::Cluster::STATIC); + auto* threshold = cluster.mutable_circuit_breakers()->mutable_thresholds()->Add(); + threshold->set_priority(envoy::config::core::v3::RoutingPriority::DEFAULT); + threshold->mutable_max_connections()->set_value(10000); + threshold->mutable_max_pending_requests()->set_value(10000); + threshold->mutable_max_requests()->set_value(10000); + threshold->mutable_max_retries()->set_value(10000); + cluster.mutable_load_assignment()->set_cluster_name(name); + auto* endpoint = + cluster.mutable_load_assignment()->add_endpoints()->add_lb_endpoints()->mutable_endpoint(); + cluster.set_lb_policy(lb_policy); + auto* addr = endpoint->mutable_address(); + addr->mutable_socket_address()->set_address(address); + addr->mutable_socket_address()->set_port_value(port); + return cluster; } -envoy::config::cluster::v3::Cluster ConfigHelper::buildCluster(const std::string& name, - const std::string& lb_policy) { - API_NO_BOOST(envoy::config::cluster::v3::Cluster) cluster; - TestUtility::loadFromYaml(fmt::format(R"EOF( - name: {} - connect_timeout: 5s - type: EDS - eds_cluster_config: - eds_config: - resource_api_version: V3 - ads: {{}} - lb_policy: {} - typed_extension_protocol_options: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicit_http_config: - http2_protocol_options: {{}} - )EOF", - name, lb_policy), - cluster); +envoy::config::cluster::v3::Cluster +ConfigHelper::buildCluster(const std::string& name, + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { + envoy::config::cluster::v3::Cluster cluster; + cluster.mutable_connect_timeout()->set_seconds(5); + cluster.set_type(envoy::config::cluster::v3::Cluster::EDS); + cluster.set_name(name); + cluster.set_lb_policy(lb_policy); + + auto* eds = cluster.mutable_eds_cluster_config()->mutable_eds_config(); + eds->set_resource_api_version(envoy::config::core::v3::ApiVersion::V3); + eds->mutable_ads(); + + envoy::extensions::upstreams::http::v3::HttpProtocolOptions protocol_options; + protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options(); + (*cluster.mutable_typed_extension_protocol_options()) + ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] + .PackFrom(protocol_options); + return cluster; } -envoy::config::cluster::v3::Cluster ConfigHelper::buildTlsCluster(const std::string& name, - const std::string& lb_policy) { - API_NO_BOOST(envoy::config::cluster::v3::Cluster) cluster; - TestUtility::loadFromYaml( - fmt::format(R"EOF( - name: {} - connect_timeout: 5s - type: EDS - eds_cluster_config: - eds_config: - resource_api_version: V3 - ads: {{}} - transport_socket: - name: envoy.transport_sockets.tls - typed_config: - "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - common_tls_context: - validation_context: - trusted_ca: - filename: {} - lb_policy: {} - typed_extension_protocol_options: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicit_http_config: - http2_protocol_options: {{}} - )EOF", - name, - TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcacert.pem"), - lb_policy), - cluster); +envoy::config::cluster::v3::Cluster +ConfigHelper::buildTlsCluster(const std::string& name, + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { + envoy::config::cluster::v3::Cluster cluster = buildCluster(name, lb_policy); + + auto* socket = cluster.mutable_transport_socket(); + envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext tls_socket; + tls_socket.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_trusted_ca() + ->set_filename( + TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcacert.pem")); + socket->set_name("envoy.transport_sockets.tls"); + socket->mutable_typed_config()->PackFrom(tls_socket); + return cluster; } envoy::config::endpoint::v3::ClusterLoadAssignment -ConfigHelper::buildClusterLoadAssignment(const std::string& name, const std::string& address, +ConfigHelper::buildClusterLoadAssignment(const std::string& name, const std::string& address_str, uint32_t port) { API_NO_BOOST(envoy::config::endpoint::v3::ClusterLoadAssignment) cluster_load_assignment; - TestUtility::loadFromYaml(fmt::format(R"EOF( - cluster_name: {} - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: {} - port_value: {} - )EOF", - name, address, port), - cluster_load_assignment); + cluster_load_assignment.set_cluster_name(name); + auto* address = cluster_load_assignment.add_endpoints() + ->add_lb_endpoints() + ->mutable_endpoint() + ->mutable_address() + ->mutable_socket_address(); + address->set_address(address_str); + address->set_port_value(port); + return cluster_load_assignment; } @@ -631,32 +600,22 @@ envoy::config::endpoint::v3::ClusterLoadAssignment ConfigHelper::buildClusterLoadAssignmentWithLeds(const std::string& name, const std::string& leds_collection_name) { API_NO_BOOST(envoy::config::endpoint::v3::ClusterLoadAssignment) cluster_load_assignment; - TestUtility::loadFromYaml(fmt::format(R"EOF( - cluster_name: {} - endpoints: - leds_cluster_locality_config: - leds_config: - resource_api_version: V3 - ads: {{}} - leds_collection_name: {} - )EOF", - name, leds_collection_name), - cluster_load_assignment); + + cluster_load_assignment.set_cluster_name(name); + auto* lclc = cluster_load_assignment.add_endpoints()->mutable_leds_cluster_locality_config(); + auto* leds = lclc->mutable_leds_config(); + leds->set_resource_api_version(envoy::config::core::v3::ApiVersion::V3); + leds->mutable_ads(); + lclc->set_leds_collection_name(leds_collection_name); return cluster_load_assignment; } -envoy::config::endpoint::v3::LbEndpoint ConfigHelper::buildLbEndpoint(const std::string& address, - uint32_t port) { +envoy::config::endpoint::v3::LbEndpoint +ConfigHelper::buildLbEndpoint(const std::string& address_str, uint32_t port) { API_NO_BOOST(envoy::config::endpoint::v3::LbEndpoint) lb_endpoint; - TestUtility::loadFromYaml(fmt::format(R"EOF( - endpoint: - address: - socket_address: - address: {} - port_value: {} - )EOF", - address, port), - lb_endpoint); + auto* address = lb_endpoint.mutable_endpoint()->mutable_address()->mutable_socket_address(); + address->set_address(address_str); + address->set_port_value(port); return lb_endpoint; } diff --git a/test/config/utility.h b/test/config/utility.h index 61c7ee881a75..9f8101b7c604 100644 --- a/test/config/utility.h +++ b/test/config/utility.h @@ -208,19 +208,23 @@ class ConfigHelper { // Builds a standard Cluster config fragment, with a single endpoint (at address:port). static envoy::config::cluster::v3::Cluster buildStaticCluster(const std::string& name, int port, const std::string& address, - const std::string& lb_policy = "ROUND_ROBIN"); + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy = + envoy::config::cluster::v3::Cluster::ROUND_ROBIN); - static envoy::config::cluster::v3::Cluster - buildH1ClusterWithHighCircuitBreakersLimits(const std::string& name, int port, - const std::string& address, - const std::string& lb_policy = "ROUND_ROBIN"); + static envoy::config::cluster::v3::Cluster buildH1ClusterWithHighCircuitBreakersLimits( + const std::string& name, int port, const std::string& address, + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy); // ADS configurations static envoy::config::cluster::v3::Cluster - buildCluster(const std::string& name, const std::string& lb_policy = "ROUND_ROBIN"); + buildCluster(const std::string& name, + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy = + envoy::config::cluster::v3::Cluster::ROUND_ROBIN); static envoy::config::cluster::v3::Cluster - buildTlsCluster(const std::string& name, const std::string& lb_policy = "ROUND_ROBIN"); + buildTlsCluster(const std::string& name, + const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy = + envoy::config::cluster::v3::Cluster::ROUND_ROBIN); static envoy::config::endpoint::v3::ClusterLoadAssignment buildClusterLoadAssignment(const std::string& name, const std::string& ip_version, uint32_t port); diff --git a/test/integration/ads_integration.cc b/test/integration/ads_integration.cc index bff190ca146d..8272c56be18f 100644 --- a/test/integration/ads_integration.cc +++ b/test/integration/ads_integration.cc @@ -47,17 +47,18 @@ AdsIntegrationTest::AdsIntegrationTest() void AdsIntegrationTest::TearDown() { cleanUpXdsConnection(); } -envoy::config::cluster::v3::Cluster AdsIntegrationTest::buildCluster(const std::string& name, - const std::string& lb_policy) { +envoy::config::cluster::v3::Cluster +AdsIntegrationTest::buildCluster(const std::string& name, + envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { return ConfigHelper::buildCluster(name, lb_policy); } envoy::config::cluster::v3::Cluster AdsIntegrationTest::buildTlsCluster(const std::string& name) { - return ConfigHelper::buildTlsCluster(name, "ROUND_ROBIN"); + return ConfigHelper::buildTlsCluster(name, envoy::config::cluster::v3::Cluster::ROUND_ROBIN); } envoy::config::cluster::v3::Cluster AdsIntegrationTest::buildRedisCluster(const std::string& name) { - return ConfigHelper::buildCluster(name, "MAGLEV"); + return ConfigHelper::buildCluster(name, envoy::config::cluster::v3::Cluster::MAGLEV); } envoy::config::endpoint::v3::ClusterLoadAssignment diff --git a/test/integration/ads_integration.h b/test/integration/ads_integration.h index 43232c8ab070..57e9f65e2c2e 100644 --- a/test/integration/ads_integration.h +++ b/test/integration/ads_integration.h @@ -49,8 +49,9 @@ class AdsIntegrationTest : public AdsDeltaSotwIntegrationSubStateParamTest, void TearDown() override; - envoy::config::cluster::v3::Cluster buildCluster(const std::string& name, - const std::string& lb_policy = "ROUND_ROBIN"); + envoy::config::cluster::v3::Cluster + buildCluster(const std::string& name, envoy::config::cluster::v3::Cluster::LbPolicy lb_policy = + envoy::config::cluster::v3::Cluster::ROUND_ROBIN); envoy::config::cluster::v3::Cluster buildTlsCluster(const std::string& name); diff --git a/test/integration/ads_integration_test.cc b/test/integration/ads_integration_test.cc index 66242df004ba..1c6c060800ca 100644 --- a/test/integration/ads_integration_test.cc +++ b/test/integration/ads_integration_test.cc @@ -109,8 +109,8 @@ TEST_P(AdsIntegrationTest, ClusterInitializationUpdateTheOnlyWarmingCluster) { test_server_->waitForGaugeEq("cluster_manager.warming_clusters", 1); // Update lb policy to MAGLEV so that cluster update is not skipped due to the same hash. sendDiscoveryResponse( - cds_type_url, {buildCluster("cluster_0", "MAGLEV")}, {buildCluster("cluster_0", "MAGLEV")}, - {}, "2"); + cds_type_url, {buildCluster("cluster_0", envoy::config::cluster::v3::Cluster::MAGLEV)}, + {buildCluster("cluster_0", envoy::config::cluster::v3::Cluster::MAGLEV)}, {}, "2"); EXPECT_TRUE(compareDiscoveryRequest(eds_type_url, "", {"cluster_0"}, {"cluster_0"}, {})); sendDiscoveryResponse( eds_type_url, {buildClusterLoadAssignment("cluster_0")}, @@ -190,9 +190,11 @@ TEST_P(AdsIntegrationTest, ClusterInitializationUpdateOneOfThe2Warming) { sendDiscoveryResponse( cds_type_url, {ConfigHelper::buildStaticCluster("primary_cluster", 8000, "127.0.0.1"), - buildCluster("cluster_0", "MAGLEV"), buildCluster("cluster_1")}, + buildCluster("cluster_0", envoy::config::cluster::v3::Cluster::MAGLEV), + buildCluster("cluster_1")}, {ConfigHelper::buildStaticCluster("primary_cluster", 8000, "127.0.0.1"), - buildCluster("cluster_0", "MAGLEV"), buildCluster("cluster_1")}, + buildCluster("cluster_0", envoy::config::cluster::v3::Cluster::MAGLEV), + buildCluster("cluster_1")}, {}, "2"); EXPECT_TRUE(compareDiscoveryRequest(eds_type_url, "", {"cluster_0", "cluster_1"}, {"cluster_0", "cluster_1"}, {})); diff --git a/test/integration/cds_integration_test.cc b/test/integration/cds_integration_test.cc index 8e03b0421201..f3b0db0ce4b4 100644 --- a/test/integration/cds_integration_test.cc +++ b/test/integration/cds_integration_test.cc @@ -83,12 +83,14 @@ class CdsIntegrationTest : public Grpc::DeltaSotwIntegrationParamTest, public Ht // cluster in the bootstrap config - which we don't want since we're testing dynamic CDS! addFakeUpstream(upstream_codec_type_); addFakeUpstream(upstream_codec_type_); - cluster1_ = cluster_creator_( - ClusterName1, fake_upstreams_[UpstreamIndex1]->localAddress()->ip()->port(), - Network::Test::getLoopbackAddressString(ipVersion()), "ROUND_ROBIN"); - cluster2_ = cluster_creator_( - ClusterName2, fake_upstreams_[UpstreamIndex2]->localAddress()->ip()->port(), - Network::Test::getLoopbackAddressString(ipVersion()), "ROUND_ROBIN"); + cluster1_ = cluster_creator_(ClusterName1, + fake_upstreams_[UpstreamIndex1]->localAddress()->ip()->port(), + Network::Test::getLoopbackAddressString(ipVersion()), + envoy::config::cluster::v3::Cluster::ROUND_ROBIN); + cluster2_ = cluster_creator_(ClusterName2, + fake_upstreams_[UpstreamIndex2]->localAddress()->ip()->port(), + Network::Test::getLoopbackAddressString(ipVersion()), + envoy::config::cluster::v3::Cluster::ROUND_ROBIN); // Let Envoy establish its connection to the CDS server. acceptXdsConnection(); @@ -136,8 +138,9 @@ class CdsIntegrationTest : public Grpc::DeltaSotwIntegrationParamTest, public Ht // True if we decided not to run the test after all. bool test_skipped_{true}; Http::CodecType upstream_codec_type_{Http::CodecType::HTTP2}; - std::function + std::function cluster_creator_; }; @@ -239,7 +242,8 @@ TEST_P(CdsIntegrationTest, CdsClusterWithThreadAwareLbCycleUpDownUp) { // Update cluster1_ to use MAGLEV load balancer policy. cluster1_ = ConfigHelper::buildStaticCluster( ClusterName1, fake_upstreams_[UpstreamIndex1]->localAddress()->ip()->port(), - Network::Test::getLoopbackAddressString(ipVersion()), "MAGLEV"); + Network::Test::getLoopbackAddressString(ipVersion()), + envoy::config::cluster::v3::Cluster::MAGLEV); // Cyclically add and remove cluster with ThreadAwareLb. for (int i = 42; i < 142; i += 2) { diff --git a/test/integration/xds_config_tracker_integration_test.cc b/test/integration/xds_config_tracker_integration_test.cc index 96f58bdaf79c..bbc6fc04920e 100644 --- a/test/integration/xds_config_tracker_integration_test.cc +++ b/test/integration/xds_config_tracker_integration_test.cc @@ -138,10 +138,10 @@ class XdsConfigTrackerIntegrationTest : public Grpc::DeltaSotwIntegrationParamTe addFakeUpstream(Http::CodecType::HTTP2); cluster1_ = ConfigHelper::buildStaticCluster( ClusterName1, fake_upstreams_[UpstreamIndex1]->localAddress()->ip()->port(), - Network::Test::getLoopbackAddressString(ipVersion()), "ROUND_ROBIN"); + Network::Test::getLoopbackAddressString(ipVersion())); cluster2_ = ConfigHelper::buildStaticCluster( ClusterName2, fake_upstreams_[UpstreamIndex2]->localAddress()->ip()->port(), - Network::Test::getLoopbackAddressString(ipVersion()), "ROUND_ROBIN"); + Network::Test::getLoopbackAddressString(ipVersion())); acceptXdsConnection(); registerTestServerPorts({}); diff --git a/test/server/config_validation/xds_fuzz.cc b/test/server/config_validation/xds_fuzz.cc index 43ec342341c4..295c2b8b0d8b 100644 --- a/test/server/config_validation/xds_fuzz.cc +++ b/test/server/config_validation/xds_fuzz.cc @@ -12,7 +12,7 @@ namespace Envoy { // Helper functions to build API responses. envoy::config::cluster::v3::Cluster XdsFuzzTest::buildCluster(const std::string& name) { - return ConfigHelper::buildCluster(name, "ROUND_ROBIN"); + return ConfigHelper::buildCluster(name); }; envoy::config::endpoint::v3::ClusterLoadAssignment From 4168a90c65e1022073d154eb6ad24552d2cd9f4b Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 25 May 2023 17:47:56 +0100 Subject: [PATCH 097/228] ci: Cleanup/fix for verify move (#27635) Signed-off-by: Ryan Northey --- .github/workflows/envoy-verify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/envoy-verify.yml b/.github/workflows/envoy-verify.yml index be10ceb57304..adeec2c8487c 100644 --- a/.github/workflows/envoy-verify.yml +++ b/.github/workflows/envoy-verify.yml @@ -24,7 +24,7 @@ jobs: ${{ github.repository == 'envoyproxy/envoy' && (!contains(github.actor, '[bot]') - || github.actor == trigger-workflow-envoy[bot]) + || github.actor == 'trigger-workflow-envoy[bot]') }} uses: ./.github/workflows/workflow-start.yml permissions: From dde960032500887867a20557d8e5c7e29753fae0 Mon Sep 17 00:00:00 2001 From: "Dr. Andre Vehreschild" <101638173+vehre-x41@users.noreply.github.com> Date: Thu, 25 May 2023 19:14:39 +0200 Subject: [PATCH 098/228] [fuzz] Remove conn_manager from writefilter allow list (#27633) Signed-off-by: Andre Vehreschild --- .../filters/network/common/fuzz/uber_per_writefilter.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc b/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc index 696935566fb4..9ea866b9ab40 100644 --- a/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc +++ b/test/extensions/filters/network/common/fuzz/uber_per_writefilter.cc @@ -15,6 +15,10 @@ std::vector UberWriteFilterFuzzer::filterNames() { // See test/extensions/filters/network/common/fuzz/BUILD for more information. filter_names = Registry::FactoryRegistry< Server::Configuration::NamedNetworkFilterConfigFactory>::registeredNames(); + // http_connection_manager gets into the build by dependencies, but shall not be + // fuzzed in the write filter. + filter_names.erase(std::remove(filter_names.begin(), filter_names.end(), + "envoy.filters.network.http_connection_manager")); } return filter_names; } From e2ec5a085e67109f7062bbbe92aa05deb1ae6c62 Mon Sep 17 00:00:00 2001 From: "Dr. Andre Vehreschild" <101638173+vehre-x41@users.noreply.github.com> Date: Thu, 25 May 2023 20:04:47 +0200 Subject: [PATCH 099/228] [fuzz] Prevent using too deeply nested configurations by cut-off (#27631) Signed-off-by: Andre Vehreschild --- test/fuzz/mutable_visitor.cc | 2 +- test/fuzz/mutable_visitor.h | 4 +-- test/fuzz/validated_input_generator.cc | 37 ++++++++++++++------------ test/fuzz/validated_input_generator.h | 11 ++++---- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/test/fuzz/mutable_visitor.cc b/test/fuzz/mutable_visitor.cc index b011d2caff42..4e61a07e5dc9 100644 --- a/test/fuzz/mutable_visitor.cc +++ b/test/fuzz/mutable_visitor.cc @@ -16,7 +16,7 @@ namespace { void traverseMessageWorkerExt(ProtoVisitor& visitor, Protobuf::Message& message, std::vector& parents, bool was_any_or_top_level, bool recurse_into_any, - absl::string_view const& field_name) { + absl::string_view field_name) { visitor.onEnterMessage(message, parents, was_any_or_top_level, field_name); absl::Cleanup message_leaver = [&visitor, &parents, &message, was_any_or_top_level, field_name] { visitor.onLeaveMessage(message, parents, was_any_or_top_level, field_name); diff --git a/test/fuzz/mutable_visitor.h b/test/fuzz/mutable_visitor.h index 789c1dfbd8de..6cc6407de4ee 100644 --- a/test/fuzz/mutable_visitor.h +++ b/test/fuzz/mutable_visitor.h @@ -22,9 +22,9 @@ class ProtoVisitor { // Any before being unpacked for further recursion. The latter can // only be achieved by using recurse_into_any. virtual void onEnterMessage(Protobuf::Message&, absl::Span, - bool was_any_or_top_level, absl::string_view const& field_name) PURE; + bool was_any_or_top_level, absl::string_view field_name) PURE; virtual void onLeaveMessage(Protobuf::Message&, absl::Span, - bool was_any_or_top_level, absl::string_view const& field_name) PURE; + bool was_any_or_top_level, absl::string_view field_name) PURE; }; void traverseMessage(ProtoVisitor& visitor, Protobuf::Message& message, bool recurse_into_any); diff --git a/test/fuzz/validated_input_generator.cc b/test/fuzz/validated_input_generator.cc index 0eb859d10859..db9e4f3700c7 100644 --- a/test/fuzz/validated_input_generator.cc +++ b/test/fuzz/validated_input_generator.cc @@ -206,7 +206,7 @@ void ValidatedInputGenerator::handleAnyRules( void ValidatedInputGenerator::handleMessageTypedField( Protobuf::Message& msg, const Protobuf::FieldDescriptor& field, const Protobuf::Reflection* reflection, const validate::FieldRules& rules, - const absl::Span& parents, const bool force_create) { + const absl::Span& parents, bool force_create, bool cut_off) { if (field.is_repeated()) { const validate::RepeatedRules& repeated_rules = rules.repeated(); @@ -250,6 +250,9 @@ void ValidatedInputGenerator::handleMessageTypedField( break; } default: + if (cut_off) { + value->Clear(); + } break; } } @@ -264,7 +267,7 @@ void ValidatedInputGenerator::handleIntrinsicTypedField(Protobuf::Message& msg, const Protobuf::FieldDescriptor& field, const Protobuf::Reflection* reflection, const validate::FieldRules& rules, - const bool force) { + bool force) { if (field.is_repeated()) { const validate::RepeatedRules& repeated_rules = rules.repeated(); @@ -314,13 +317,13 @@ void ValidatedInputGenerator::handleIntrinsicTypedField(Protobuf::Message& msg, void ValidatedInputGenerator::onField(Protobuf::Message& msg, const Protobuf::FieldDescriptor& field, const absl::Span parents) { - onField(msg, field, parents, false); + onField(msg, field, parents, false, false); } void ValidatedInputGenerator::onField(Protobuf::Message& msg, const Protobuf::FieldDescriptor& field, const absl::Span parents, - const bool force_create) { + bool force_create, bool cut_off) { const Protobuf::Reflection* reflection = msg.GetReflection(); if (!field.options().HasExtension(validate::rules) && !force_create) { @@ -393,7 +396,7 @@ void ValidatedInputGenerator::onField(Protobuf::Message& msg, break; } case Protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { - handleMessageTypedField(msg, field, reflection, rules, parents, force_create); + handleMessageTypedField(msg, field, reflection, rules, parents, force_create, cut_off); break; } default: @@ -403,7 +406,7 @@ void ValidatedInputGenerator::onField(Protobuf::Message& msg, void ValidatedInputGenerator::onEnterMessage(Protobuf::Message& msg, absl::Span parents, - bool, absl::string_view const& field_name) { + bool, absl::string_view field_name) { ++current_depth_; const Protobuf::Reflection* reflection = msg.GetReflection(); const Protobuf::Descriptor* descriptor = msg.GetDescriptor(); @@ -416,28 +419,28 @@ void ValidatedInputGenerator::onEnterMessage(Protobuf::Message& msg, any_message->Clear(); } } + const bool max_depth_exceeded = max_depth_ > 0 && current_depth_ > max_depth_; for (int oneof_index = 0; oneof_index < descriptor->oneof_decl_count(); ++oneof_index) { const Protobuf::OneofDescriptor* oneof_desc = descriptor->oneof_decl(oneof_index); - if (oneof_desc->options().HasExtension(validate::required) && - oneof_desc->options().GetExtension(validate::required) && - !reflection->HasOneof(msg, descriptor->oneof_decl(oneof_index))) { + if (max_depth_exceeded || (oneof_desc->options().HasExtension(validate::required) && + oneof_desc->options().GetExtension(validate::required) && + !reflection->HasOneof(msg, descriptor->oneof_decl(oneof_index)))) { // No required member in one of set, so create one. for (int index = 0; index < oneof_desc->field_count(); ++index) { const std::string parents_class_name = parents.back()->GetDescriptor()->full_name(); // Treat matchers special, because in their oneof they reference themselves, which may // create long chains. Prefer the first alternative, which does not reference itself. // Nevertheless do it randomly to allow for some nesting. - if ((max_depth_ > 0 && current_depth_ > max_depth_) || - ((parents_class_name == "xds.type.matcher.v3.Matcher.MatcherList.Predicate" || - parents_class_name == - "xds.type.matcher.v3.Matcher.MatcherList.Predicate.SinglePredicate") && - (random_() % 200) > 0)) { - onField(msg, *oneof_desc->field(0), parents, true); + if ((parents_class_name == "xds.type.matcher.v3.Matcher.MatcherList.Predicate" || + parents_class_name == + "xds.type.matcher.v3.Matcher.MatcherList.Predicate.SinglePredicate") && + (random_() % 200) > 0) { + onField(msg, *oneof_desc->field(0), parents, true, max_depth_exceeded); } else { // Do not use the first available alternative all the time, because of cyclic // dependencies. const int rnd_index = random_() % oneof_desc->field_count(); - onField(msg, *oneof_desc->field(rnd_index), parents, true); + onField(msg, *oneof_desc->field(rnd_index), parents, true, max_depth_exceeded); } // Check if for the above field an entry could be created and quit the inner loop if so. // It might not be possible, when the datatype is not supported (yet). @@ -451,7 +454,7 @@ void ValidatedInputGenerator::onEnterMessage(Protobuf::Message& msg, void ValidatedInputGenerator::onLeaveMessage(Protobuf::Message&, absl::Span, bool, - absl::string_view const&) { + absl::string_view) { message_path_.pop_back(); --current_depth_; } diff --git a/test/fuzz/validated_input_generator.h b/test/fuzz/validated_input_generator.h index d7844217bbfe..7074e43c0852 100644 --- a/test/fuzz/validated_input_generator.h +++ b/test/fuzz/validated_input_generator.h @@ -42,7 +42,7 @@ class ValidatedInputGenerator : public ProtobufMessage::ProtoVisitor, private pg const Protobuf::Reflection* reflection, const validate::FieldRules& rules, const absl::Span& parents, - const bool force_create); + bool force_create, bool cut_off); // Handle all validation rules for intrinsic types like int, uint and string. // Messages are more complicated to handle and can not be handled here. @@ -52,19 +52,20 @@ class ValidatedInputGenerator : public ProtobufMessage::ProtoVisitor, private pg T, typename std::result_of::type>> void handleIntrinsicTypedField(Protobuf::Message& msg, const Protobuf::FieldDescriptor& field, const Protobuf::Reflection* reflection, - const validate::FieldRules& rules, const bool force); + const validate::FieldRules& rules, bool force); void onField(Protobuf::Message& msg, const Protobuf::FieldDescriptor& field, const absl::Span parents) override; void onField(Protobuf::Message& msg, const Protobuf::FieldDescriptor& field, - const absl::Span parents, const bool force_create); + const absl::Span parents, bool force_create, + bool cut_off); void onEnterMessage(Protobuf::Message& msg, absl::Span parents, - bool, absl::string_view const& field_name) override; + bool, absl::string_view field_name) override; void onLeaveMessage(Protobuf::Message&, absl::Span, bool, - absl::string_view const&) override; + absl::string_view) override; private: Mutator mutator_; From 693dab2c88a43c55185b373bbc8e955cf9afa7ad Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 25 May 2023 19:09:10 +0100 Subject: [PATCH 100/228] ci: Further cleanup/fix for verify move (#27636) Signed-off-by: Ryan Northey --- .github/workflows/envoy-verify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/envoy-verify.yml b/.github/workflows/envoy-verify.yml index adeec2c8487c..7682fe649507 100644 --- a/.github/workflows/envoy-verify.yml +++ b/.github/workflows/envoy-verify.yml @@ -53,7 +53,7 @@ jobs: BUCKET="envoy-pr" fi - DOWNLOAD_PATH="$(echo "${{ github.event.inputs.sha }}" | head -c 7)" + DOWNLOAD_PATH="$(echo "${{ inputs.ref }}" | head -c 7)" tmpdir=$(mktemp -d) cd "$tmpdir" From 17b40953f28219caf3f40e273a0ee361f6bc0826 Mon Sep 17 00:00:00 2001 From: Christoph Pakulski Date: Thu, 25 May 2023 16:46:28 -0400 Subject: [PATCH 101/228] router: add unit tests for router/delegating_route_impl (#27616) add unit tests for router/delegating_route_impl Additional Description: This is to increase coverage for common/router code which dropped after #27360. Risk Level: Low. Testing: Docs Changes: No Release Notes: No Platform Specific Features: N Fixes #27406 Signed-off-by: Christoph Pakulski --- source/common/router/delegating_route_impl.cc | 4 + source/common/router/delegating_route_impl.h | 1 + test/common/router/BUILD | 11 +++ .../router/delegating_route_impl_test.cc | 96 +++++++++++++++++++ test/mocks/router/mocks.cc | 6 ++ test/mocks/router/mocks.h | 20 ++-- test/per_file_coverage.sh | 2 +- 7 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 test/common/router/delegating_route_impl_test.cc diff --git a/source/common/router/delegating_route_impl.cc b/source/common/router/delegating_route_impl.cc index fe0df35d47b0..fb117da3bcd3 100644 --- a/source/common/router/delegating_route_impl.cc +++ b/source/common/router/delegating_route_impl.cc @@ -189,5 +189,9 @@ const EarlyDataPolicy& DelegatingRouteEntry::earlyDataPolicy() const { return base_route_->routeEntry()->earlyDataPolicy(); } +const RouteStatsContextOptRef DelegatingRouteEntry::routeStatsContext() const { + return base_route_->routeEntry()->routeStatsContext(); +} + } // namespace Router } // namespace Envoy diff --git a/source/common/router/delegating_route_impl.h b/source/common/router/delegating_route_impl.h index 9677945ed23c..422f770bded6 100644 --- a/source/common/router/delegating_route_impl.h +++ b/source/common/router/delegating_route_impl.h @@ -112,6 +112,7 @@ class DelegatingRouteEntry : public Router::RouteEntry { const ConnectConfigOptRef connectConfig() const override; const std::string& routeName() const override; const EarlyDataPolicy& earlyDataPolicy() const override; + const RouteStatsContextOptRef routeStatsContext() const override; private: const Router::RouteConstSharedPtr base_route_; diff --git a/test/common/router/BUILD b/test/common/router/BUILD index a01f8c91bf96..affe611e5150 100644 --- a/test/common/router/BUILD +++ b/test/common/router/BUILD @@ -488,6 +488,17 @@ envoy_cc_test( ], ) +envoy_cc_test( + name = "delegating_route_impl_test", + srcs = ["delegating_route_impl_test.cc"], + deps = [ + "//source/common/router:config_lib", + "//source/common/router:delegating_route_lib", + "//test/mocks/router:router_mocks", + "//test/mocks/stream_info:stream_info_mocks", + ], +) + envoy_proto_library( name = "router_fuzz_proto", srcs = ["router_fuzz.proto"], diff --git a/test/common/router/delegating_route_impl_test.cc b/test/common/router/delegating_route_impl_test.cc new file mode 100644 index 000000000000..b09cd55899d5 --- /dev/null +++ b/test/common/router/delegating_route_impl_test.cc @@ -0,0 +1,96 @@ +#include "source/common/router/delegating_route_impl.h" + +#include "test/mocks/router/mocks.h" +#include "test/mocks/stream_info/mocks.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Router { +namespace { + +using testing::Return; + +#define TEST_METHOD(method, ...) \ + EXPECT_CALL(*inner_object_ptr, method); \ + wrapper_object.method(__VA_ARGS__); + +// Verify that DelegatingRoute class forwards all calls to internal base route. +TEST(DelegatingRoute, DelegatingRouteTest) { + const std::shared_ptr inner_object_ptr = std::make_shared(); + DelegatingRoute wrapper_object(inner_object_ptr); + + TEST_METHOD(directResponseEntry); + TEST_METHOD(routeEntry); + TEST_METHOD(decorator); + TEST_METHOD(tracingConfig); + TEST_METHOD(metadata); + TEST_METHOD(typedMetadata); + + std::string name; + TEST_METHOD(mostSpecificPerFilterConfig, name); + + std::function cb; + TEST_METHOD(traversePerFilterConfig, name, cb); +} + +// Verify that DelegatingRouteEntry class forwards all calls to internal base route. +TEST(DelegatingRouteEntry, DelegatingRouteEntryTest) { + const std::shared_ptr base_route_ptr = std::make_shared(); + const std::shared_ptr inner_object_ptr = std::make_shared(); + DelegatingRouteEntry wrapper_object(base_route_ptr); + EXPECT_CALL(*base_route_ptr, routeEntry).WillRepeatedly(Return(inner_object_ptr.get())); + + Http::TestRequestHeaderMapImpl request_headers; + Http::TestResponseHeaderMapImpl response_headers; + StreamInfo::MockStreamInfo stream_info; + + TEST_METHOD(finalizeResponseHeaders, response_headers, stream_info); + TEST_METHOD(responseHeaderTransforms, stream_info); + TEST_METHOD(clusterName); + TEST_METHOD(clusterNotFoundResponseCode); + TEST_METHOD(corsPolicy); + TEST_METHOD(currentUrlPathAfterRewrite, request_headers); + TEST_METHOD(finalizeRequestHeaders, request_headers, stream_info, true); + TEST_METHOD(requestHeaderTransforms, stream_info); + TEST_METHOD(hashPolicy); + TEST_METHOD(hedgePolicy); + TEST_METHOD(priority); + TEST_METHOD(rateLimitPolicy); + TEST_METHOD(retryPolicy); + TEST_METHOD(pathMatcher); + TEST_METHOD(pathRewriter); + TEST_METHOD(internalRedirectPolicy); + TEST_METHOD(retryShadowBufferLimit); + TEST_METHOD(shadowPolicies); + TEST_METHOD(timeout); + TEST_METHOD(idleTimeout); + TEST_METHOD(usingNewTimeouts); + TEST_METHOD(maxStreamDuration); + TEST_METHOD(grpcTimeoutHeaderMax); + TEST_METHOD(grpcTimeoutHeaderOffset); + TEST_METHOD(maxGrpcTimeout); + TEST_METHOD(grpcTimeoutOffset); + TEST_METHOD(virtualCluster, request_headers); + TEST_METHOD(virtualHost); + TEST_METHOD(autoHostRewrite); + TEST_METHOD(appendXfh); + TEST_METHOD(metadataMatchCriteria); + TEST_METHOD(opaqueConfig); + TEST_METHOD(includeVirtualHostRateLimits); + TEST_METHOD(tlsContextMatchCriteria); + TEST_METHOD(pathMatchCriterion); + TEST_METHOD(includeAttemptCountInRequest); + TEST_METHOD(includeAttemptCountInResponse); + TEST_METHOD(upgradeMap); + TEST_METHOD(connectConfig); + TEST_METHOD(routeName); + TEST_METHOD(earlyDataPolicy); + TEST_METHOD(routeStatsContext); +} + +} // namespace +} // namespace Router +} // namespace Envoy diff --git a/test/mocks/router/mocks.cc b/test/mocks/router/mocks.cc index 3c77af507b18..caeed352f87f 100644 --- a/test/mocks/router/mocks.cc +++ b/test/mocks/router/mocks.cc @@ -115,6 +115,11 @@ MockRouteEntry::MockRouteEntry() { return connect_config_.has_value() ? makeOptRef(connect_config_.value()) : absl::nullopt; })); ON_CALL(*this, earlyDataPolicy()).WillByDefault(ReturnRef(early_data_policy_)); + path_matcher_ = std::make_shared>(); + ON_CALL(*this, pathMatcher()).WillByDefault(ReturnRef(path_matcher_)); + path_rewriter_ = std::make_shared>(); + ON_CALL(*this, pathRewriter()).WillByDefault(ReturnRef(path_rewriter_)); + ON_CALL(*this, routeStatsContext()).WillByDefault(Return(RouteStatsContextOptRef())); } MockRouteEntry::~MockRouteEntry() = default; @@ -143,6 +148,7 @@ MockRoute::MockRoute() { ON_CALL(*this, decorator()).WillByDefault(Return(&decorator_)); ON_CALL(*this, tracingConfig()).WillByDefault(Return(nullptr)); ON_CALL(*this, metadata()).WillByDefault(ReturnRef(metadata_)); + ON_CALL(*this, typedMetadata()).WillByDefault(ReturnRef(typed_metadata_)); } MockRoute::~MockRoute() = default; diff --git a/test/mocks/router/mocks.h b/test/mocks/router/mocks.h index 9f5976bd814f..8acad60e6201 100644 --- a/test/mocks/router/mocks.h +++ b/test/mocks/router/mocks.h @@ -438,10 +438,7 @@ class MockRouteEntry : public RouteEntry { MOCK_METHOD(const UpgradeMap&, upgradeMap, (), (const)); MOCK_METHOD(const std::string&, routeName, (), (const)); MOCK_METHOD(const EarlyDataPolicy&, earlyDataPolicy, (), (const)); - - const RouteStatsContextOptRef routeStatsContext() const override { - return RouteStatsContextOptRef(); - } + MOCK_METHOD(const RouteStatsContextOptRef, routeStatsContext, (), (const)); std::string cluster_name_{"fake_cluster"}; std::string route_name_{"fake_route_name"}; @@ -449,8 +446,8 @@ class MockRouteEntry : public RouteEntry { TestVirtualCluster virtual_cluster_; TestRetryPolicy retry_policy_; testing::NiceMock internal_redirect_policy_; - testing::NiceMock path_matcher_; - testing::NiceMock path_rewriter_; + PathMatcherSharedPtr path_matcher_; + PathRewriterSharedPtr path_rewriter_; TestHedgePolicy hedge_policy_; testing::NiceMock rate_limit_policy_; std::vector shadow_policies_; @@ -492,6 +489,16 @@ class MockRouteTracing : public RouteTracing { class MockRoute : public Route { public: + struct MockRouteMetadataObj : public Envoy::Config::TypedMetadata::Object {}; + class MockRouteMetadata : public Envoy::Config::TypedMetadata { + public: + const Envoy::Config::TypedMetadata::Object* getData(const std::string&) const override { + return &object_; + } + + private: + MockRouteMetadataObj object_; + }; MockRoute(); ~MockRoute() override; @@ -513,6 +520,7 @@ class MockRoute : public Route { testing::NiceMock decorator_; testing::NiceMock route_tracing_; envoy::config::core::v3::Metadata metadata_; + MockRouteMetadata typed_metadata_; }; class MockConfig : public Config { diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index fcc07960f9f5..0f2d76724055 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -18,7 +18,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/network/dns_resolver:91.6" # A few lines of MacOS code not tested in linux scripts. Tested in MacOS scripts "source/common/protobuf:96.3" "source/common/quic:93.5" -"source/common/router:96.2" +"source/common/router:96.6" "source/common/secret:95.0" "source/common/signal:87.2" # Death tests don't report LCOV "source/common/singleton:95.7" From 263cb1c29ef434b08e16355ff3a236f93eb995d2 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 26 May 2023 08:42:25 +0100 Subject: [PATCH 102/228] deps: Bump `edenhill_librdkafka` -> 2.1.1 (#27507) Signed-off-by: Ryan Northey Co-authored-by: Adam Kotwasinski --- bazel/foreign_cc/BUILD | 2 +- bazel/foreign_cc/librdkafka.patch | 57 +++++++++++++++++++ bazel/repositories.bzl | 4 ++ bazel/repository_locations.bzl | 6 +- .../filters/network/test/mesh/kafka_mocks.h | 18 +++++- 5 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 bazel/foreign_cc/librdkafka.patch diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index e450ecfee7b2..67caf394a107 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -55,7 +55,7 @@ cc_library( configure_make( name = "librdkafka_build", configure_in_place = True, - configure_options = ["--disable-ssl --disable-gssapi --disable-lz4-ext --disable-zstd && cp Makefile.config src/.. && cp config.h src/.."], + configure_options = ["--disable-ssl --disable-gssapi --disable-lz4-ext --disable-zstd --disable-curl && cp Makefile.config src/.. && cp config.h src/.."], lib_source = "@edenhill_librdkafka//:all", out_static_libs = [ "librdkafka.a", diff --git a/bazel/foreign_cc/librdkafka.patch b/bazel/foreign_cc/librdkafka.patch new file mode 100644 index 000000000000..a1321f77da23 --- /dev/null +++ b/bazel/foreign_cc/librdkafka.patch @@ -0,0 +1,57 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 33481ba1..681d0c5c 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -66,7 +66,6 @@ set( + tinycthread.c + tinycthread_extra.c + rdxxhash.c +- cJSON.c + ) + + if(WITH_SSL) +diff --git a/src/Makefile b/src/Makefile +index 26df5723..69bdb427 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -43,7 +43,7 @@ SRCS= rdkafka.c rdkafka_broker.c rdkafka_msg.c rdkafka_topic.c \ + rdkafka_assignor.c rdkafka_range_assignor.c \ + rdkafka_roundrobin_assignor.c rdkafka_sticky_assignor.c \ + rdkafka_feature.c \ +- rdcrc32.c crc32c.c rdmurmur2.c rdfnv1a.c cJSON.c \ ++ rdcrc32.c crc32c.c rdmurmur2.c rdfnv1a.c \ + rdaddr.c rdrand.c rdlist.c \ + tinycthread.c tinycthread_extra.c \ + rdlog.c rdstring.c rdkafka_event.c rdkafka_metadata.c \ +diff --git a/src/rdkafka.c b/src/rdkafka.c +index 33147ccd..5ed33b29 100644 +--- a/src/rdkafka.c ++++ b/src/rdkafka.c +@@ -71,9 +71,6 @@ + #include + #endif + +-#define CJSON_HIDE_SYMBOLS +-#include "cJSON.h" +- + #if WITH_CURL + #include "rdhttp.h" + #endif +@@ -139,8 +136,6 @@ void rd_kafka_set_thread_sysname(const char *fmt, ...) { + } + + static void rd_kafka_global_init0(void) { +- cJSON_Hooks json_hooks = {.malloc_fn = rd_malloc, .free_fn = rd_free}; +- + mtx_init(&rd_kafka_global_lock, mtx_plain); + #if ENABLE_DEVEL + rd_atomic32_init(&rd_kafka_op_cnt, 0); +@@ -153,8 +148,6 @@ static void rd_kafka_global_init0(void) { + rd_kafka_ssl_init(); + #endif + +- cJSON_InitHooks(&json_hooks); +- + #if WITH_CURL + rd_http_global_init(); + #endif diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index c52716a570cd..fd13e7347949 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -1308,6 +1308,10 @@ filegroup( external_http_archive( name = "edenhill_librdkafka", build_file_content = BUILD_ALL_CONTENT, + # (adam.kotwasinski) librdkafka bundles in cJSON, which is also bundled in by libvppinfra. + # For now, let's just drop this dependency from Kafka, as it's used only for monitoring. + patches = ["@envoy//bazel/foreign_cc:librdkafka.patch"], + patch_args = ["-p1"], ) native.bind( name = "librdkafka", diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 387ae12c3aaa..1236add57d89 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1202,13 +1202,13 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Kafka (C/C++ client)", project_desc = "C/C++ client for Apache Kafka (open-source distributed event streaming platform)", project_url = "https://github.com/edenhill/librdkafka", - version = "1.8.2", - sha256 = "6a747d293a7a4613bd2897e28e8791476fbe1ae7361f2530a876e0fd483482a6", + version = "2.1.1", + sha256 = "7be1fc37ab10ebdc037d5c5a9b35b48931edafffae054b488faaff99e60e0108", strip_prefix = "librdkafka-{version}", urls = ["https://github.com/edenhill/librdkafka/archive/v{version}.tar.gz"], use_category = ["dataplane_ext"], extensions = ["envoy.filters.network.kafka_mesh"], - release_date = "2021-10-18", + release_date = "2023-05-02", cpe = "N/A", license = "librdkafka", license_url = "https://github.com/edenhill/librdkafka/blob/v{version}/LICENSE", diff --git a/contrib/kafka/filters/network/test/mesh/kafka_mocks.h b/contrib/kafka/filters/network/test/mesh/kafka_mocks.h index 2e2a7efb758f..212e473101cb 100644 --- a/contrib/kafka/filters/network/test/mesh/kafka_mocks.h +++ b/contrib/kafka/filters/network/test/mesh/kafka_mocks.h @@ -42,8 +42,8 @@ class MockLibRdKafkaUtils : public LibRdKafkaUtils { // Base class for librdkafka objects. class MockKafkaHandle : public virtual RdKafka::Handle { public: - MOCK_METHOD(const std::string, name, (), (const)); - MOCK_METHOD(const std::string, memberid, (), (const)); + MOCK_METHOD(std::string, name, (), (const)); + MOCK_METHOD(std::string, memberid, (), (const)); MOCK_METHOD(int, poll, (int), ()); MOCK_METHOD(int, outq_len, (), ()); MOCK_METHOD(RdKafka::ErrorCode, metadata, @@ -59,7 +59,7 @@ class MockKafkaHandle : public virtual RdKafka::Handle { MOCK_METHOD(RdKafka::Queue*, get_partition_queue, (const RdKafka::TopicPartition*), ()); MOCK_METHOD(RdKafka::ErrorCode, set_log_queue, (RdKafka::Queue*), ()); MOCK_METHOD(void, yield, (), ()); - MOCK_METHOD(const std::string, clusterid, (int), ()); + MOCK_METHOD(std::string, clusterid, (int), ()); MOCK_METHOD(struct rd_kafka_s*, c_ptr, (), ()); MOCK_METHOD(int32_t, controllerid, (int), ()); MOCK_METHOD(RdKafka::ErrorCode, fatal_error, (std::string&), (const)); @@ -98,6 +98,10 @@ class MockKafkaProducer : public RdKafka::Producer, public MockKafkaHandle { ()); MOCK_METHOD(RdKafka::Error*, commit_transaction, (int), ()); MOCK_METHOD(RdKafka::Error*, abort_transaction, (int), ()); + MOCK_METHOD(RdKafka::Error*, sasl_background_callbacks_enable, (), ()); + MOCK_METHOD(RdKafka::Queue*, get_sasl_queue, (), ()); + MOCK_METHOD(RdKafka::Queue*, get_background_queue, (), ()); + MOCK_METHOD(RdKafka::Error*, sasl_set_credentials, (const std::string&, const std::string&), ()); }; class MockKafkaMessage : public RdKafka::Message { @@ -121,6 +125,8 @@ class MockKafkaMessage : public RdKafka::Message { MOCK_METHOD(RdKafka::Headers*, headers, ()); MOCK_METHOD(RdKafka::Headers*, headers, (RdKafka::ErrorCode*)); MOCK_METHOD(int32_t, broker_id, (), (const)); + MOCK_METHOD(int32_t, leader_epoch, (), (const)); + MOCK_METHOD(RdKafka::Error*, offset_store, ()); }; class MockKafkaConsumer : public RdKafka::KafkaConsumer, public MockKafkaHandle { @@ -144,6 +150,8 @@ class MockKafkaConsumer : public RdKafka::KafkaConsumer, public MockKafkaHandle MOCK_METHOD(RdKafka::ErrorCode, committed, (std::vector&, int), ()); MOCK_METHOD(RdKafka::ErrorCode, position, (std::vector&), ()); MOCK_METHOD(RdKafka::ErrorCode, close, (), ()); + MOCK_METHOD(RdKafka::Error*, close, (RdKafka::Queue*), ()); + MOCK_METHOD(bool, closed, (), ()); MOCK_METHOD(RdKafka::ErrorCode, seek, (const RdKafka::TopicPartition&, int), ()); MOCK_METHOD(RdKafka::ErrorCode, offsets_store, (std::vector&), ()); MOCK_METHOD(RdKafka::ConsumerGroupMetadata*, groupMetadata, (), ()); @@ -153,6 +161,10 @@ class MockKafkaConsumer : public RdKafka::KafkaConsumer, public MockKafkaHandle ()); MOCK_METHOD(RdKafka::Error*, incremental_unassign, (const std::vector&), ()); + MOCK_METHOD(RdKafka::Error*, sasl_background_callbacks_enable, (), ()); + MOCK_METHOD(RdKafka::Queue*, get_sasl_queue, (), ()); + MOCK_METHOD(RdKafka::Queue*, get_background_queue, (), ()); + MOCK_METHOD(RdKafka::Error*, sasl_set_credentials, (const std::string&, const std::string&), ()); }; } // namespace Mesh From 3cde58784b639c5e408ad793b18460859a7a5fae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 08:46:42 +0100 Subject: [PATCH 103/228] build(deps): bump nginx from `a2f6ffd` to `af296b1` in /examples/local_ratelimit (#27629) build(deps): bump nginx in /examples/local_ratelimit Bumps nginx from `a2f6ffd` to `af296b1`. --- updated-dependencies: - dependency-name: nginx dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/local_ratelimit/Dockerfile-nginx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/local_ratelimit/Dockerfile-nginx b/examples/local_ratelimit/Dockerfile-nginx index d48af7252182..d4d5b1681b33 100644 --- a/examples/local_ratelimit/Dockerfile-nginx +++ b/examples/local_ratelimit/Dockerfile-nginx @@ -1 +1 @@ -FROM nginx@sha256:a2f6ffddd272625464710d6189f1bf5d02e068392facae344762a512209e74d5 +FROM nginx@sha256:af296b188c7b7df99ba960ca614439c99cb7cf252ed7bbc23e90cfda59092305 From 0c4f903e5a63665cedac818d4f83e17ee82062ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 08:54:11 +0100 Subject: [PATCH 104/228] build(deps): bump orjson from 3.8.13 to 3.8.14 in /tools/base (#27648) Bumps [orjson](https://github.com/ijl/orjson) from 3.8.13 to 3.8.14. - [Release notes](https://github.com/ijl/orjson/releases) - [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md) - [Commits](https://github.com/ijl/orjson/compare/3.8.13...3.8.14) --- updated-dependencies: - dependency-name: orjson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 94 ++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index ab3a456306a0..a901bba652a5 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -926,53 +926,53 @@ oauth2client==4.1.3 \ # via # gcs-oauth2-boto-plugin # google-apitools -orjson==3.8.13 \ - --hash=sha256:0055168bc38c9caf7211e66e7c06d7f127d2c1dd1cd1d806c58f3a81d6074a6c \ - --hash=sha256:05bfef2719d68b44ab38061f9cd2b3a58d9994f7230734ba6d3c16db97c5e94a \ - --hash=sha256:0a3bc7e12f69f7bcefe522c4e4dac33a9b3b450aae0b3170ab61fbce0a6e1b37 \ - --hash=sha256:0ca2aced3fa6ce6d440a2a2e55bb7618fd24fce146068523472f349598e992ee \ - --hash=sha256:0d2e9a8ea45db847864868f7a566bece7d425c06627e5dbdd5fc8399a9c3330b \ - --hash=sha256:11a457fafdd207f361986750a5229fc36911fc9fdfc274d078fdf1654845ef45 \ - --hash=sha256:1234110f782af5e81893b5419b9374ca2559dbd976cbd515e6c3afc292cdfb6a \ - --hash=sha256:1316c60c0f55440e765b0211e94d171ab2c11d00fe8dcf0ac70c9bd1d9818e6b \ - --hash=sha256:14e54713703d5436a7be54ff50d780b6b09358f1a0be6107a3ea4f3537a4f6d8 \ - --hash=sha256:156bd6325a4f4a0c88556b7d774e3e18713c8134b6f807571a3eec14dfcafff6 \ - --hash=sha256:17788155c50f47d9fd037e12ac82a57381c157ea4de50e8946df8519da0f7f02 \ - --hash=sha256:246e22d167ede9ebf09685587187bde9e2440a515bd5eab2e97f029b9de57677 \ - --hash=sha256:24f923cf8d7e2e9a975f4507f93e93c262f26b4a1a4f72e4d6e75eda45de8f40 \ - --hash=sha256:2e362090bdd4261608eceefd8ed127cd2bfc48643601f9c0cf5d162ca6a7c4cd \ - --hash=sha256:305ffd227857cede7318c056020d1a3f3295e8adf8e7f2cbd78c26c530a0f234 \ - --hash=sha256:386e60a09585b2b5db84879ebad6d49427ae5a9677f86a90bff9cbbec42b03be \ - --hash=sha256:41585f90cfe24d0ae7d5bc96968617b8bcebb618e19db5b0bbadce6bc82f3455 \ - --hash=sha256:47cb98386a7ff79d0ace6a7c9d5c49ca2b4ea42e4339c565f5efe7757790dd04 \ - --hash=sha256:4b98fbca0ea0f5e56b3c1d050b78460ca9708419780ec218cef1eca424db2ee5 \ - --hash=sha256:50cfa3449157c4a4ad017a041dbb5fe37091800220fd5e651c0e5fff63bdac61 \ - --hash=sha256:5492a1d9eea5a1cb33ae6d225091c69dc79f16d952885625c00070388489d412 \ - --hash=sha256:59d79e5de4a1de246517b4c92dcf6a7ef1fb12e3ce4bbfc6c0f99d1d905405fd \ - --hash=sha256:59d81f5b9e280ac3ced615e726bfba722785cc5f7fc3aa1e0ea304c5a4114e94 \ - --hash=sha256:5e56ca7bd82b25f40955184df21c977369debe51c4b83fc3113b6427726312f3 \ - --hash=sha256:637d55ba6b48b698973d7e647b9de6bb2b424c445f51c86df4e976e672300b21 \ - --hash=sha256:6b323bb4af76c16636ac1fec403331208f978ae8a2c6bcab904ee1683c05ad7a \ - --hash=sha256:6dcccda35f11f12ebb36db0ebdca9854327530e1fffe02331cde78177851ae7f \ - --hash=sha256:6fe2981bd0f6959d821253604e9ba2c5ffa03c6202d11f0e3c190e5712b6835b \ - --hash=sha256:8075487b7b2e7cc2c44d8ee7950845b6854cd08a04df80b36055cc0236c28edd \ - --hash=sha256:8d2ce41c5992dbe9962ef75db1e70ed33636959f2f4b929f9d8cbb2e30472a08 \ - --hash=sha256:97d8444cf48f8fe2718fd3b99484906c29a909dc3a8177e8751170a9a28bcf33 \ - --hash=sha256:9b5b005841394e563f1ca3314a6884101a1b1f1dd30c569b4a0335e1ebf49fbf \ - --hash=sha256:a4a182e7a58114a81d52d67bdc034eb83571690158c4b8d3f1bf5c5f772f77b1 \ - --hash=sha256:b05ef096362c8a96fdcd85392c68156c9b680271aea350b490c2d0f3ef1b6b6a \ - --hash=sha256:b2325d8471867c99c432c96861d72d8b7336293860ebb17c9d70e1d377cc2b32 \ - --hash=sha256:bf934a036dafe63c3b1d630efaf996b85554e7ab03754019a18cc0fe2bdcc3a9 \ - --hash=sha256:c97be6a6ff4d546579f08f1d67aad92715313a06b214e3f2df9bb9f1b45765c2 \ - --hash=sha256:ce737ddf9d5f960996b63c12dbcc82ae2315c45f19165b2fe14a5b33ab8705bb \ - --hash=sha256:cf79f51a7ca59ac322a1e65430142ab1cb9c9a845e893e0e3958deaefe1c9873 \ - --hash=sha256:d30b8b9fe1ff56fb6ff64d2c2e227d49819b58ae8dac51089f393e31b39a4080 \ - --hash=sha256:e62f14f3eabccdd2108e3d5884fb66197255accc42b9ffa7f04d9dbf7336b479 \ - --hash=sha256:e792d286ad175d36f6b77b7ba77f1654a13f705a7ccfef7819e9b6d49277120d \ - --hash=sha256:ea6899624661d2258a71bde33266c3c08c8d9596865acf0ac19a9552c08fa1a6 \ - --hash=sha256:f084ce58b3fd496429deb3435aa7295ab57e349a33cdb99b3cb5f0a66a610a84 \ - --hash=sha256:f8aa77df01c60b7d8b0ff5501d6b8583a4acb06c4373c59bf769025ff8b8b4cb \ - --hash=sha256:fc42b2006abaa4fb72c9193931a9236dd85ce0483cc74079c315ce8529568ca1 +orjson==3.8.14 \ + --hash=sha256:01640ab79111dd97515cba9fab7c66cb3b0967b0892cc74756a801ff681a01b6 \ + --hash=sha256:017de5ba22e58dfa6f41914f5edb8cd052d23f171000684c26b2d2ab219db31e \ + --hash=sha256:04c70dc8ca79b0072a16d82f94b9d9dd6598a43dd753ab20039e9f7d2b14f017 \ + --hash=sha256:062829b5e20cd8648bf4c11c3a5ee7cf196fa138e573407b5312c849b0cf354d \ + --hash=sha256:087c0dc93379e8ba2d59e9f586fab8de8c137d164fccf8afd5523a2137570917 \ + --hash=sha256:09a3bf3154f40299b8bc95e9fb8da47436a59a2106fc22cae15f76d649e062da \ + --hash=sha256:0bc6b7abf27f1dc192dadad249df9b513912506dd420ce50fd18864a33789b71 \ + --hash=sha256:0bf00c42333412a9338297bf888d7428c99e281e20322070bde8c2314775508b \ + --hash=sha256:19415aaf30525a5baff0d72a089fcdd68f19a3674998263c885c3908228c1086 \ + --hash=sha256:20b7ffc7736000ea205f9143df322b03961f287b4057606291c62c842ff3c5b5 \ + --hash=sha256:27967be4c16bd09f4aeff8896d9be9cbd00fd72f5815d5980e4776f821e2f77c \ + --hash=sha256:31a2a29be559e92dcc5c278787b4166da6f0d45675b59a11c4867f5d1455ebf4 \ + --hash=sha256:33bc310da4ad2ffe8f7f1c9e89692146d9ec5aec2d1c9ef6b67f8dc5e2d63241 \ + --hash=sha256:38ca39bae7fbc050332a374062d4cdec28095540fa8bb245eada467897a3a0bb \ + --hash=sha256:3ee09bfbf1d54c127d3061f6721a1a11d2ce502b50597c3d0d2e1bd2d235b764 \ + --hash=sha256:5ea93fd3ef7be7386f2516d728c877156de1559cda09453fc7dd7b696d0439b3 \ + --hash=sha256:5fb66f0ac23e861b817c858515ac1f74d1cd9e72e3f82a5b2c9bae9f92286adc \ + --hash=sha256:6112194c11e611596eed72f46efb0e6b4812682eff3c7b48473d1146c3fa0efb \ + --hash=sha256:64b4fca0531030040e611c6037aaf05359e296877ab0a8e744c26ef9c32738b9 \ + --hash=sha256:67a7e883b6f782b106683979ccc43d89b98c28a1f4a33fe3a22e253577499bb1 \ + --hash=sha256:716a3994e039203f0a59056efa28185d4cac51b922cc5bf27ab9182cfa20e12e \ + --hash=sha256:739f9f633e1544f2a477fa3bef380f488c8dca6e2521c8dc36424b12554ee31e \ + --hash=sha256:7a7b0fead2d0115ef927fa46ad005d7a3988a77187500bf895af67b365c10d1f \ + --hash=sha256:7cb35dd3ba062c1d984d57e6477768ed7b62ed9260f31362b2d69106f9c60ebd \ + --hash=sha256:7d3d8faded5a514b80b56d0429eb38b429d7a810f8749d25dc10a0cc15b8a3c8 \ + --hash=sha256:7e2f75b7d9285e35c3d4dff9811185535ff2ea637f06b2b242cb84385f8ffe63 \ + --hash=sha256:87ba7882e146e24a7d8b4a7971c20212c2af75ead8096fc3d55330babb1015fb \ + --hash=sha256:8a896a12b38fe201a72593810abc1f4f1597e65b8c869d5fc83bbcf75d93398f \ + --hash=sha256:8b206cca6836a4c6683bcaa523ab467627b5f03902e5e1082dc59cd010e6925f \ + --hash=sha256:92374bc35b6da344a927d5a850f7db80a91c7b837de2f0ea90fc870314b1ff44 \ + --hash=sha256:9393a63cb0424515ec5e434078b3198de6ec9e057f1d33bad268683935f0a5d5 \ + --hash=sha256:9725226478d1dafe46d26f758eadecc6cf98dcbb985445e14a9c74aaed6ccfea \ + --hash=sha256:97ebb7fab5f1ae212a6501f17cb7750a6838ffc2f1cebbaa5dec1a90038ca3c6 \ + --hash=sha256:9df820e6c8c84c52ec39ea2cc9c79f7999c839c7d1481a056908dce3b90ce9f9 \ + --hash=sha256:9f5cf61b6db68f213c805c55bf0aab9b4cb75a4e9c7f5bfbd4deb3a0aef0ec53 \ + --hash=sha256:aedba48264fe87e5060c0e9c2b28909f1e60626e46dc2f77e0c8c16939e2e1f7 \ + --hash=sha256:bf6825e160e4eb0ef65ce37d8c221edcab96ff2ffba65e5da2437a60a12b3ad1 \ + --hash=sha256:ca90db8f551b8960da95b0d4cad6c0489df52ea03585b6979595be7b31a3f946 \ + --hash=sha256:d03f29b0369bb1ab55c8a67103eb3a9675daaf92f04388568034fe16be48fa5d \ + --hash=sha256:d66966fd94719beb84e8ed84833bc59c3c005d3d2d0c42f11d7552d3267c6de7 \ + --hash=sha256:de1ee13d6b6727ee1db38722695250984bae81b8fc9d05f1176c74d14b1322d9 \ + --hash=sha256:e53bc5beb612df8ddddb065f079d3fd30b5b4e73053518524423549d61177f3f \ + --hash=sha256:ebca14ae80814219ea3327e3dfa7ff618621ff335e45781fac26f5cd0b48f2b4 \ + --hash=sha256:ee0299b2dda9afce351a5e8c148ea7a886de213f955aa0288fb874fb44829c36 \ + --hash=sha256:f4ac01a3db4e6a98a8ad1bb1a3e8bfc777928939e87c04e93e0d5006df574a4b \ + --hash=sha256:f80e62afe49e6bfc706e041faa351d7520b5f86572b8e31455802251ea989613 # via # -r requirements.in # envoy-base-utils From cab680b0ef801e269f9a50cd745728d4ae8b86e6 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 26 May 2023 09:51:00 +0100 Subject: [PATCH 105/228] ci: Use `bazel.yml` for Docker publishing (#27047) Signed-off-by: Ryan Northey --- .azure-pipelines/bazel.yml | 24 ++++- .azure-pipelines/stage/publish.yml | 136 ++++++++++++++++++----------- .azure-pipelines/stage/verify.yml | 58 +----------- .azure-pipelines/stages.yml | 8 +- 4 files changed, 110 insertions(+), 116 deletions(-) diff --git a/.azure-pipelines/bazel.yml b/.azure-pipelines/bazel.yml index 7a3c701ac8ac..37c7d4735fd0 100644 --- a/.azure-pipelines/bazel.yml +++ b/.azure-pipelines/bazel.yml @@ -7,12 +7,30 @@ parameters: displayName: "Suffix of artifact" type: string default: "" + +# caching +- name: cacheKeyDocker + type: string + default: ".devcontainer/Dockerfile" +- name: cacheKeyDockerVersion + type: string + default: $(cacheKeyBuildImage) +- name: cacheKeyDockerName + type: string + default: envoy_build_image +- name: cacheKeyDockerPath + type: string + default: /mnt/docker +- name: cacheKeyDockerTmpDir + type: string + default: /mnt/docker_cache - name: cacheKey type: string default: $(cacheKeyBazelFiles) - name: cacheVersion type: string default: $(cacheKeyBazel) + - name: rbe displayName: "Enable RBE" type: boolean @@ -128,7 +146,11 @@ steps: condition: and(not(canceled()), eq(variables.BAZEL_CACHE_RESTORED, 'true')) - template: cached.yml parameters: - version: "$(cacheKeyBuildImage)" + key: "${{ parameters.cacheKeyDocker }}" + version: "${{ parameters.cacheKeyDockerVersion }}" + name: "${{ parameters.cacheKeyDockerName }}" + path: "${{ parameters.cacheKeyDockerPath }}" + tmpDirectory: "${{ parameters.cacheKeyDockerTmpDir }}" arch: "${{ parameters.artifactSuffix }}" - ${{ each step in parameters.stepsPre }}: diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml index d7c79e7cabf4..b028aa88c9ea 100644 --- a/.azure-pipelines/stage/publish.yml +++ b/.azure-pipelines/stage/publish.yml @@ -24,6 +24,15 @@ parameters: - name: authGithub type: string default: "" +- name: authGithubWorkflow + type: string + default: "" +- name: authGithubWorkflowAppId + type: string + default: "" +- name: authGithubWorkflowInstallId + type: string + default: "" - name: authGPGPassphrase type: string default: "" @@ -93,70 +102,91 @@ jobs: pool: vmImage: "ubuntu-20.04" steps: - - template: ../cached.yml - parameters: - name: publish_docker - # VERSION.txt is included to refresh Docker images for release - key: "ci/Dockerfile-envoy | VERSION.txt| $(cacheKeyBazelFiles)" - version: "$(cacheKeyDockerBuild)" - path: "" - - bash: | - echo "disk space at beginning of build:" - df -h - displayName: "Check disk space at beginning" - task: DownloadBuildArtifacts@0 inputs: buildType: current artifactName: "bazel.release" itemPattern: "bazel.release/**/bin/*" targetPath: $(Build.StagingDirectory) - - bash: | - set -e - - mkdir -p linux/amd64 linux/arm64 - - # x64 - cp -a $(Build.StagingDirectory)/bazel.release/x64/bin/release.tar.zst linux/amd64/release.tar.zst - cp -a $(Build.StagingDirectory)/bazel.release/x64/bin/schema_validator_tool linux/amd64/schema_validator_tool - - # arm64 - cp -a $(Build.StagingDirectory)/bazel.release/arm64/bin/release.tar.zst linux/arm64/release.tar.zst - cp -a $(Build.StagingDirectory)/bazel.release/arm64/bin/schema_validator_tool linux/arm64/schema_validator_tool + - template: ../bazel.yml + parameters: + ciTarget: docker-upload + # cacheVersion: $(cacheKeyBazel) + publishEnvoy: false + publishTestResults: false + # VERSION.txt is included to refresh Docker images for release + cacheKeyDocker: "ci/Dockerfile-envoy | VERSION.txt| $(cacheKeyBazelFiles)" + cacheKeyDockerName: publish_docker + cacheKeyDockerTmpDir: /var/azpcache + cacheKeyDockerPath: "" + cacheKeyDockerVersion: "$(cacheKeyDockerBuild)" + env: + GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} + stepsPre: + - bash: | + echo "disk space at beginning of Docker build:" + df -h + displayName: "Check disk space before Docker build" + - bash: | + set -e - # Debug what files appear to have been downloaded - find linux -type f -name "*" | xargs ls -l + mkdir -p linux/amd64 linux/arm64 - ci/docker_ci.sh - timeoutInMinutes: ${{ parameters.timeoutDockerPublish }} - workingDirectory: $(Build.SourcesDirectory) - env: - AZP_BRANCH: $(Build.SourceBranch) - AZP_SHA1: $(Build.SourceVersion) - DOCKERHUB_USERNAME: ${{ parameters.authDockerUser }} - DOCKERHUB_PASSWORD: ${{ parameters.authDockerPassword }} - DOCKER_BUILD_TIMEOUT: ${{ parameters.timeoutDockerBuild }} + # x64 + cp -a $(Build.StagingDirectory)/bazel.release/x64/bin/release.tar.zst linux/amd64/release.tar.zst + cp -a $(Build.StagingDirectory)/bazel.release/x64/bin/schema_validator_tool linux/amd64/schema_validator_tool - - bash: | - echo "disk space at end of build:" - df -h - displayName: "Check disk space at end" - condition: not(canceled()) + # arm64 + cp -a $(Build.StagingDirectory)/bazel.release/arm64/bin/release.tar.zst linux/arm64/release.tar.zst + cp -a $(Build.StagingDirectory)/bazel.release/arm64/bin/schema_validator_tool linux/arm64/schema_validator_tool - # Publish docker - - script: | - ci/run_envoy_docker.sh 'ci/do_ci.sh docker-upload' - displayName: "Upload Docker to GCS" - env: - ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) - ENVOY_RBE: "1" - BAZEL_BUILD_EXTRA_OPTIONS: "--config=remote-ci --jobs=$(RbeJobs)" - BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com - BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance - GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} - GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} + # Debug what files appear to have been downloaded + find linux -type f -name "*" | xargs ls -l - - script: sudo .azure-pipelines/docker/save_cache.sh /mnt/docker_cache - displayName: "Cache/save (publish_docker)" + ci/docker_ci.sh + displayName: Build Docker images + timeoutInMinutes: ${{ parameters.timeoutDockerPublish }} + workingDirectory: $(Build.SourcesDirectory) + env: + AZP_BRANCH: $(Build.SourceBranch) + AZP_SHA1: $(Build.SourceVersion) + DOCKERHUB_USERNAME: ${{ parameters.authDockerUser }} + DOCKERHUB_PASSWORD: ${{ parameters.authDockerPassword }} + DOCKER_BUILD_TIMEOUT: ${{ parameters.timeoutDockerBuild }} + stepsPost: + - task: DownloadSecureFile@1 + name: WorkflowTriggerKey + displayName: 'Download workflow trigger key' + inputs: + secureFile: '${{ parameters.authGithubWorkflow }}' + - bash: | + set -e + KEY="$(cat $(WorkflowTriggerKey.secureFilePath) | base64 -w0)" + echo "##vso[task.setvariable variable=value;isoutput=true]$KEY" + name: key + - script: ci/run_envoy_docker.sh 'ci/do_ci.sh verify.trigger' || echo "trigger not ready yet ..." + # Please see `ci/do_ci.sh` for notes on required vars. + env: + ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: + ENVOY_BRANCH: "$(System.PullRequest.TargetBranch)" + ENVOY_COMMIT: "$(System.PullRequest.SourceCommitId)" + ENVOY_HEAD_REF: "$(Build.SourceBranch)" + ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: + ENVOY_BRANCH: "$(Build.SourceBranch)" + # github auth + GITHUB_TOKEN: "$(key.value)" + GITHUB_APP_ID: ${{ parameters.authGithubWorkflowAppId }} + GITHUB_INSTALL_ID: ${{ parameters.authGithubWorkflowInstallId }} + # rbe env + BAZEL_BUILD_EXTRA_OPTIONS: "--config=remote-ci --jobs=$(RbeJobs)" + BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com + BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance + GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} + GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }} + ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) + ENVOY_RBE: "1" + - script: sudo .azure-pipelines/docker/save_cache.sh /var/azpcache + displayName: "Cache/save (publish_docker)" - job: package_x64 displayName: Linux debs (x64) diff --git a/.azure-pipelines/stage/verify.yml b/.azure-pipelines/stage/verify.yml index 238d7b4da974..127a2148ac8f 100644 --- a/.azure-pipelines/stage/verify.yml +++ b/.azure-pipelines/stage/verify.yml @@ -1,68 +1,13 @@ parameters: -- name: bucketGCP - type: string - default: "" - # Auth - name: authGCP type: string default: "" -- name: authGithubWorkflow - type: string - default: "" -- name: authGithubWorkflowAppId - type: string - default: "" -- name: authGithubWorkflowInstallId - type: string - default: "" - -- name: runDocker - displayName: "Run Docker" - type: string - default: true -# TODO(phlax): improve docker publishing job and move this there jobs: -- job: examples - displayName: Examples (Docker/x64) - condition: | - and(not(canceled()), - eq(${{ parameters.runDocker }}, 'true')) - timeoutInMinutes: 120 - pool: - vmImage: "ubuntu-20.04" - steps: - - task: DownloadSecureFile@1 - name: WorkflowTriggerKey - displayName: 'Download workflow trigger key' - inputs: - secureFile: '${{ parameters.authGithubWorkflow }}' - - - bash: | - set -e - KEY="$(cat $(WorkflowTriggerKey.secureFilePath) | base64 -w0)" - echo "##vso[task.setvariable variable=value;isoutput=true]$KEY" - name: key - - - template: ../bazel.yml - parameters: - ciTarget: verify.trigger - authGithub: "$(key.value)" - # Please see `ci/do_ci.sh` for notes on required vars. - env: - ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: - ENVOY_BRANCH: "$(System.PullRequest.TargetBranch)" - ENVOY_COMMIT: "$(System.PullRequest.SourceCommitId)" - ENVOY_HEAD_REF: "$(Build.SourceBranch)" - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - ENVOY_BRANCH: "$(Build.SourceBranch)" - GITHUB_APP_ID: ${{ parameters.authGithubWorkflowAppId }} - GITHUB_INSTALL_ID: ${{ parameters.authGithubWorkflowInstallId }} - - job: packages_x64 displayName: Debs (x64) condition: and(not(canceled()), succeeded(), ne(stageDependencies.env.repo.outputs['changed.mobileOnly'], 'true'), ne(stageDependencies.env.repo.outputs['changed.docsOnly'], 'true'), ne(stageDependencies.env.repo.outputs['changed.examplesOnly'], 'true')) @@ -114,7 +59,7 @@ jobs: - job: verified displayName: Verification complete - dependsOn: ["examples", "packages_x64", "packages_arm64"] + dependsOn: ["packages_x64", "packages_arm64"] pool: vmImage: "ubuntu-20.04" # This condition ensures that this (required) check passes if all of @@ -124,7 +69,6 @@ jobs: condition: | and( eq(variables['Build.Reason'], 'PullRequest'), - in(dependencies.examples.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), in(dependencies.packages_x64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), in(dependencies.packages_arm64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')) steps: diff --git a/.azure-pipelines/stages.yml b/.azure-pipelines/stages.yml index e678f892e541..caab5bae0fad 100644 --- a/.azure-pipelines/stages.yml +++ b/.azure-pipelines/stages.yml @@ -148,6 +148,9 @@ stages: authDockerPassword: $(DockerPassword) authGCP: $(GcpServiceAccountKey) authGithub: $(GitHubPublicRepoOnlyAccessToken) + authGithubWorkflow: $(GitHubPublicRepoWorkflowKey) + authGithubWorkflowAppId: $(GitHubPublicRepoWorkflowAppId) + authGithubWorkflowInstallId: $(GitHubPublicRepoWorkflowInstallId) authGPGPassphrase: $(MaintainerGPGKeyPassphrase) authGPGKey: $(MaintainerGPGKeySecureFileDownloadPath) authGPGPath: $(MaintainerGPGKey.secureFilePath) @@ -175,11 +178,6 @@ stages: - template: stage/verify.yml parameters: authGCP: $(GcpServiceAccountKey) - bucketGCP: $(GcsArtifactBucket) - authGithubWorkflow: $(GitHubPublicRepoWorkflowKey) - authGithubWorkflowAppId: $(GitHubPublicRepoWorkflowAppId) - authGithubWorkflowInstallId: $(GitHubPublicRepoWorkflowInstallId) - runDocker: variables['RUN_DOCKER'] - stage: macos displayName: macOS From 0d79cc8a107a86c2f6880fff42b7c5c3d30f87ad Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Fri, 26 May 2023 14:36:57 -0400 Subject: [PATCH 106/228] ext_proc filter allow_mode_override API implemenation (#27618) * ext_proc filter allow_mode_override API implemenation Signed-off-by: Yanjun Xiang --- .../filters/http/ext_proc/v3/ext_proc.proto | 4 +- changelogs/current.yaml | 9 ++++ .../filters/http/ext_proc/ext_proc.cc | 5 +- .../filters/http/ext_proc/ext_proc.h | 8 +++- .../filters/http/ext_proc/filter_test.cc | 47 ++++++++++++++++++- .../ext_proc/streaming_integration_test.cc | 2 +- 6 files changed, 68 insertions(+), 7 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 38feceb22706..2198a2d6f25e 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -76,7 +76,8 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // By default, the processor sends only the request and response headers messages. // This may be changed to include any of the six steps by changing the processing_mode // setting of the filter configuration, or by setting the mode_override of any response -// from the external processor. This way, a processor may, for example, use information +// from the external processor. The latter is only enabled if allow_mode_override is +// set to true. This way, a processor may, for example, use information // in the request header to determine whether the message body must be examined, or whether // the proxy should simply stream it straight through. // @@ -196,7 +197,6 @@ message ExternalProcessor { // ext_proc filter name. google.protobuf.Struct filter_metadata = 13; - // [#not-implemented-hide:] // If ``allow_mode_override`` is set to true, the filter config :ref:`processing_mode // ` // can be overridden by the response message from the external processing server diff --git a/changelogs/current.yaml b/changelogs/current.yaml index f537a751f08d..6cb35b3eaa98 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -206,6 +206,15 @@ new_features: - area: ext_proc change: | added new configuration field + :ref:`allow_mode_override ` + If set to true, the filter config + :ref:`processing_mode ` + can be overridden by the + :ref:`mode_override ` + in the response message from the external processing server. + If not set, the ``mode_override`` API in the response message will be ignored. +- area: ext_proc + change: | :ref:`forward_rules ` to only allow headers matchinging the forward rules to be forwarded to the external processing server. - area: redis_proxy diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index deb93c625667..7661048511ac 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -607,8 +607,9 @@ void Filter::onReceiveMessage(std::unique_ptr&& r) { // Update processing mode now because filter callbacks check it // and the various "handle" methods below may result in callbacks - // being invoked in line. - if (response->has_mode_override()) { + // being invoked in line. This only happens when filter has allow_mode_override + // set to true. Otherwise, the response mode_override proto field is ignored. + if (config_->allowModeOverride() && response->has_mode_override()) { ENVOY_LOG(debug, "Processing mode overridden by server for this request"); decoding_state_.setProcessingMode(response->mode_override()); encoding_state_.setProcessingMode(response->mode_override()); diff --git a/source/extensions/filters/http/ext_proc/ext_proc.h b/source/extensions/filters/http/ext_proc/ext_proc.h index ecbf61dcaae8..f3917364d197 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.h +++ b/source/extensions/filters/http/ext_proc/ext_proc.h @@ -111,7 +111,9 @@ class FilterConfig { message_timeout_(message_timeout), max_message_timeout_ms_(max_message_timeout_ms), stats_(generateStats(stats_prefix, config.stat_prefix(), scope)), processing_mode_(config.processing_mode()), mutation_checker_(config.mutation_rules()), - filter_metadata_(config.filter_metadata()), header_matchers_(initHeaderMatchers(config)) {} + filter_metadata_(config.filter_metadata()), + allow_mode_override_(config.allow_mode_override()), + header_matchers_(initHeaderMatchers(config)) {} bool failureModeAllow() const { return failure_mode_allow_; } @@ -125,6 +127,8 @@ class FilterConfig { return processing_mode_; } + bool allowModeOverride() const { return allow_mode_override_; } + const Filters::Common::MutationRules::Checker& mutationChecker() const { return mutation_checker_; } @@ -161,6 +165,8 @@ class FilterConfig { const envoy::extensions::filters::http::ext_proc::v3::ProcessingMode processing_mode_; const Filters::Common::MutationRules::Checker mutation_checker_; const Envoy::ProtobufWkt::Struct filter_metadata_; + // If set to true, allow the processing mode to be modified by the ext_proc response. + const bool allow_mode_override_; // Empty header_matchers_ means allow all. const std::vector header_matchers_; }; diff --git a/test/extensions/filters/http/ext_proc/filter_test.cc b/test/extensions/filters/http/ext_proc/filter_test.cc index 009458d53c6d..3f54f761d261 100644 --- a/test/extensions/filters/http/ext_proc/filter_test.cc +++ b/test/extensions/filters/http/ext_proc/filter_test.cc @@ -1395,6 +1395,7 @@ TEST_F(HttpFilterTest, GetStreamingBodyAndChangeMode) { response_body_mode: "STREAMED" request_trailer_mode: "SKIP" response_trailer_mode: "SKIP" + allow_mode_override: true )EOF"); // Create synthetic HTTP request @@ -1482,6 +1483,7 @@ TEST_F(HttpFilterTest, GetStreamingBodyAndChangeModeDifferentOrder) { response_body_mode: "STREAMED" request_trailer_mode: "SKIP" response_trailer_mode: "SKIP" + allow_mode_override: true )EOF"); // Create synthetic HTTP request @@ -1885,8 +1887,9 @@ TEST_F(HttpFilterTest, ProcessingModeOverrideResponseHeaders) { grpc_service: envoy_grpc: cluster_name: "ext_proc_server" + allow_mode_override: true )EOF"); - + EXPECT_EQ(filter_->config().allowModeOverride(), true); EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers_, false)); processRequestHeaders( @@ -1920,6 +1923,48 @@ TEST_F(HttpFilterTest, ProcessingModeOverrideResponseHeaders) { EXPECT_EQ(1, config_->stats().streams_closed_.value()); } +// Leaving the allow_mode_override in filter config to be default, which is false. +// In such case, the mode_override in the response will be ignored. +TEST_F(HttpFilterTest, DisableResponseModeOverride) { + initialize(R"EOF( + grpc_service: + envoy_grpc: + cluster_name: "ext_proc_server" + processing_mode: + request_header_mode: "SEND" + response_header_mode: "SEND" + )EOF"); + + EXPECT_EQ(filter_->config().allowModeOverride(), false); + EXPECT_EQ(filter_->config().processingMode().response_header_mode(), ProcessingMode::SEND); + EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers_, true)); + + // When ext_proc server sends back the request header response, it contains the + // mode_override for the response_header_mode to be SKIP. + processRequestHeaders( + false, [](const HttpHeaders&, ProcessingResponse& response, HeadersResponse&) { + response.mutable_mode_override()->set_response_header_mode(ProcessingMode::SKIP); + }); + + response_headers_.addCopy(LowerCaseString(":status"), "200"); + response_headers_.addCopy(LowerCaseString("content-type"), "text/plain"); + EXPECT_EQ(FilterHeadersStatus::StopIteration, filter_->encodeHeaders(response_headers_, true)); + + // Such mode_override is ignored. The response header is still sent to the ext_proc server. + processResponseHeaders(false, + [](const HttpHeaders& header_resp, ProcessingResponse&, HeadersResponse&) { + EXPECT_TRUE(header_resp.end_of_stream()); + Http::TestRequestHeaderMapImpl expected_response{ + {":status", "200"}, {"content-type", "text/plain"}}; + EXPECT_THAT(header_resp.headers(), HeaderProtosEqual(expected_response)); + }); + + Http::TestRequestHeaderMapImpl final_expected_response{{":status", "200"}, + {"content-type", "text/plain"}}; + EXPECT_THAT(&response_headers_, HeaderMapEqualIgnoreOrder(&final_expected_response)); + filter_->onDestroy(); +} + // Using a processing mode, configure the filter to only send the response_headers // message. TEST_F(HttpFilterTest, ProcessingModeResponseHeadersOnly) { diff --git a/test/extensions/filters/http/ext_proc/streaming_integration_test.cc b/test/extensions/filters/http/ext_proc/streaming_integration_test.cc index 76ae7902ac8c..5b6d46413e21 100644 --- a/test/extensions/filters/http/ext_proc/streaming_integration_test.cc +++ b/test/extensions/filters/http/ext_proc/streaming_integration_test.cc @@ -44,7 +44,7 @@ class StreamingIntegrationTest : public HttpIntegrationTest, void initializeConfig() { // This enables a built-in automatic upstream server. autonomous_upstream_ = true; - + proto_config_.set_allow_mode_override(true); config_helper_.addConfigModifier([this](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { // Create a cluster for our gRPC server pointing to the address that is running the gRPC // server. From 92be7e1e7d668ddac6e282e0ceaff38ffe0f2737 Mon Sep 17 00:00:00 2001 From: Ketankumar Rana <124616929+ktn-nv@users.noreply.github.com> Date: Fri, 26 May 2023 11:51:23 -0700 Subject: [PATCH 107/228] Oauth2: Marking token holding cookie as httpOnly to prevent attacks (#27297) * Oauth2: Marking token holiding cookie as httpOnly to prevent attacks Signed-off-by: Ketankumar Rana --- changelogs/current.yaml | 7 +++ source/common/runtime/runtime_features.cc | 1 + .../extensions/filters/http/oauth2/filter.cc | 22 +++++----- .../filters/http/oauth2/filter_test.cc | 44 ++++++++++++++++--- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 6cb35b3eaa98..0a5f3aadd377 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -114,6 +114,13 @@ bug_fixes: - area: boringssl change: | Fixed the crash that occurs when contrib is compiled with ``boringssl=fips`` defined. +- area: oauth2 + change: | + The httpOnly attribute for Set-Cookie for tokens in HTTP response header was missing, + causing tokens to be accessible from the JavaScript making the apps vulnerable. + This was fixed now by marking the cookie as httpOnly. + This behavioral change can be temporarily reverted by setting runtime guard + ``envoy.reloadable_features.oauth_make_token_cookie_httponly`` to false. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 14e980901d74..5d6d318e0b55 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -55,6 +55,7 @@ RUNTIME_GUARD(envoy_reloadable_features_initialize_upstream_filters); RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name); RUNTIME_GUARD(envoy_reloadable_features_no_full_scan_certs_on_sni_mismatch); RUNTIME_GUARD(envoy_reloadable_features_oauth_header_passthrough_fix); +RUNTIME_GUARD(envoy_reloadable_features_oauth_make_token_cookie_httponly); RUNTIME_GUARD(envoy_reloadable_features_oauth_use_standard_max_age_value); RUNTIME_GUARD(envoy_reloadable_features_oauth_use_url_encoding); RUNTIME_GUARD(envoy_reloadable_features_original_dst_rely_on_idle_timeout); diff --git a/source/extensions/filters/http/oauth2/filter.cc b/source/extensions/filters/http/oauth2/filter.cc index af111b3c26b1..d3422448d46b 100644 --- a/source/extensions/filters/http/oauth2/filter.cc +++ b/source/extensions/filters/http/oauth2/filter.cc @@ -36,9 +36,7 @@ Http::RegisterCustomInlineHeadercookieNames(); headers.addReferenceKey( @@ -535,18 +532,23 @@ void OAuth2Filter::addResponseCookies(Http::ResponseHeaderMap& headers, // If opted-in, we also create a new Bearer cookie for the authorization token provided by the // auth server. if (config_->forwardBearerToken()) { + std::string cookie_attribute_httponly = + Runtime::runtimeFeatureEnabled("envoy.reloadable_features.oauth_make_token_cookie_httponly") + ? cookie_tail_http_only + : cookie_tail; headers.addReferenceKey( Http::Headers::get().SetCookie, - absl::StrCat(cookie_names.bearer_token_, "=", access_token_, cookie_tail)); + absl::StrCat(cookie_names.bearer_token_, "=", access_token_, cookie_attribute_httponly)); if (id_token_ != EMPTY_STRING) { - headers.addReferenceKey(Http::Headers::get().SetCookie, - absl::StrCat(cookie_names.id_token_, "=", id_token_, cookie_tail)); + headers.addReferenceKey( + Http::Headers::get().SetCookie, + absl::StrCat(cookie_names.id_token_, "=", id_token_, cookie_attribute_httponly)); } if (refresh_token_ != EMPTY_STRING) { - headers.addReferenceKey( - Http::Headers::get().SetCookie, - absl::StrCat(cookie_names.refresh_token_, "=", refresh_token_, cookie_tail)); + headers.addReferenceKey(Http::Headers::get().SetCookie, + absl::StrCat(cookie_names.refresh_token_, "=", refresh_token_, + cookie_attribute_httponly)); } } } diff --git a/test/extensions/filters/http/oauth2/filter_test.cc b/test/extensions/filters/http/oauth2/filter_test.cc index 970bbf360e81..e0445410e3ec 100644 --- a/test/extensions/filters/http/oauth2/filter_test.cc +++ b/test/extensions/filters/http/oauth2/filter_test.cc @@ -1104,7 +1104,8 @@ TEST_F(OAuth2Test, OAuthTestFullFlowPostWithParametersLegacyEncoding) { "version=1;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "OauthExpires=;version=1;path=/;Max-Age=;secure;HttpOnly"}, - {Http::Headers::get().SetCookie.get(), "BearerToken=;version=1;path=/;Max-Age=;secure"}, + {Http::Headers::get().SetCookie.get(), + "BearerToken=;version=1;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().Location.get(), "https://traffic.example.com/test?name=admin&level=trace"}, }; @@ -1195,7 +1196,8 @@ TEST_F(OAuth2Test, OAuthTestFullFlowPostWithParameters) { "version=1;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "OauthExpires=;version=1;path=/;Max-Age=;secure;HttpOnly"}, - {Http::Headers::get().SetCookie.get(), "BearerToken=;version=1;path=/;Max-Age=;secure"}, + {Http::Headers::get().SetCookie.get(), + "BearerToken=;version=1;path=/;Max-Age=;secure;HttpOnly"}, {Http::Headers::get().Location.get(), "https://traffic.example.com/test/utf8%C3%83?name=admin&level=trace"}, }; @@ -1226,11 +1228,11 @@ TEST_F(OAuth2Test, OAuthAccessTokenSucessWithTokens) { {Http::Headers::get().SetCookie.get(), "OauthExpires=1600;version=1;path=/;Max-Age=600;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), - "BearerToken=access_code;version=1;path=/;Max-Age=600;secure"}, + "BearerToken=access_code;version=1;path=/;Max-Age=600;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), - "IdToken=some-id-token;version=1;path=/;Max-Age=600;secure"}, + "IdToken=some-id-token;version=1;path=/;Max-Age=600;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), - "RefreshToken=some-refresh-token;version=1;path=/;Max-Age=600;secure"}, + "RefreshToken=some-refresh-token;version=1;path=/;Max-Age=600;secure;HttpOnly"}, {Http::Headers::get().Location.get(), ""}, }; @@ -1258,6 +1260,38 @@ TEST_F(OAuth2Test, OAuthAccessTokenSucessWithTokens_oauth_use_standard_max_age_v "version=1;path=/;Max-Age=600;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "OauthExpires=600;version=1;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "BearerToken=access_code;version=1;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "IdToken=some-id-token;version=1;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "RefreshToken=some-refresh-token;version=1;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().Location.get(), ""}, + }; + + EXPECT_CALL(decoder_callbacks_, encodeHeaders_(HeaderMapEqualRef(&expected_headers), true)); + + filter_->onGetAccessTokenSuccess("access_code", "some-id-token", "some-refresh-token", + std::chrono::seconds(600)); +} +TEST_F(OAuth2Test, OAuthAccessTokenSucessWithTokens_oauth_make_token_cookie_httponly) { + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues({ + {"envoy.reloadable_features.oauth_make_token_cookie_httponly", "false"}, + }); + + // Set SystemTime to a fixed point so we get consistent HMAC encodings between test runs. + test_time_.setSystemTime(SystemTime(std::chrono::seconds(1000))); + + // Expected response after the callback is complete. + Http::TestRequestHeaderMapImpl expected_headers{ + {Http::Headers::get().Status.get(), "302"}, + {Http::Headers::get().SetCookie.get(), + "OauthHMAC=" + "MjI2YmI5YTRiZjJlNTFlNDUzZWVjOWUzYmU1MThlNGQyNDgyNzA0ZTBkMGQyY2M3M2QyMzg3NTRkZTY0YmU5YQ==;" + "version=1;path=/;Max-Age=600;secure;HttpOnly"}, + {Http::Headers::get().SetCookie.get(), + "OauthExpires=1600;version=1;path=/;Max-Age=600;secure;HttpOnly"}, {Http::Headers::get().SetCookie.get(), "BearerToken=access_code;version=1;path=/;Max-Age=600;secure"}, {Http::Headers::get().SetCookie.get(), From 0e822607588b6313931154a5ae8680c0df2af08a Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Fri, 26 May 2023 15:07:26 -0400 Subject: [PATCH 108/228] Fix ext_proc fuzzer test issues. (#27619) * Fix ext_proc fuzzer test issues. Signed-off-by: Yanjun Xiang --- ...h-df781e3c1eede590dddbb6d3fd7e58f87b8d89cd | 28 +++++++++++++++++++ .../unit_test_fuzz/ext_proc_unit_test_fuzz.cc | 14 +++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-df781e3c1eede590dddbb6d3fd7e58f87b8d89cd diff --git a/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-df781e3c1eede590dddbb6d3fd7e58f87b8d89cd b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-df781e3c1eede590dddbb6d3fd7e58f87b8d89cd new file mode 100644 index 000000000000..8d60ca08e841 --- /dev/null +++ b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-df781e3c1eede590dddbb6d3fd7e58f87b8d89cd @@ -0,0 +1,28 @@ +config { + grpc_service { + envoy_grpc { + cluster_name: ":" + } + } + processing_mode { + response_header_mode: SKIP + request_trailer_mode: SKIP + response_trailer_mode: SKIP + } + max_message_timeout { + nanos: 89 + } +} +request { + http_body { + data: "\177\177\177\177" + } +} +response { + request_headers { + } + mode_override { + request_header_mode: SKIP + request_body_mode: BUFFERED + } +} diff --git a/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc index 477a04bb2841..8ca81765cb27 100644 --- a/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc +++ b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_unit_test_fuzz.cc @@ -18,13 +18,18 @@ namespace UnitTestFuzz { class FuzzerMocks { public: - FuzzerMocks() : addr_(std::make_shared("/test/test.sock")) { + FuzzerMocks() + : addr_(std::make_shared("/test/test.sock")), buffer_("foo") { ON_CALL(decoder_callbacks_, connection()) .WillByDefault(Return(OptRef{connection_})); connection_.stream_info_.downstream_connection_info_provider_->setRemoteAddress(addr_); connection_.stream_info_.downstream_connection_info_provider_->setLocalAddress(addr_); ON_CALL(decoder_callbacks_, addDecodedTrailers()).WillByDefault(ReturnRef(request_trailers_)); ON_CALL(encoder_callbacks_, addEncodedTrailers()).WillByDefault(ReturnRef(response_trailers_)); + ON_CALL(decoder_callbacks_, decodingBuffer()).WillByDefault(Return(&buffer_)); + ON_CALL(encoder_callbacks_, encodingBuffer()).WillByDefault(Return(&buffer_)); + ON_CALL(decoder_callbacks_, decoderBufferLimit()).WillByDefault(Return(1024)); + ON_CALL(encoder_callbacks_, encoderBufferLimit()).WillByDefault(Return(1024)); } NiceMock decoder_callbacks_; @@ -33,6 +38,7 @@ class FuzzerMocks { NiceMock connection_; NiceMock request_trailers_; NiceMock response_trailers_; + NiceMock buffer_; testing::NiceMock async_client_stream_info_; }; @@ -72,8 +78,8 @@ DEFINE_PROTO_FUZZER( filter->setDecoderFilterCallbacks(mocks.decoder_callbacks_); filter->setEncoderFilterCallbacks(mocks.encoder_callbacks_); - ON_CALL(*client, start(_, _, _)) - .WillByDefault(Invoke( + EXPECT_CALL(*client, start(_, _, _)) + .WillRepeatedly(Invoke( [&](ExternalProcessing::ExternalProcessorCallbacks&, const envoy::config::core::v3::GrpcService&, const StreamInfo::StreamInfo&) -> ExternalProcessing::ExternalProcessorStreamPtr { @@ -88,7 +94,7 @@ DEFINE_PROTO_FUZZER( })); EXPECT_CALL(*stream, streamInfo()) .WillRepeatedly(ReturnRef(mocks.async_client_stream_info_)); - ON_CALL(*stream, close()).WillByDefault(Return(false)); + EXPECT_CALL(*stream, close()).WillRepeatedly(Return(false)); return stream; })); From 71a50bea7bc46e965eae3a12253d9021de40fcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20R=2E=20Sede=C3=B1o?= Date: Fri, 26 May 2023 15:07:59 -0400 Subject: [PATCH 109/228] Update QUICHE from 4a5e9e692 to 4506f8d26 (#27638) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update QUICHE from 4a5e9e692 to 4506f8d26 https://github.com/google/quiche/compare/4a5e9e692..4506f8d26 ``` $ git log 4a5e9e692..4506f8d26 --date=short --no-merges --format="%ad %al %s" 2023-05-24 bnc Internal change 2023-05-24 danzh Internal change 2023-05-23 martinduke Use QuicPacketWriter::SupportsEcn interface to abandon ECN attempts. 2023-05-23 martinduke Refactor ECN in QuicConnection. 2023-05-23 martinduke Add SupportsEcn() interface to QuicPacketWriter. A follow-on will use this interface in QuicConnection. 2023-05-23 martinduke Refactor PerPacketOptions for QuicWriter. From the bug: 2023-05-22 elburrito Use public metadata expiry time as BlindSignAuth token expiry 2023-05-19 elburrito Add ClearCache function to CachedBlindSignAuth. This function will be called when the cached tokens are invalid and need to be deleted. 2023-05-19 danzh Internal change ``` Signed-off-by: Alejandro R Sedeño --- bazel/repository_locations.bzl | 6 ++--- .../common/quic/envoy_quic_packet_writer.cc | 8 +++---- source/common/quic/envoy_quic_packet_writer.h | 5 +++- source/common/quic/udp_gso_batch_writer.cc | 3 ++- .../quic/envoy_quic_client_session_test.cc | 2 +- .../quic/envoy_quic_client_stream_test.cc | 5 ++-- .../common/quic/envoy_quic_dispatcher_test.cc | 2 +- .../quic/envoy_quic_server_session_test.cc | 5 ++-- .../quic/envoy_quic_server_stream_test.cc | 5 ++-- test/common/quic/envoy_quic_writer_test.cc | 24 +++++++++++-------- test/per_file_coverage.sh | 2 +- 11 files changed, 39 insertions(+), 28 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 1236add57d89..f6769dc0c707 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1056,12 +1056,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "QUICHE", project_desc = "QUICHE (QUIC, HTTP/2, Etc) is Google‘s implementation of QUIC and related protocols", project_url = "https://github.com/google/quiche", - version = "4a5e9e692040ff0786563c30488a7d29fd58f40d", - sha256 = "59e4712549c8f39fa31b5ded59ab548538384785bcc0854ee59221160f91a16d", + version = "4506f8d266853c2b039bec1ee4bc8ed0f22d861c", + sha256 = "f532f981381b8e0f817b4426d6dae085c32bdfe75ba01c55ad09a6d9341f91fb", urls = ["https://github.com/google/quiche/archive/{version}.tar.gz"], strip_prefix = "quiche-{version}", use_category = ["controlplane", "dataplane_core"], - release_date = "2023-05-18", + release_date = "2023-05-24", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/google/quiche/blob/{version}/LICENSE", diff --git a/source/common/quic/envoy_quic_packet_writer.cc b/source/common/quic/envoy_quic_packet_writer.cc index 74663900d619..75178b9cdf27 100644 --- a/source/common/quic/envoy_quic_packet_writer.cc +++ b/source/common/quic/envoy_quic_packet_writer.cc @@ -25,10 +25,10 @@ quic::WriteResult convertToQuicWriteResult(Api::IoCallUint64Result& result) { EnvoyQuicPacketWriter::EnvoyQuicPacketWriter(Network::UdpPacketWriterPtr envoy_udp_packet_writer) : envoy_udp_packet_writer_(std::move(envoy_udp_packet_writer)) {} -quic::WriteResult EnvoyQuicPacketWriter::WritePacket(const char* buffer, size_t buffer_len, - const quic::QuicIpAddress& self_ip, - const quic::QuicSocketAddress& peer_address, - quic::PerPacketOptions* options) { +quic::WriteResult EnvoyQuicPacketWriter::WritePacket( + const char* buffer, size_t buffer_len, const quic::QuicIpAddress& self_ip, + const quic::QuicSocketAddress& peer_address, quic::PerPacketOptions* options, + [[maybe_unused]] const quic::QuicPacketWriterParams& params) { ASSERT(options == nullptr, "Per packet option is not supported yet."); Buffer::BufferFragmentImpl fragment(buffer, buffer_len, nullptr); diff --git a/source/common/quic/envoy_quic_packet_writer.h b/source/common/quic/envoy_quic_packet_writer.h index 2b50c8aa2c95..80b4b6bfc02e 100644 --- a/source/common/quic/envoy_quic_packet_writer.h +++ b/source/common/quic/envoy_quic_packet_writer.h @@ -14,7 +14,8 @@ class EnvoyQuicPacketWriter : public quic::QuicPacketWriter { quic::WriteResult WritePacket(const char* buffer, size_t buf_len, const quic::QuicIpAddress& self_address, const quic::QuicSocketAddress& peer_address, - quic::PerPacketOptions* options) override; + quic::PerPacketOptions* options, + const quic::QuicPacketWriterParams& params) override; // quic::QuicPacketWriter bool IsWriteBlocked() const override { return envoy_udp_packet_writer_->isWriteBlocked(); } @@ -22,6 +23,8 @@ class EnvoyQuicPacketWriter : public quic::QuicPacketWriter { bool IsBatchMode() const override { return envoy_udp_packet_writer_->isBatchMode(); } // Currently this writer doesn't support pacing offload. bool SupportsReleaseTime() const override { return false; } + // Currently this writer doesn't support Explicit Congestion Notification. + bool SupportsEcn() const override { return false; } absl::optional MessageTooBigErrorCode() const override; quic::QuicByteCount GetMaxPacketSize(const quic::QuicSocketAddress& peer_address) const override; diff --git a/source/common/quic/udp_gso_batch_writer.cc b/source/common/quic/udp_gso_batch_writer.cc index fa08f95b29b6..7171806d7640 100644 --- a/source/common/quic/udp_gso_batch_writer.cc +++ b/source/common/quic/udp_gso_batch_writer.cc @@ -55,9 +55,10 @@ UdpGsoBatchWriter::writePacket(const Buffer::Instance& buffer, const Network::Ad // TODO(yugant): Currently we do not use PerPacketOptions with Quic, we may want to // specify this parameter here at a later stage. + quic::QuicPacketWriterParams params; quic::WriteResult quic_result = WritePacket(static_cast(buffer.frontSlice().mem_), payload_len, self_addr.host(), peer_addr, - /*quic::PerPacketOptions=*/nullptr); + /*quic::PerPacketOptions=*/nullptr, params); updateUdpGsoBatchWriterStats(quic_result); return convertQuicWriteResult(quic_result, payload_len); diff --git a/test/common/quic/envoy_quic_client_session_test.cc b/test/common/quic/envoy_quic_client_session_test.cc index e9c30b2fde0b..921c0237f117 100644 --- a/test/common/quic/envoy_quic_client_session_test.cc +++ b/test/common/quic/envoy_quic_client_session_test.cc @@ -91,7 +91,7 @@ class EnvoyQuicClientSessionTest : public testing::TestWithParam) { return quic::QuicConsumedData{write_length, state != quic::NO_FIN}; })); - EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)) + EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _)) .WillRepeatedly(Invoke([](const char*, size_t buf_len, const quic::QuicIpAddress&, - const quic::QuicSocketAddress&, quic::PerPacketOptions*) { + const quic::QuicSocketAddress&, quic::PerPacketOptions*, + const quic::QuicPacketWriterParams&) { return quic::WriteResult{quic::WRITE_STATUS_OK, static_cast(buf_len)}; })); } diff --git a/test/common/quic/envoy_quic_dispatcher_test.cc b/test/common/quic/envoy_quic_dispatcher_test.cc index ce0bb7d806de..2bf102ad948c 100644 --- a/test/common/quic/envoy_quic_dispatcher_test.cc +++ b/test/common/quic/envoy_quic_dispatcher_test.cc @@ -79,7 +79,7 @@ class EnvoyQuicDispatcherTest : public testing::TestWithParam>()) { auto writer = new testing::NiceMock(); envoy_quic_dispatcher_.InitializeWithWriter(writer); - EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)) + EXPECT_CALL(*writer, WritePacket(_, _, _, _, _, _)) .WillRepeatedly(Return(quic::WriteResult(quic::WRITE_STATUS_OK, 0))); EXPECT_CALL(proof_source_->filterChain(), transportSocketFactory()) .WillRepeatedly(ReturnRef(transport_socket_factory_)); diff --git a/test/common/quic/envoy_quic_server_session_test.cc b/test/common/quic/envoy_quic_server_session_test.cc index 210abdda140e..43608d9f8cde 100644 --- a/test/common/quic/envoy_quic_server_session_test.cc +++ b/test/common/quic/envoy_quic_server_session_test.cc @@ -177,9 +177,10 @@ class EnvoyQuicServerSessionTest : public testing::Test { Event::Dispatcher::RunType::NonBlock); connection_helper_.GetClock()->Now(); - ON_CALL(writer_, WritePacket(_, _, _, _, _)) + ON_CALL(writer_, WritePacket(_, _, _, _, _, _)) .WillByDefault(Invoke([](const char*, size_t buf_len, const quic::QuicIpAddress&, - const quic::QuicSocketAddress&, quic::PerPacketOptions*) { + const quic::QuicSocketAddress&, quic::PerPacketOptions*, + const quic::QuicPacketWriterParams&) { return quic::WriteResult{quic::WRITE_STATUS_OK, static_cast(buf_len)}; })); ON_CALL(crypto_stream_helper_, CanAcceptClientHello(_, _, _, _, _)).WillByDefault(Return(true)); diff --git a/test/common/quic/envoy_quic_server_stream_test.cc b/test/common/quic/envoy_quic_server_stream_test.cc index f2a79a6c6b67..7b2f5f9e05ef 100644 --- a/test/common/quic/envoy_quic_server_stream_test.cc +++ b/test/common/quic/envoy_quic_server_stream_test.cc @@ -73,9 +73,10 @@ class EnvoyQuicServerStreamTest : public testing::Test { quic::StreamSendingState state, bool, absl::optional) { return quic::QuicConsumedData{write_length, state != quic::NO_FIN}; })); - EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)) + EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _)) .WillRepeatedly(Invoke([](const char*, size_t buf_len, const quic::QuicIpAddress&, - const quic::QuicSocketAddress&, quic::PerPacketOptions*) { + const quic::QuicSocketAddress&, quic::PerPacketOptions*, + const quic::QuicPacketWriterParams&) { return quic::WriteResult{quic::WRITE_STATUS_OK, static_cast(buf_len)}; })); } diff --git a/test/common/quic/envoy_quic_writer_test.cc b/test/common/quic/envoy_quic_writer_test.cc index f6a21ffce892..3dc8a748d4bf 100644 --- a/test/common/quic/envoy_quic_writer_test.cc +++ b/test/common/quic/envoy_quic_writer_test.cc @@ -59,22 +59,23 @@ class EnvoyQuicWriterTest : public ::testing::Test { TEST_F(EnvoyQuicWriterTest, AssertOnNonNullPacketOption) { std::string str("Hello World!"); - EXPECT_DEBUG_DEATH(envoy_quic_writer_.WritePacket(str.data(), str.length(), self_address_, - peer_address_, - reinterpret_cast(0x1)), - ""); + quic::QuicPacketWriterParams params; + EXPECT_DEBUG_DEATH( + envoy_quic_writer_.WritePacket(str.data(), str.length(), self_address_, peer_address_, + reinterpret_cast(0x1), params), + ""); } TEST_F(EnvoyQuicWriterTest, SendSuccessfully) { std::string str("Hello World!"); - + quic::QuicPacketWriterParams params; EXPECT_CALL(os_sys_calls_, sendmsg(_, _, _)) .WillOnce(testing::Invoke([this, str](int, const msghdr* message, int) { verifySendData(str, message); return Api::SysCallSizeResult{static_cast(str.length()), 0}; })); quic::WriteResult result = envoy_quic_writer_.WritePacket(str.data(), str.length(), self_address_, - peer_address_, nullptr); + peer_address_, nullptr, params); EXPECT_EQ(quic::WRITE_STATUS_OK, result.status); EXPECT_EQ(str.length(), result.bytes_written); EXPECT_FALSE(envoy_quic_writer_.IsWriteBlocked()); @@ -82,13 +83,14 @@ TEST_F(EnvoyQuicWriterTest, SendSuccessfully) { TEST_F(EnvoyQuicWriterTest, SendBlocked) { std::string str("Hello World!"); + quic::QuicPacketWriterParams params; EXPECT_CALL(os_sys_calls_, sendmsg(_, _, _)) .WillOnce(testing::Invoke([this, str](int, const msghdr* message, int) { verifySendData(str, message); return Api::SysCallSizeResult{-1, SOCKET_ERROR_AGAIN}; })); quic::WriteResult result = envoy_quic_writer_.WritePacket(str.data(), str.length(), self_address_, - peer_address_, nullptr); + peer_address_, nullptr, params); EXPECT_EQ(quic::WRITE_STATUS_BLOCKED, result.status); EXPECT_EQ(SOCKET_ERROR_AGAIN, result.error_code); EXPECT_TRUE(envoy_quic_writer_.IsWriteBlocked()); @@ -101,7 +103,7 @@ TEST_F(EnvoyQuicWriterTest, SendBlocked) { })); #endif EXPECT_DEBUG_DEATH(envoy_quic_writer_.WritePacket(str.data(), str.length(), self_address_, - peer_address_, nullptr), + peer_address_, nullptr, params), ""); envoy_quic_writer_.SetWritable(); EXPECT_FALSE(envoy_quic_writer_.IsWriteBlocked()); @@ -109,13 +111,14 @@ TEST_F(EnvoyQuicWriterTest, SendBlocked) { TEST_F(EnvoyQuicWriterTest, SendFailure) { std::string str("Hello World!"); + quic::QuicPacketWriterParams params; EXPECT_CALL(os_sys_calls_, sendmsg(_, _, _)) .WillOnce(testing::Invoke([this, str](int, const msghdr* message, int) { verifySendData(str, message); return Api::SysCallSizeResult{-1, SOCKET_ERROR_NOT_SUP}; })); quic::WriteResult result = envoy_quic_writer_.WritePacket(str.data(), str.length(), self_address_, - peer_address_, nullptr); + peer_address_, nullptr, params); EXPECT_EQ(quic::WRITE_STATUS_ERROR, result.status); EXPECT_EQ(SOCKET_ERROR_NOT_SUP, result.error_code); EXPECT_FALSE(envoy_quic_writer_.IsWriteBlocked()); @@ -123,13 +126,14 @@ TEST_F(EnvoyQuicWriterTest, SendFailure) { TEST_F(EnvoyQuicWriterTest, SendFailureMessageTooBig) { std::string str("Hello World!"); + quic::QuicPacketWriterParams params; EXPECT_CALL(os_sys_calls_, sendmsg(_, _, _)) .WillOnce(testing::Invoke([this, str](int, const msghdr* message, int) { verifySendData(str, message); return Api::SysCallSizeResult{-1, SOCKET_ERROR_MSG_SIZE}; })); quic::WriteResult result = envoy_quic_writer_.WritePacket(str.data(), str.length(), self_address_, - peer_address_, nullptr); + peer_address_, nullptr, params); // Currently MessageSize should be propagated through error_code. This test // would fail if QUICHE changes to propagate through status in the future. EXPECT_EQ(quic::WRITE_STATUS_ERROR, result.status); diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index 0f2d76724055..3c31ef8fed8a 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -17,7 +17,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/network:94.4" # Flaky, `activateFileEvents`, `startSecureTransport` and `ioctl`, listener_socket do not always report LCOV "source/common/network/dns_resolver:91.6" # A few lines of MacOS code not tested in linux scripts. Tested in MacOS scripts "source/common/protobuf:96.3" -"source/common/quic:93.5" +"source/common/quic:93.4" "source/common/router:96.6" "source/common/secret:95.0" "source/common/signal:87.2" # Death tests don't report LCOV From 3f0b409ec062baec62d650d86333250d0b893df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Sun, 28 May 2023 22:52:57 +0800 Subject: [PATCH 110/228] docs: we can only choose bazelisk via Homebrew (#27644) If we try to install bazelisk & bazel, there will be an error: Error: Cannot install bazel because conflicting formulae are installed. bazelisk: because Bazelisk replaces the bazel binary Please `brew unlink bazelisk` before continuing. The rest of this doc recommends using bazelisk, so we replace bazel here to bazelisk. Signed-off-by: spacewander --- bazel/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazel/README.md b/bazel/README.md index 116399e4904c..38cd9a9f0df3 100644 --- a/bazel/README.md +++ b/bazel/README.md @@ -122,7 +122,7 @@ for how to update or override dependencies. ### macOS On macOS, you'll need to install several dependencies. This can be accomplished via [Homebrew](https://brew.sh/): ```console - brew install coreutils wget libtool go bazel clang-format autoconf aspell + brew install coreutils wget libtool go bazelisk clang-format autoconf aspell ``` _notes_: `coreutils` is used for `realpath`, `gmd5sum` and `gsha256sum` From 5e7900dc7b88faa78d2343e45d58412616320a2e Mon Sep 17 00:00:00 2001 From: Zhewei Hu Date: Sun, 28 May 2023 18:29:22 -0700 Subject: [PATCH 111/228] [ZK filter] update doc for *_resp_fast metrics (#27613) Signed-off-by: Zhewei Hu Co-authored-by: Zhewei Hu --- .../zookeeper_proxy_filter.rst | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/root/configuration/listeners/network_filters/zookeeper_proxy_filter.rst b/docs/root/configuration/listeners/network_filters/zookeeper_proxy_filter.rst index 8f914333364e..b3785d9ec37d 100644 --- a/docs/root/configuration/listeners/network_filters/zookeeper_proxy_filter.rst +++ b/docs/root/configuration/listeners/network_filters/zookeeper_proxy_filter.rst @@ -97,33 +97,33 @@ The following counters are available: getallchildrennumber_resp, Counter, Number of getallchildrennumber responses close_resp, Counter, Number of close responses watch_event, Counter, Number of watch events fired by the server - connect_resp_fast, Counter, Number of connect responses faster than the threshold - ping_resp_fast, Counter, Number of ping responses faster than the threshold - auth_resp_fast, Counter, Number of auth responses faster than the threshold - getdata_resp_fast, Counter, Number of getdata responses faster than the threshold - create_resp_fast, Counter, Number of create responses faster than the threshold - create2_resp_fast, Counter, Number of create2 responses faster than the threshold - createcontainer_resp_fast, Counter, Number of createcontainer responses faster than the threshold - createttl_resp_fast, Counter, Number of createttl responses faster than the threshold - setdata_resp_fast, Counter, Number of setdata responses faster than the threshold - getchildren_resp_fast, Counter, Number of getchildren responses faster than the threshold - getchildren2_resp_fast, Counter, Number of getchildren2 responses faster than the threshold - delete_resp_fast, Counter, Number of delete responses faster than the threshold - exists_resp_fast, Counter, Number of exists responses faster than the threshold - getacl_resp_fast, Counter, Number of getacl responses faster than the threshold - setacl_resp_fast, Counter, Number of setacl responses faster than the threshold - sync_resp_fast, Counter, Number of sync responses faster than the threshold - check_resp_fast, Counter, Number of check responses faster than the threshold - multi_resp_fast, Counter, Number of multi responses faster than the threshold - reconfig_resp_fast, Counter, Number of reconfig responses faster than the threshold - setauth_resp_fast, Counter, Number of setauth responses faster than the threshold - setwatches_resp_fast, Counter, Number of setwatches responses faster than the threshold - setwatches2_resp_fast, Counter, Number of setwatches2 responses faster than the threshold - checkwatches_resp_fast, Counter, Number of checkwatches responses faster than the threshold - removewatches_resp_fast, Counter, Number of removewatches responses faster than the threshold - getephemerals_resp_fast, Counter, Number of getephemerals responses faster than the threshold - getallchildrennumber_resp_fast, Counter, Number of getallchildrennumber responses faster than the threshold - close_resp_fast, Counter, Number of close responses faster than the threshold + connect_resp_fast, Counter, Number of connect responses faster than or equal to the threshold + ping_resp_fast, Counter, Number of ping responses faster than or equal to the threshold + auth_resp_fast, Counter, Number of auth responses faster than or equal to the threshold + getdata_resp_fast, Counter, Number of getdata responses faster than or equal to the threshold + create_resp_fast, Counter, Number of create responses faster than or equal to the threshold + create2_resp_fast, Counter, Number of create2 responses faster than or equal to the threshold + createcontainer_resp_fast, Counter, Number of createcontainer responses faster than or equal to the threshold + createttl_resp_fast, Counter, Number of createttl responses faster than or equal to the threshold + setdata_resp_fast, Counter, Number of setdata responses faster than or equal to the threshold + getchildren_resp_fast, Counter, Number of getchildren responses faster than or equal to the threshold + getchildren2_resp_fast, Counter, Number of getchildren2 responses faster than or equal to the threshold + delete_resp_fast, Counter, Number of delete responses faster than or equal to the threshold + exists_resp_fast, Counter, Number of exists responses faster than or equal to the threshold + getacl_resp_fast, Counter, Number of getacl responses faster than or equal to the threshold + setacl_resp_fast, Counter, Number of setacl responses faster than or equal to the threshold + sync_resp_fast, Counter, Number of sync responses faster than or equal to the threshold + check_resp_fast, Counter, Number of check responses faster than or equal to the threshold + multi_resp_fast, Counter, Number of multi responses faster than or equal to the threshold + reconfig_resp_fast, Counter, Number of reconfig responses faster than or equal to the threshold + setauth_resp_fast, Counter, Number of setauth responses faster than or equal to the threshold + setwatches_resp_fast, Counter, Number of setwatches responses faster than or equal to the threshold + setwatches2_resp_fast, Counter, Number of setwatches2 responses faster than or equal to the threshold + checkwatches_resp_fast, Counter, Number of checkwatches responses faster than or equal to the threshold + removewatches_resp_fast, Counter, Number of removewatches responses faster than or equal to the threshold + getephemerals_resp_fast, Counter, Number of getephemerals responses faster than or equal to the threshold + getallchildrennumber_resp_fast, Counter, Number of getallchildrennumber responses faster than or equal to the threshold + close_resp_fast, Counter, Number of close responses faster than or equal to the threshold connect_resp_slow, Counter, Number of connect responses slower than the threshold ping_resp_slow, Counter, Number of ping responses slower than the threshold auth_resp_slow, Counter, Number of auth responses slower than the threshold From 9b27cf63fb62d0e12ae44d417b1815c299b67b58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 09:26:47 +0100 Subject: [PATCH 112/228] build(deps): bump openpolicyagent/opa from 0.52.0-istio to 0.53.0-istio in /examples/ext_authz (#27671) build(deps): bump openpolicyagent/opa in /examples/ext_authz Bumps openpolicyagent/opa from 0.52.0-istio to 0.53.0-istio. --- updated-dependencies: - dependency-name: openpolicyagent/opa dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/ext_authz/Dockerfile-opa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ext_authz/Dockerfile-opa b/examples/ext_authz/Dockerfile-opa index 950698be7305..70847d7d5ae2 100644 --- a/examples/ext_authz/Dockerfile-opa +++ b/examples/ext_authz/Dockerfile-opa @@ -1 +1 @@ -FROM openpolicyagent/opa:0.52.0-istio@sha256:03fce2c713c1b10c01371aea70aa2630b7a464cce45fe458286a5734ec492a3b +FROM openpolicyagent/opa:0.53.0-istio@sha256:dcf28d23b3d1919b6314ef34342687c558cec64fe4f93fa484e8c8e82824d56d From d8126fa32df3433f57cf95d7f4cabb13c771c4b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 11:30:00 +0100 Subject: [PATCH 113/228] build(deps): bump jaegertracing/all-in-one from `308b14d` to `114816a` in /examples/shared/jaeger (#27670) build(deps): bump jaegertracing/all-in-one in /examples/shared/jaeger Bumps jaegertracing/all-in-one from `308b14d` to `114816a`. --- updated-dependencies: - dependency-name: jaegertracing/all-in-one dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/jaeger/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/jaeger/Dockerfile b/examples/shared/jaeger/Dockerfile index 2c87ffde174e..57dfe7cb60a4 100644 --- a/examples/shared/jaeger/Dockerfile +++ b/examples/shared/jaeger/Dockerfile @@ -1,4 +1,4 @@ -FROM jaegertracing/all-in-one@sha256:308b14daf2ddbc171bd5ce882dd5b12c1bac6446913fbb60b69424f4a34b7ade +FROM jaegertracing/all-in-one@sha256:114816a5808fddda2bdcf85f335d306b279b2cebb1e48d9d1d0f0e9ab53beeb9 HEALTHCHECK \ --interval=1s \ --timeout=1s \ From 32724b8808d451491a7afe32f685769816c6673f Mon Sep 17 00:00:00 2001 From: zhaohuabing Date: Mon, 29 May 2023 18:34:45 +0800 Subject: [PATCH 114/228] support fips-compliant build for arm (#27622) Signed-off-by: Huabing Zhao --- bazel/BUILD | 1 - bazel/external/boringssl_fips.genrule_cmd | 59 +++++++++++++++-------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/bazel/BUILD b/bazel/BUILD index c1557d082179..ca8db723eb3e 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -464,7 +464,6 @@ config_setting( name = "boringssl_fips", constraint_values = [ "@platforms//os:linux", - "@platforms//cpu:x86_64", ], values = {"define": "boringssl=fips"}, ) diff --git a/bazel/external/boringssl_fips.genrule_cmd b/bazel/external/boringssl_fips.genrule_cmd index 37fc301a9f9f..46526a9a84de 100755 --- a/bazel/external/boringssl_fips.genrule_cmd +++ b/bazel/external/boringssl_fips.genrule_cmd @@ -2,15 +2,21 @@ set -e -# BoringSSL build as described in the Security Policy for BoringCrypto module (2020-07-02): -# https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf +export CXXFLAGS='' +export LDFLAGS='' -# This works only on Linux-x86_64. -if [[ `uname` != "Linux" || `uname -m` != "x86_64" ]]; then - echo "ERROR: BoringSSL FIPS is currently supported only on Linux-x86_64." +# BoringSSL build as described in the Security Policy for BoringCrypto module (2022-05-06): +# https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp4407.pdf + +OS=`uname` +ARCH=`uname -m` +# This works only on Linux-x86_64 and Linux-aarch64. +if [[ "$OS" != "Linux" || ("$ARCH" != "x86_64" && "$ARCH" != "aarch64") ]]; then + echo "ERROR: BoringSSL FIPS is currently supported only on Linux-x86_64 and Linux-aarch64." exit 1 fi + # Bazel magic. # ROOT=$(dirname $(rootpath boringssl/BUILDING.md))/.. ROOT=./external/boringssl_fips @@ -27,11 +33,15 @@ export PATH="$(dirname `which cmake`):/usr/bin:/bin" # Clang VERSION=12.0.0 -SHA256=a9ff205eb0b73ca7c86afc6432eed1c2d49133bd0d49e47b15be59bbf0dd292e -PLATFORM="x86_64-linux-gnu-ubuntu-20.04" +if [[ "$ARCH" == "x86_64" ]]; then + PLATFORM="x86_64-linux-gnu-ubuntu-20.04" + SHA256=a9ff205eb0b73ca7c86afc6432eed1c2d49133bd0d49e47b15be59bbf0dd292e +else + PLATFORM="aarch64-linux-gnu" + SHA256=d05f0b04fb248ce1e7a61fcd2087e6be8bc4b06b2cc348792f383abf414dec48 +fi -curl -sLO https://github.com/llvm/llvm-project/releases/download/llvmorg-"$VERSION"/clang+llvm-"$VERSION"-"$PLATFORM".tar.xz \ - && echo "$SHA256" clang+llvm-"$VERSION"-"$PLATFORM".tar.xz | sha256sum --check +curl -sLO https://github.com/llvm/llvm-project/releases/download/llvmorg-"$VERSION"/clang+llvm-"$VERSION"-"$PLATFORM".tar.xz tar xf clang+llvm-"$VERSION"-"$PLATFORM".tar.xz export HOME="$PWD" @@ -45,8 +55,13 @@ fi # Go VERSION=1.16.5 -SHA256=b12c23023b68de22f74c0524f10b753e7b08b1504cb7e417eccebdd3fae49061 -PLATFORM="linux-amd64" +if [[ "$ARCH" == "x86_64" ]]; then + PLATFORM="linux-amd64" + SHA256=b12c23023b68de22f74c0524f10b753e7b08b1504cb7e417eccebdd3fae49061 +else + PLATFORM="linux-arm64" + SHA256=d5446b46ef6f36fdffa852f73dfbbe78c1ddf010b99fa4964944b9ae8b4d6799 +fi curl -sLO https://dl.google.com/go/go"$VERSION"."$PLATFORM".tar.gz \ && echo "$SHA256" go"$VERSION"."$PLATFORM".tar.gz | sha256sum --check @@ -63,12 +78,12 @@ fi # Ninja VERSION=1.10.2 -SHA256=763464859c7ef2ea3a0a10f4df40d2025d3bb9438fcb1228404640410c0ec22d -PLATFORM="linux" - -curl -sLO https://github.com/ninja-build/ninja/releases/download/v"$VERSION"/ninja-"$PLATFORM".zip \ - && echo "$SHA256" ninja-"$PLATFORM".zip | sha256sum --check -unzip -o ninja-"$PLATFORM".zip +SHA256=ce35865411f0490368a8fc383f29071de6690cbadc27704734978221f25e2bed +curl -sLO https://github.com/ninja-build/ninja/archive/refs/tags/v"$VERSION".tar.gz \ + && echo "$SHA256" v"$VERSION".tar.gz | sha256sum --check +tar -xvf v"$VERSION".tar.gz +cd ninja-"$VERSION" +python3 ./configure.py --bootstrap export PATH="$PWD:$PATH" @@ -76,11 +91,17 @@ if [[ `ninja --version` != "$VERSION" ]]; then echo "ERROR: Ninja version doesn't match." exit 1 fi +cd .. # CMake VERSION=3.20.1 -SHA256=b8c141bd7a6d335600ab0a8a35e75af79f95b837f736456b5532f4d717f20a09 -PLATFORM="linux-x86_64" +if [[ "$ARCH" == "x86_64" ]]; then + PLATFORM="linux-x86_64" + SHA256=b8c141bd7a6d335600ab0a8a35e75af79f95b837f736456b5532f4d717f20a09 +else + PLATFORM="linux-aarch64" + SHA256=5ad1f8139498a1956df369c401658ec787f63c8cb4e9759f2edaa51626a86512 +fi curl -sLO https://github.com/Kitware/CMake/releases/download/v"$VERSION"/cmake-"$VERSION"-"$PLATFORM".tar.gz \ && echo "$SHA256" cmake-"$VERSION"-"$PLATFORM".tar.gz | sha256sum --check From f80fd48f5f7417c5aa77ee4f5ca4df6e0f8e625d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 12:27:45 +0100 Subject: [PATCH 115/228] build(deps): bump protobuf from 4.23.1 to 4.23.2 in /examples/grpc-bridge/client (#27668) build(deps): bump protobuf in /examples/grpc-bridge/client Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.23.1 to 4.23.2. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/generate_changelog.py) - [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.23.1...v4.23.2) --- updated-dependencies: - dependency-name: protobuf dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/grpc-bridge/client/requirements.txt | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/grpc-bridge/client/requirements.txt b/examples/grpc-bridge/client/requirements.txt index 41ca3dbc8d03..4044bb58fc62 100644 --- a/examples/grpc-bridge/client/requirements.txt +++ b/examples/grpc-bridge/client/requirements.txt @@ -112,20 +112,20 @@ idna==3.2 \ --hash=sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a \ --hash=sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3 # via requests -protobuf==4.23.1 \ - --hash=sha256:2036a3a1e7fc27f973fa0a7888dce712393af644f4695385f117886abc792e39 \ - --hash=sha256:32e78beda26d7a101fecf15d7a4a792278a0d26a31bc327ff05564a9d68ab8ee \ - --hash=sha256:346990f634272caac1f09efbcfbbacb23098b1f606d172534c6fa2d9758bb436 \ - --hash=sha256:3b8905eafe4439076e1f58e9d1fa327025fd2777cf90f14083092ae47f77b0aa \ - --hash=sha256:3ce113b3f3362493bddc9069c2163a38f240a9ed685ff83e7bcb756b05e1deb0 \ - --hash=sha256:410bcc0a5b279f634d3e16082ce221dfef7c3392fac723500e2e64d1806dd2be \ - --hash=sha256:5b9cd6097e6acae48a68cb29b56bc79339be84eca65b486910bb1e7a30e2b7c1 \ - --hash=sha256:65f0ac96ef67d7dd09b19a46aad81a851b6f85f89725577f16de38f2d68ad477 \ - --hash=sha256:91fac0753c3c4951fbb98a93271c43cc7cf3b93cf67747b3e600bb1e5cc14d61 \ - --hash=sha256:95789b569418a3e32a53f43d7763be3d490a831e9c08042539462b6d972c2d7e \ - --hash=sha256:ac50be82491369a9ec3710565777e4da87c6d2e20404e0abb1f3a8f10ffd20f0 \ - --hash=sha256:decf119d54e820f298ee6d89c72d6b289ea240c32c521f00433f9dc420595f38 \ - --hash=sha256:f9510cac91e764e86acd74e2b7f7bc5e6127a7f3fb646d7c8033cfb84fd1176a +protobuf==4.23.2 \ + --hash=sha256:09310bce43353b46d73ba7e3bca78273b9bc50349509b9698e64d288c6372c2a \ + --hash=sha256:20874e7ca4436f683b64ebdbee2129a5a2c301579a67d1a7dda2cdf62fb7f5f7 \ + --hash=sha256:25e3370eda26469b58b602e29dff069cfaae8eaa0ef4550039cc5ef8dc004511 \ + --hash=sha256:281342ea5eb631c86697e1e048cb7e73b8a4e85f3299a128c116f05f5c668f8f \ + --hash=sha256:384dd44cb4c43f2ccddd3645389a23ae61aeb8cfa15ca3a0f60e7c3ea09b28b3 \ + --hash=sha256:54a533b971288af3b9926e53850c7eb186886c0c84e61daa8444385a4720297f \ + --hash=sha256:6c081863c379bb1741be8f8193e893511312b1d7329b4a75445d1ea9955be69e \ + --hash=sha256:86df87016d290143c7ce3be3ad52d055714ebaebb57cc659c387e76cfacd81aa \ + --hash=sha256:8da6070310d634c99c0db7df48f10da495cc283fd9e9234877f0cd182d43ab7f \ + --hash=sha256:b2cfab63a230b39ae603834718db74ac11e52bccaaf19bf20f5cce1a84cf76df \ + --hash=sha256:c52cfcbfba8eb791255edd675c1fe6056f723bf832fa67f0442218f8817c076e \ + --hash=sha256:ce744938406de1e64b91410f473736e815f28c3b71201302612a68bf01517fea \ + --hash=sha256:efabbbbac1ab519a514579ba9ec52f006c28ae19d97915951f69fa70da2c9e91 # via # -r requirements.in # grpcio-tools From af8aef48b5395d32d4bbac5aa3ed0a84d3bf31d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 12:31:22 +0100 Subject: [PATCH 116/228] build(deps): bump github/codeql-action from 2.3.4 to 2.3.5 (#27647) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.4 to 2.3.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f0e3dfb30302f8a0881bb509b044e0de4f6ef589...0225834cc549ee0ca93cb085b92954821a145866) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-daily.yml | 4 ++-- .github/workflows/codeql-push.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 660eec1f12a5..b81e86623169 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -33,7 +33,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 + uses: github/codeql-action/init@0225834cc549ee0ca93cb085b92954821a145866 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -64,4 +64,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 + uses: github/codeql-action/analyze@0225834cc549ee0ca93cb085b92954821a145866 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index fcb710edb6e4..b1ab668242b7 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 + uses: github/codeql-action/init@0225834cc549ee0ca93cb085b92954821a145866 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -78,4 +78,4 @@ jobs: - name: Perform CodeQL Analysis if: env.BUILD_TARGETS != '' - uses: github/codeql-action/analyze@f0e3dfb30302f8a0881bb509b044e0de4f6ef589 + uses: github/codeql-action/analyze@0225834cc549ee0ca93cb085b92954821a145866 From 69ebcab163608f172fe5ac5e7092353e1264b1a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 May 2023 08:53:23 +0100 Subject: [PATCH 117/228] build(deps): bump github.com/envoyproxy/go-control-plane from 0.11.0 to 0.11.1 in /examples/ext_authz/auth/grpc-service (#27683) build(deps): bump github.com/envoyproxy/go-control-plane Bumps [github.com/envoyproxy/go-control-plane](https://github.com/envoyproxy/go-control-plane) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/envoyproxy/go-control-plane/releases) - [Changelog](https://github.com/envoyproxy/go-control-plane/blob/main/CHANGELOG.md) - [Commits](https://github.com/envoyproxy/go-control-plane/compare/v0.11.0...v0.11.1) --- updated-dependencies: - dependency-name: github.com/envoyproxy/go-control-plane dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/ext_authz/auth/grpc-service/go.mod | 4 +- examples/ext_authz/auth/grpc-service/go.sum | 134 +++++++++++++++++++- 2 files changed, 129 insertions(+), 9 deletions(-) diff --git a/examples/ext_authz/auth/grpc-service/go.mod b/examples/ext_authz/auth/grpc-service/go.mod index a1a9385404d8..8bc653ebc6e5 100644 --- a/examples/ext_authz/auth/grpc-service/go.mod +++ b/examples/ext_authz/auth/grpc-service/go.mod @@ -3,8 +3,8 @@ module github.com/envoyproxy/envoy/examples/ext_authz/auth/grpc-service go 1.14 require ( - github.com/envoyproxy/go-control-plane v0.11.0 + github.com/envoyproxy/go-control-plane v0.11.1 github.com/golang/protobuf v1.5.3 - google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 + google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e google.golang.org/grpc v1.55.0 ) diff --git a/examples/ext_authz/auth/grpc-service/go.sum b/examples/ext_authz/auth/grpc-service/go.sum index ed297be4e25b..3eb080a7e70a 100644 --- a/examples/ext_authz/auth/grpc-service/go.sum +++ b/examples/ext_authz/auth/grpc-service/go.sum @@ -42,13 +42,18 @@ cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wx cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= @@ -57,25 +62,35 @@ cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= @@ -96,6 +111,7 @@ cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oe cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -105,12 +121,16 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= @@ -122,9 +142,12 @@ cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5v cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= @@ -133,6 +156,7 @@ cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uX cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= @@ -146,6 +170,7 @@ cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARy cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -156,9 +181,12 @@ cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iW cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= @@ -166,6 +194,7 @@ cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= @@ -173,6 +202,7 @@ cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KF cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= @@ -182,6 +212,7 @@ cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxB cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= @@ -191,14 +222,17 @@ cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZW cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= @@ -206,6 +240,7 @@ cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= @@ -214,12 +249,14 @@ cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= @@ -227,15 +264,19 @@ cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aU cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= @@ -250,6 +291,7 @@ cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+o cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= @@ -265,19 +307,26 @@ cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQE cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= @@ -296,6 +345,7 @@ cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtq cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= @@ -312,22 +362,26 @@ cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJP cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= @@ -353,9 +407,11 @@ cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2om cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -363,8 +419,10 @@ cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjp cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= @@ -372,6 +430,7 @@ cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7d cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= @@ -388,6 +447,8 @@ cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0 cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= @@ -399,11 +460,13 @@ cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQk cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= @@ -414,35 +477,44 @@ cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3s cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -453,9 +525,11 @@ cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= @@ -470,12 +544,18 @@ cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV6 cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= @@ -487,11 +567,14 @@ cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiC cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= @@ -522,6 +605,7 @@ github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGW github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -547,8 +631,9 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74 h1:zlUubfBUxApscKFsF4VSvvfhsBNTBu0eF/ddvpo96yk= +github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -564,13 +649,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ= +github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -681,6 +768,7 @@ github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -710,6 +798,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= @@ -728,6 +817,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -750,6 +840,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -836,6 +927,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -891,8 +983,10 @@ golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1012,8 +1106,10 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1021,6 +1117,8 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1035,13 +1133,15 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1103,6 +1203,7 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1174,6 +1275,8 @@ google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1305,8 +1408,23 @@ google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= +google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= +google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e h1:NumxXLPfHSndr3wBBdeKiVHjGVFzi9RX2HwwQke94iY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1346,6 +1464,7 @@ google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1364,6 +1483,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 3a8ad2fe8afa7a6ab428ded663b3b34cf8f02500 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 May 2023 09:39:49 +0100 Subject: [PATCH 118/228] build(deps): bump github.com/envoyproxy/go-control-plane from 0.11.0 to 0.11.1 in /examples/load-reporting-service (#27682) build(deps): bump github.com/envoyproxy/go-control-plane Bumps [github.com/envoyproxy/go-control-plane](https://github.com/envoyproxy/go-control-plane) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/envoyproxy/go-control-plane/releases) - [Changelog](https://github.com/envoyproxy/go-control-plane/blob/main/CHANGELOG.md) - [Commits](https://github.com/envoyproxy/go-control-plane/compare/v0.11.0...v0.11.1) --- updated-dependencies: - dependency-name: github.com/envoyproxy/go-control-plane dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/load-reporting-service/go.mod | 2 +- examples/load-reporting-service/go.sum | 134 +++++++++++++++++++++++-- 2 files changed, 128 insertions(+), 8 deletions(-) diff --git a/examples/load-reporting-service/go.mod b/examples/load-reporting-service/go.mod index 99b9d340b241..a7de6e377294 100644 --- a/examples/load-reporting-service/go.mod +++ b/examples/load-reporting-service/go.mod @@ -3,7 +3,7 @@ module github.com/envoyproxy/envoy/examples/load-reporting-service go 1.13 require ( - github.com/envoyproxy/go-control-plane v0.11.0 + github.com/envoyproxy/go-control-plane v0.11.1 github.com/golang/protobuf v1.5.3 google.golang.org/grpc v1.55.0 ) diff --git a/examples/load-reporting-service/go.sum b/examples/load-reporting-service/go.sum index ed297be4e25b..3eb080a7e70a 100644 --- a/examples/load-reporting-service/go.sum +++ b/examples/load-reporting-service/go.sum @@ -42,13 +42,18 @@ cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wx cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= @@ -57,25 +62,35 @@ cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= @@ -96,6 +111,7 @@ cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oe cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -105,12 +121,16 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= @@ -122,9 +142,12 @@ cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5v cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= @@ -133,6 +156,7 @@ cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uX cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= @@ -146,6 +170,7 @@ cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARy cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -156,9 +181,12 @@ cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iW cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= @@ -166,6 +194,7 @@ cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= @@ -173,6 +202,7 @@ cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KF cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= @@ -182,6 +212,7 @@ cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxB cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= @@ -191,14 +222,17 @@ cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZW cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= @@ -206,6 +240,7 @@ cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= @@ -214,12 +249,14 @@ cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= @@ -227,15 +264,19 @@ cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aU cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= @@ -250,6 +291,7 @@ cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+o cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= @@ -265,19 +307,26 @@ cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQE cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= @@ -296,6 +345,7 @@ cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtq cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= @@ -312,22 +362,26 @@ cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJP cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= @@ -353,9 +407,11 @@ cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2om cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -363,8 +419,10 @@ cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjp cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= @@ -372,6 +430,7 @@ cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7d cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= @@ -388,6 +447,8 @@ cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0 cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= @@ -399,11 +460,13 @@ cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQk cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= @@ -414,35 +477,44 @@ cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3s cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -453,9 +525,11 @@ cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= @@ -470,12 +544,18 @@ cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV6 cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= @@ -487,11 +567,14 @@ cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiC cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= @@ -522,6 +605,7 @@ github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGW github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -547,8 +631,9 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74 h1:zlUubfBUxApscKFsF4VSvvfhsBNTBu0eF/ddvpo96yk= +github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -564,13 +649,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ= +github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -681,6 +768,7 @@ github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -710,6 +798,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= @@ -728,6 +817,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -750,6 +840,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -836,6 +927,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -891,8 +983,10 @@ golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1012,8 +1106,10 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1021,6 +1117,8 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1035,13 +1133,15 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1103,6 +1203,7 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1174,6 +1275,8 @@ google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1305,8 +1408,23 @@ google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= +google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= +google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e h1:NumxXLPfHSndr3wBBdeKiVHjGVFzi9RX2HwwQke94iY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1346,6 +1464,7 @@ google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1364,6 +1483,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 08ddc06c9469825f2ce3ae423947b8e5b170143c Mon Sep 17 00:00:00 2001 From: Zhewei Hu Date: Tue, 30 May 2023 02:01:01 -0700 Subject: [PATCH 119/228] [ZK filter] pass std::chrono::milliseconds by value (#27533) Signed-off-by: Zhewei Hu --- .../extensions/filters/network/zookeeper_proxy/decoder.cc | 2 +- source/extensions/filters/network/zookeeper_proxy/decoder.h | 6 +++--- source/extensions/filters/network/zookeeper_proxy/filter.cc | 4 ++-- source/extensions/filters/network/zookeeper_proxy/filter.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/extensions/filters/network/zookeeper_proxy/decoder.cc b/source/extensions/filters/network/zookeeper_proxy/decoder.cc index cce503acb9f9..18a9ee1129da 100644 --- a/source/extensions/filters/network/zookeeper_proxy/decoder.cc +++ b/source/extensions/filters/network/zookeeper_proxy/decoder.cc @@ -617,7 +617,7 @@ void DecoderImpl::decode(Buffer::Instance& data, DecodeType dtype, uint64_t full } void DecoderImpl::parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, - const std::chrono::milliseconds& latency) { + const std::chrono::milliseconds latency) { ensureMinLength(len, PROTOCOL_VERSION_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); const auto timeout = helper_.peekInt32(data, offset); diff --git a/source/extensions/filters/network/zookeeper_proxy/decoder.h b/source/extensions/filters/network/zookeeper_proxy/decoder.h index af737a6753d3..540cff9d8e23 100644 --- a/source/extensions/filters/network/zookeeper_proxy/decoder.h +++ b/source/extensions/filters/network/zookeeper_proxy/decoder.h @@ -101,9 +101,9 @@ class DecoderCallbacks { virtual void onCloseRequest() PURE; virtual void onResponseBytes(uint64_t bytes) PURE; virtual void onConnectResponse(int32_t proto_version, int32_t timeout, bool readonly, - const std::chrono::milliseconds& latency) PURE; + const std::chrono::milliseconds latency) PURE; virtual void onResponse(OpCodes opcode, int32_t xid, int64_t zxid, int32_t error, - const std::chrono::milliseconds& latency) PURE; + const std::chrono::milliseconds latency) PURE; virtual void onWatchEvent(int32_t event_type, int32_t client_state, const std::string& path, int64_t zxid, int32_t error) PURE; }; @@ -174,7 +174,7 @@ class DecoderImpl : public Decoder, Logger::Loggable { void ensureMaxLength(int32_t len) const; std::string pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); void parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, - const std::chrono::milliseconds& latency); + const std::chrono::milliseconds latency); void parseWatchEvent(Buffer::Instance& data, uint64_t& offset, uint32_t len, int64_t zxid, int32_t error); bool maybeReadBool(Buffer::Instance& data, uint64_t& offset); diff --git a/source/extensions/filters/network/zookeeper_proxy/filter.cc b/source/extensions/filters/network/zookeeper_proxy/filter.cc index 665c61ce09e0..a6369e84444a 100644 --- a/source/extensions/filters/network/zookeeper_proxy/filter.cc +++ b/source/extensions/filters/network/zookeeper_proxy/filter.cc @@ -368,7 +368,7 @@ void ZooKeeperFilter::onCloseRequest() { void ZooKeeperFilter::onConnectResponse(const int32_t proto_version, const int32_t timeout, const bool readonly, - const std::chrono::milliseconds& latency) { + const std::chrono::milliseconds latency) { config_->stats_.connect_resp_.inc(); switch (config_->errorBudgetDecision(OpCodes::Connect, latency)) { @@ -394,7 +394,7 @@ void ZooKeeperFilter::onConnectResponse(const int32_t proto_version, const int32 } void ZooKeeperFilter::onResponse(const OpCodes opcode, const int32_t xid, const int64_t zxid, - const int32_t error, const std::chrono::milliseconds& latency) { + const int32_t error, const std::chrono::milliseconds latency) { Stats::StatName opcode_latency = config_->unknown_opcode_latency_; std::string opname = ""; auto iter = config_->op_code_map_.find(opcode); diff --git a/source/extensions/filters/network/zookeeper_proxy/filter.h b/source/extensions/filters/network/zookeeper_proxy/filter.h index 85dbb04cb322..483c5653a59f 100644 --- a/source/extensions/filters/network/zookeeper_proxy/filter.h +++ b/source/extensions/filters/network/zookeeper_proxy/filter.h @@ -291,9 +291,9 @@ class ZooKeeperFilter : public Network::Filter, void onCloseRequest() override; void onResponseBytes(uint64_t bytes) override; void onConnectResponse(int32_t proto_version, int32_t timeout, bool readonly, - const std::chrono::milliseconds& latency) override; + const std::chrono::milliseconds latency) override; void onResponse(OpCodes opcode, int32_t xid, int64_t zxid, int32_t error, - const std::chrono::milliseconds& latency) override; + const std::chrono::milliseconds latency) override; void onWatchEvent(int32_t event_type, int32_t client_state, const std::string& path, int64_t zxid, int32_t error) override; From 891329516d9e68c248763308f3c8a52c5ea32261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Tue, 30 May 2023 18:53:05 +0800 Subject: [PATCH 120/228] golang filter: reject if the cgocheck is not disabled (#27677) Signed-off-by: spacewander --- .../filters/http/source/go/pkg/api/BUILD | 1 + .../http/source/go/pkg/api/cgocheck.go | 32 +++++++++++++++++++ .../filters/http/source/go/pkg/http/config.go | 5 +++ 3 files changed, 38 insertions(+) create mode 100644 contrib/golang/filters/http/source/go/pkg/api/cgocheck.go diff --git a/contrib/golang/filters/http/source/go/pkg/api/BUILD b/contrib/golang/filters/http/source/go/pkg/api/BUILD index 45b8bc46cb1a..392f1cab149d 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/BUILD +++ b/contrib/golang/filters/http/source/go/pkg/api/BUILD @@ -6,6 +6,7 @@ go_library( name = "api", srcs = [ "capi.go", + "cgocheck.go", "filter.go", "type.go", ], diff --git a/contrib/golang/filters/http/source/go/pkg/api/cgocheck.go b/contrib/golang/filters/http/source/go/pkg/api/cgocheck.go new file mode 100644 index 000000000000..01c6f84c8c40 --- /dev/null +++ b/contrib/golang/filters/http/source/go/pkg/api/cgocheck.go @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package api + +import ( + "os" + "strings" +) + +func CgoCheckDisabled() bool { + env := os.Getenv("GODEBUG") + // TODO: handle compile-time GODEBUG var after Go 1.21 is released + if strings.Index(env, "cgocheck=0") != -1 { + return true + } + return false +} diff --git a/contrib/golang/filters/http/source/go/pkg/http/config.go b/contrib/golang/filters/http/source/go/pkg/http/config.go index 703c5bdf97e5..b58b2dfd9f0d 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/config.go +++ b/contrib/golang/filters/http/source/go/pkg/http/config.go @@ -50,6 +50,11 @@ var ( //export envoyGoFilterNewHttpPluginConfig func envoyGoFilterNewHttpPluginConfig(namePtr, nameLen, configPtr, configLen uint64) uint64 { + if !api.CgoCheckDisabled() { + cAPI.HttpLog(api.Error, "The Envoy Golang filter requires the `GODEBUG=cgocheck=0` environment variable set.") + return 0 + } + buf := utils.BytesToSlice(configPtr, configLen) var any anypb.Any proto.Unmarshal(buf, &any) From 86537d1640e47b386e2f466e58931ccfa8aca770 Mon Sep 17 00:00:00 2001 From: norbjd Date: Tue, 30 May 2023 15:02:02 +0200 Subject: [PATCH 121/228] tooling: include protoc-gen-jsonschema repository (#27661) Signed-off-by: norbjd --- api/bazel/repositories.bzl | 4 ++++ api/bazel/repository_locations.bzl | 11 +++++++++++ bazel/dependency_imports.bzl | 3 +++ 3 files changed, 18 insertions(+) diff --git a/api/bazel/repositories.bzl b/api/bazel/repositories.bzl index b49db8c59a0c..8142c827e981 100644 --- a/api/bazel/repositories.bzl +++ b/api/bazel/repositories.bzl @@ -49,6 +49,10 @@ def api_dependencies(): build_file_content = BUF_BUILD_CONTENT, ) + external_http_archive( + name = "com_github_chrusty_protoc_gen_jsonschema", + ) + PROMETHEUSMETRICS_BUILD_CONTENT = """ load("@envoy_api//bazel:api_build_system.bzl", "api_cc_py_proto_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index c259e3633f93..670c0ad4fc04 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -140,4 +140,15 @@ REPOSITORY_LOCATIONS_SPEC = dict( license = "Apache-2.0", license_url = "https://github.com/bufbuild/buf/blob/v{version}/LICENSE", ), + com_github_chrusty_protoc_gen_jsonschema = dict( + project_name = "protoc-gen-jsonschema", + project_desc = "Protobuf to JSON-Schema compiler", + project_url = "https://github.com/norbjd/protoc-gen-jsonschema", + strip_prefix = "protoc-gen-jsonschema-{version}", + sha256 = "ba3e313b10a1b50a6c1232d994c13f6e23d3669be4ae7fea13762f42bb3b2abc", + version = "7680e4998426e62b6896995ff73d4d91cc5fb13c", + urls = ["https://github.com/norbjd/protoc-gen-jsonschema/archive/{version}.zip"], + use_category = ["build"], + release_date = "2023-05-30", + ), ) diff --git a/bazel/dependency_imports.bzl b/bazel/dependency_imports.bzl index 72c90bf19d74..b743a1936d0d 100644 --- a/bazel/dependency_imports.bzl +++ b/bazel/dependency_imports.bzl @@ -15,6 +15,7 @@ load("@emsdk//:emscripten_deps.bzl", "emscripten_deps") load("@com_github_aignas_rules_shellcheck//:deps.bzl", "shellcheck_dependencies") load("@aspect_bazel_lib//lib:repositories.bzl", "register_jq_toolchains", "register_yq_toolchains") load("@com_google_cel_cpp//bazel:deps.bzl", "parser_deps") +load("@com_github_chrusty_protoc_gen_jsonschema//:deps.bzl", protoc_gen_jsonschema_go_dependencies = "go_dependencies") # go version for rules_go GO_VERSION = "1.18" @@ -146,6 +147,8 @@ def envoy_dependency_imports(go_version = GO_VERSION, jq_version = JQ_VERSION, y # source = "https://github.com/bufbuild/protoc-gen-validate/blob/v0.6.1/dependencies.bzl#L23-L28" ) + protoc_gen_jsonschema_go_dependencies() + def envoy_download_go_sdks(go_version): go_download_sdk( name = "go_linux_amd64", From da913546f6647ffd91939faa54cecc19868db449 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 30 May 2023 14:48:32 +0100 Subject: [PATCH 122/228] deps: Bump `rules_python` -> 0.22.0 (#27688) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index f6769dc0c707..938da6a0bf74 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -884,9 +884,9 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Python rules for Bazel", project_desc = "Bazel rules for the Python language", project_url = "https://github.com/bazelbuild/rules_python", - version = "0.20.0", - sha256 = "a644da969b6824cc87f8fe7b18101a8a6c57da5db39caa6566ec6109f37d2141", - release_date = "2023-03-20", + version = "0.22.0", + sha256 = "863ba0fa944319f7e3d695711427d9ad80ba92c6edd0b7c7443b84e904689539", + release_date = "2023-05-25", strip_prefix = "rules_python-{version}", urls = ["https://github.com/bazelbuild/rules_python/archive/{version}.tar.gz"], use_category = ["build"], From 8d85d3534dde5e3a1ba4b21617b8a04492383225 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 30 May 2023 14:48:55 +0100 Subject: [PATCH 123/228] deps: Bump `com_github_c_ares_c_ares` -> 1.19.1 (#27685) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 938da6a0bf74..b99962c6db20 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -207,12 +207,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "c-ares", project_desc = "C library for asynchronous DNS requests", project_url = "https://c-ares.haxx.se/", - version = "1.19.0", - sha256 = "bfceba37e23fd531293829002cac0401ef49a6dc55923f7f92236585b7ad1dd3", + version = "1.19.1", + sha256 = "321700399b72ed0e037d0074c629e7741f6b2ec2dda92956abe3e9671d3e268e", strip_prefix = "c-ares-{version}", urls = ["https://github.com/c-ares/c-ares/releases/download/cares-{underscore_version}/c-ares-{version}.tar.gz"], use_category = ["dataplane_core", "controlplane"], - release_date = "2023-01-28", + release_date = "2023-05-22", cpe = "cpe:2.3:a:c-ares_project:c-ares:*", license = "c-ares", license_url = "https://github.com/c-ares/c-ares/blob/cares-{underscore_version}/LICENSE.md", From e9574b229551d3f3509315475ad60451d10579a1 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 30 May 2023 14:49:15 +0100 Subject: [PATCH 124/228] deps: Bump `rules_rust` -> 0.22.0 (#27689) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index b99962c6db20..350791fd267e 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1321,12 +1321,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Bazel rust rules", project_desc = "Bazel rust rules (used by Wasm)", project_url = "https://github.com/bazelbuild/rules_rust", - version = "0.21.1", - sha256 = "25209daff2ba21e818801c7b2dab0274c43808982d6aea9f796d899db6319146", + version = "0.22.0", + sha256 = "50272c39f20a3a3507cb56dcb5c3b348bda697a7d868708449e2fa6fb893444c", urls = ["https://github.com/bazelbuild/rules_rust/releases/download/{version}/rules_rust-v{version}.tar.gz"], use_category = ["dataplane_ext"], extensions = ["envoy.wasm.runtime.wasmtime"], - release_date = "2023-04-24", + release_date = "2023-05-22", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_rust/blob/{version}/LICENSE.txt", From abeed2f37528901d22bdb8f92fe1acad4bacae0b Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 30 May 2023 14:49:41 +0100 Subject: [PATCH 125/228] deps: Bump `com_github_google_perfetto` -> 34.0 (#27691) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 350791fd267e..123d1b13a58f 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -193,12 +193,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Perfetto", project_desc = "Perfetto Tracing SDK", project_url = "https://perfetto.dev/", - version = "32.1", - sha256 = "0d1088b4758b3d5f3813178c6de22386329d42407d23aa1479f20dce96e49d78", + version = "34.0", + sha256 = "81dbf2fac446a0389c80e309b2060dcccd926012ce2a61621a47e3e432aee8c1", strip_prefix = "perfetto-{version}/sdk", urls = ["https://github.com/google/perfetto/archive/v{version}.tar.gz"], use_category = ["dataplane_core", "controlplane"], - release_date = "2023-02-01", + release_date = "2023-05-02", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/google/perfetto/blob/v{version}/LICENSE", From cac2ac36ebb92f9602401700d9181ecc33811d56 Mon Sep 17 00:00:00 2001 From: StarryNight Date: Tue, 30 May 2023 23:06:17 +0800 Subject: [PATCH 126/228] add go extension trailer get raw api (#27676) Signed-off-by: wangkai19 --- contrib/golang/filters/http/source/go/pkg/http/type.go | 4 +++- contrib/golang/filters/http/test/golang_integration_test.cc | 5 +++++ contrib/golang/filters/http/test/test_data/basic/filter.go | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/contrib/golang/filters/http/source/go/pkg/http/type.go b/contrib/golang/filters/http/source/go/pkg/http/type.go index 411f7db12d7a..a9c35dd85ca1 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/type.go +++ b/contrib/golang/filters/http/source/go/pkg/http/type.go @@ -180,7 +180,9 @@ func (h *requestOrResponseTrailerMapImpl) initTrailers() { } func (h *requestOrResponseTrailerMapImpl) GetRaw(key string) string { - panic("unsupported yet") + var value string + cAPI.HttpGetHeader(unsafe.Pointer(h.request.req), &key, &value) + return value } func (h *requestOrResponseTrailerMapImpl) Get(key string) (string, bool) { diff --git a/contrib/golang/filters/http/test/golang_integration_test.cc b/contrib/golang/filters/http/test/golang_integration_test.cc index 71c8f8fee378..efda0c3f4541 100644 --- a/contrib/golang/filters/http/test/golang_integration_test.cc +++ b/contrib/golang/filters/http/test/golang_integration_test.cc @@ -298,6 +298,11 @@ name: golang true, upstream_request_->trailers()->get(Http::LowerCaseString("x-test-trailer-1")).empty()); + // check trailer value which add in golang: x-test-trailer-2 + entries = upstream_request_->trailers()->get(Http::LowerCaseString("x-test-trailer-2")); + + EXPECT_EQ("bar", entries[0]->value().getStringView()); + Http::TestResponseHeaderMapImpl response_headers{ {":status", "200"}, {"x-test-header-0", "foo"}, diff --git a/contrib/golang/filters/http/test/test_data/basic/filter.go b/contrib/golang/filters/http/test/test_data/basic/filter.go index 93870973acd2..3d73cd9df187 100644 --- a/contrib/golang/filters/http/test/test_data/basic/filter.go +++ b/contrib/golang/filters/http/test/test_data/basic/filter.go @@ -196,6 +196,10 @@ func (f *filter) decodeTrailers(trailers api.RequestTrailerMap) api.StatusType { trailers.Set("x-test-trailer-0", "bar") trailers.Del("x-test-trailer-1") + if trailers.GetRaw("existed-trailer") == "foo" { + trailers.Add("x-test-trailer-2", "bar") + } + if f.panic == "decode-trailer" { badcode() } From 2f511b5d528622d0d2c2e0d592b09b746a4369b9 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 30 May 2023 16:16:13 +0100 Subject: [PATCH 127/228] examples: Fix for cache example (#27695) Not sure why this has not failed before, but the current code is definitely not correct Signed-off-by: Ryan Northey --- examples/cache/service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/cache/service.py b/examples/cache/service.py index 08c98df447fd..aff199544db3 100644 --- a/examples/cache/service.py +++ b/examples/cache/service.py @@ -1,5 +1,6 @@ import hashlib import os +import re import datetime from typing import Optional From f0a949c403a41b7ff2a3e72a7a232e0179373cf7 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 30 May 2023 16:38:54 +0100 Subject: [PATCH 128/228] deps: Bump `bazel_gazelle` -> 0.31.0 (#27694) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 123d1b13a58f..a401e54c11af 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -33,10 +33,10 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Gazelle", project_desc = "Bazel BUILD file generator for Go projects", project_url = "https://github.com/bazelbuild/bazel-gazelle", - version = "0.30.0", - sha256 = "727f3e4edd96ea20c29e8c2ca9e8d2af724d8c7778e7923a854b2c80952bc405", + version = "0.31.0", + sha256 = "29d5dafc2a5582995488c6735115d1d366fcd6a0fc2e2a153f02988706349825", urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/v{version}/bazel-gazelle-v{version}.tar.gz"], - release_date = "2023-03-30", + release_date = "2023-05-27", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/bazelbuild/bazel-gazelle/blob/v{version}/LICENSE", From ddac503792e67cabf9e593ed89ce829fb693b3b5 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 30 May 2023 16:39:08 +0100 Subject: [PATCH 129/228] deps: Bump `com_github_bufbuild_buf` -> 1.19.0 (#27690) Signed-off-by: Ryan Northey --- api/bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/bazel/repository_locations.bzl b/api/bazel/repository_locations.bzl index 670c0ad4fc04..4a95ca496959 100644 --- a/api/bazel/repository_locations.bzl +++ b/api/bazel/repository_locations.bzl @@ -131,11 +131,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "buf", project_desc = "A new way of working with Protocol Buffers.", # Used for breaking change detection in API protobufs project_url = "https://buf.build", - version = "1.14.0", - sha256 = "9ab382081872df03faaf192cfa82566d32436cfd78782035e94b4d04a982620f", + version = "1.19.0", + sha256 = "ff35aa96b54037d492d30a21dce8d96d47693a761487f98551d750407c27c285", strip_prefix = "buf", urls = ["https://github.com/bufbuild/buf/releases/download/v{version}/buf-Linux-x86_64.tar.gz"], - release_date = "2023-02-09", + release_date = "2023-05-17", use_category = ["api"], license = "Apache-2.0", license_url = "https://github.com/bufbuild/buf/blob/v{version}/LICENSE", From 7f51511d154e53eda1d93a856bf23aec7f75eb4a Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 30 May 2023 12:00:24 -0400 Subject: [PATCH 130/228] mobile: moving test filters to test directory (#27611) Signed-off-by: Alyssa Wilk --- mobile/envoy_build_config/BUILD | 16 ++++++------- mobile/envoy_build_config/test_extensions.cc | 18 ++++++++------ .../extensions/filters/http/assertion/BUILD | 23 ------------------ .../common/http/filters}/assertion/BUILD | 24 +++++++++++++++---- .../assertion/assertion_filter_test.cc | 6 ++--- .../common/http/filters}/assertion/config.cc | 4 ++-- .../common/http/filters}/assertion/config.h | 4 ++-- .../common/http/filters}/assertion/filter.cc | 2 +- .../common/http/filters}/assertion/filter.h | 2 +- .../http/filters}/assertion/filter.proto | 0 .../http/filters}/route_cache_reset/BUILD | 10 ++++---- .../http/filters}/route_cache_reset/config.cc | 4 ++-- .../http/filters}/route_cache_reset/config.h | 4 ++-- .../http/filters}/route_cache_reset/filter.cc | 2 +- .../http/filters}/route_cache_reset/filter.h | 2 +- .../filters}/route_cache_reset/filter.proto | 0 .../common/http/filters}/test_accessor/BUILD | 10 ++++---- .../http/filters}/test_accessor/config.cc | 4 ++-- .../http/filters}/test_accessor/config.h | 6 ++--- .../http/filters}/test_accessor/filter.cc | 2 +- .../http/filters}/test_accessor/filter.h | 3 ++- .../http/filters}/test_accessor/filter.proto | 0 .../http/filters}/test_event_tracker/BUILD | 10 ++++---- .../filters}/test_event_tracker/config.cc | 4 ++-- .../http/filters}/test_event_tracker/config.h | 6 ++--- .../filters}/test_event_tracker/filter.cc | 2 +- .../http/filters}/test_event_tracker/filter.h | 3 ++- .../filters}/test_event_tracker/filter.proto | 0 .../common/http/filters}/test_kv_store/BUILD | 10 ++++---- .../http/filters}/test_kv_store/config.cc | 4 ++-- .../http/filters}/test_kv_store/config.h | 6 ++--- .../http/filters}/test_kv_store/filter.cc | 2 +- .../http/filters}/test_kv_store/filter.h | 3 ++- .../http/filters}/test_kv_store/filter.proto | 0 .../common/http/filters}/test_logger/BUILD | 10 ++++---- .../http/filters}/test_logger/config.cc | 4 ++-- .../common/http/filters}/test_logger/config.h | 6 ++--- .../common/http/filters}/test_logger/filter.h | 2 +- .../http/filters}/test_logger/filter.proto | 0 .../common/http/filters}/test_read/BUILD | 10 ++++---- .../common/http/filters}/test_read/config.cc | 4 ++-- .../common/http/filters}/test_read/config.h | 4 ++-- .../common/http/filters}/test_read/filter.cc | 2 +- .../common/http/filters}/test_read/filter.h | 2 +- .../http/filters}/test_read/filter.proto | 0 .../http/filters}/test_remote_response/BUILD | 10 ++++---- .../filters}/test_remote_response/config.cc | 4 ++-- .../filters}/test_remote_response/config.h | 4 ++-- .../filters}/test_remote_response/filter.cc | 2 +- .../filters}/test_remote_response/filter.h | 2 +- .../test_remote_response/filter.proto | 0 tools/code_format/check_format.py | 2 +- 52 files changed, 131 insertions(+), 133 deletions(-) delete mode 100644 mobile/test/common/extensions/filters/http/assertion/BUILD rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/assertion/BUILD (67%) rename mobile/test/common/{extensions/filters/http => http/filters}/assertion/assertion_filter_test.cc (98%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/assertion/config.cc (86%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/assertion/config.h (85%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/assertion/filter.cc (99%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/assertion/filter.h (96%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/assertion/filter.proto (100%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/route_cache_reset/BUILD (86%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/route_cache_reset/config.cc (83%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/route_cache_reset/config.h (84%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/route_cache_reset/filter.cc (93%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/route_cache_reset/filter.h (94%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/route_cache_reset/filter.proto (100%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_accessor/BUILD (88%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_accessor/config.cc (85%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_accessor/config.h (79%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_accessor/filter.cc (93%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_accessor/filter.h (94%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_accessor/filter.proto (100%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_event_tracker/BUILD (88%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_event_tracker/config.cc (85%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_event_tracker/config.h (79%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_event_tracker/filter.cc (93%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_event_tracker/filter.h (95%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_event_tracker/filter.proto (100%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_kv_store/BUILD (89%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_kv_store/config.cc (86%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_kv_store/config.h (80%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_kv_store/filter.cc (95%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_kv_store/filter.h (96%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_kv_store/filter.proto (100%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_logger/BUILD (86%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_logger/config.cc (83%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_logger/config.h (78%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_logger/filter.h (88%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_logger/filter.proto (100%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_read/BUILD (87%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_read/config.cc (83%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_read/config.h (85%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_read/filter.cc (96%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_read/filter.h (93%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_read/filter.proto (100%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_remote_response/BUILD (90%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_remote_response/config.cc (83%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_remote_response/config.h (84%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_remote_response/filter.cc (96%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_remote_response/filter.h (92%) rename mobile/{library/common/extensions/filters/http => test/common/http/filters}/test_remote_response/filter.proto (100%) diff --git a/mobile/envoy_build_config/BUILD b/mobile/envoy_build_config/BUILD index 3b3c27bddcf1..49edbf5a85ff 100644 --- a/mobile/envoy_build_config/BUILD +++ b/mobile/envoy_build_config/BUILD @@ -115,14 +115,14 @@ envoy_cc_library( deps = [ "@envoy//source/extensions/clusters/static:static_cluster_lib", "@envoy//source/extensions/filters/http/buffer:config", - "@envoy_mobile//library/common/extensions/filters/http/assertion:config", - "@envoy_mobile//library/common/extensions/filters/http/route_cache_reset:config", - "@envoy_mobile//library/common/extensions/filters/http/test_accessor:config", - "@envoy_mobile//library/common/extensions/filters/http/test_event_tracker:config", - "@envoy_mobile//library/common/extensions/filters/http/test_kv_store:config", - "@envoy_mobile//library/common/extensions/filters/http/test_logger:config", - "@envoy_mobile//library/common/extensions/filters/http/test_read:config", - "@envoy_mobile//library/common/extensions/filters/http/test_remote_response:config", + "@envoy_mobile//test/common/http/filters/assertion:config", + "@envoy_mobile//test/common/http/filters/route_cache_reset:config", + "@envoy_mobile//test/common/http/filters/test_accessor:config", + "@envoy_mobile//test/common/http/filters/test_event_tracker:config", + "@envoy_mobile//test/common/http/filters/test_kv_store:config", + "@envoy_mobile//test/common/http/filters/test_logger:config", + "@envoy_mobile//test/common/http/filters/test_read:config", + "@envoy_mobile//test/common/http/filters/test_remote_response:config", ], alwayslink = 1, ) diff --git a/mobile/envoy_build_config/test_extensions.cc b/mobile/envoy_build_config/test_extensions.cc index d0bb9c56087b..b18f120c95fc 100644 --- a/mobile/envoy_build_config/test_extensions.cc +++ b/mobile/envoy_build_config/test_extensions.cc @@ -1,14 +1,16 @@ #include "source/extensions/clusters/static/static_cluster.h" #include "source/extensions/filters/http/buffer/config.h" +#include "test/common/http/filters/assertion/config.h" +#include "test/common/http/filters/route_cache_reset/config.h" +#include "test/common/http/filters/test_accessor/config.h" +#include "test/common/http/filters/test_event_tracker/config.h" +#include "test/common/http/filters/test_kv_store/config.h" +#include "test/common/http/filters/test_logger/config.h" +#include "test/common/http/filters/test_read/config.h" +#include "test/common/http/filters/test_remote_response/config.h" + #include "external/envoy_build_config/test_extensions.h" -#include "library/common/extensions/filters/http/assertion/config.h" -#include "library/common/extensions/filters/http/route_cache_reset/config.h" -#include "library/common/extensions/filters/http/test_accessor/config.h" -#include "library/common/extensions/filters/http/test_event_tracker/config.h" -#include "library/common/extensions/filters/http/test_kv_store/config.h" -#include "library/common/extensions/filters/http/test_logger/config.h" -#include "library/common/extensions/filters/http/test_read/config.h" void register_test_extensions() { Envoy::Extensions::HttpFilters::Assertion::forceRegisterAssertionFilterFactory(); @@ -18,6 +20,8 @@ void register_test_extensions() { Envoy::Extensions::HttpFilters::TestEventTracker::forceRegisterTestEventTrackerFilterFactory(); Envoy::Extensions::HttpFilters::TestKeyValueStore::forceRegisterTestKeyValueStoreFilterFactory(); Envoy::Extensions::HttpFilters::TestLogger::forceRegisterFactory(); + Envoy::Extensions::HttpFilters::TestRemoteResponse:: + forceRegisterTestRemoteResponseFilterFactory(); Envoy::HttpFilters::TestRead::forceRegisterTestReadFilterFactory(); Envoy::Upstream::forceRegisterStaticClusterFactory(); } diff --git a/mobile/test/common/extensions/filters/http/assertion/BUILD b/mobile/test/common/extensions/filters/http/assertion/BUILD deleted file mode 100644 index 5081eebf6d63..000000000000 --- a/mobile/test/common/extensions/filters/http/assertion/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -load("@envoy//bazel:envoy_build_system.bzl", "envoy_package") -load( - "@envoy//test/extensions:extensions_build_system.bzl", - "envoy_extension_cc_test", -) - -licenses(["notice"]) # Apache 2 - -envoy_package() - -envoy_extension_cc_test( - name = "assertion_filter_test", - srcs = ["assertion_filter_test.cc"], - extension_names = ["envoy.filters.http.assertion"], - repository = "@envoy", - deps = [ - "//library/common/extensions/filters/http/assertion:config", - "//library/common/extensions/filters/http/assertion:filter_cc_proto", - "@envoy//test/mocks/http:http_mocks", - "@envoy//test/mocks/server:factory_context_mocks", - "@envoy//test/test_common:utility_lib", - ], -) diff --git a/mobile/library/common/extensions/filters/http/assertion/BUILD b/mobile/test/common/http/filters/assertion/BUILD similarity index 67% rename from mobile/library/common/extensions/filters/http/assertion/BUILD rename to mobile/test/common/http/filters/assertion/BUILD index 8e858b5b4ccf..30e054af6339 100644 --- a/mobile/library/common/extensions/filters/http/assertion/BUILD +++ b/mobile/test/common/http/filters/assertion/BUILD @@ -1,13 +1,14 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_cc_test", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", @@ -17,7 +18,7 @@ envoy_proto_library( ], ) -envoy_cc_extension( +envoy_cc_library( name = "assertion_filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], @@ -32,7 +33,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], @@ -42,3 +43,16 @@ envoy_cc_extension( "@envoy//source/extensions/filters/http/common:factory_base_lib", ], ) + +envoy_cc_test( + name = "assertion_filter_test", + srcs = ["assertion_filter_test.cc"], + repository = "@envoy", + deps = [ + ":config", + ":filter_cc_proto", + "@envoy//test/mocks/http:http_mocks", + "@envoy//test/mocks/server:factory_context_mocks", + "@envoy//test/test_common:utility_lib", + ], +) diff --git a/mobile/test/common/extensions/filters/http/assertion/assertion_filter_test.cc b/mobile/test/common/http/filters/assertion/assertion_filter_test.cc similarity index 98% rename from mobile/test/common/extensions/filters/http/assertion/assertion_filter_test.cc rename to mobile/test/common/http/filters/assertion/assertion_filter_test.cc index ea1d66dbba06..9623ccc6787e 100644 --- a/mobile/test/common/extensions/filters/http/assertion/assertion_filter_test.cc +++ b/mobile/test/common/http/filters/assertion/assertion_filter_test.cc @@ -1,11 +1,11 @@ +#include "test/common/http/filters/assertion/config.h" +#include "test/common/http/filters/assertion/filter.h" +#include "test/common/http/filters/assertion/filter.pb.h" #include "test/mocks/http/mocks.h" #include "test/mocks/server/factory_context.h" #include "test/test_common/utility.h" #include "gtest/gtest.h" -#include "library/common/extensions/filters/http/assertion/config.h" -#include "library/common/extensions/filters/http/assertion/filter.h" -#include "library/common/extensions/filters/http/assertion/filter.pb.h" using testing::ByMove; using testing::Return; diff --git a/mobile/library/common/extensions/filters/http/assertion/config.cc b/mobile/test/common/http/filters/assertion/config.cc similarity index 86% rename from mobile/library/common/extensions/filters/http/assertion/config.cc rename to mobile/test/common/http/filters/assertion/config.cc index 14e45062cc5c..0637ba36855f 100644 --- a/mobile/library/common/extensions/filters/http/assertion/config.cc +++ b/mobile/test/common/http/filters/assertion/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/assertion/config.h" +#include "test/common/http/filters/assertion/config.h" -#include "library/common/extensions/filters/http/assertion/filter.h" +#include "test/common/http/filters/assertion/filter.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/assertion/config.h b/mobile/test/common/http/filters/assertion/config.h similarity index 85% rename from mobile/library/common/extensions/filters/http/assertion/config.h rename to mobile/test/common/http/filters/assertion/config.h index 4b4e69a786a9..4c3df493b976 100644 --- a/mobile/library/common/extensions/filters/http/assertion/config.h +++ b/mobile/test/common/http/filters/assertion/config.h @@ -4,8 +4,8 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/assertion/filter.pb.h" -#include "library/common/extensions/filters/http/assertion/filter.pb.validate.h" +#include "test/common/http/filters/assertion/filter.pb.h" +#include "test/common/http/filters/assertion/filter.pb.validate.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/assertion/filter.cc b/mobile/test/common/http/filters/assertion/filter.cc similarity index 99% rename from mobile/library/common/extensions/filters/http/assertion/filter.cc rename to mobile/test/common/http/filters/assertion/filter.cc index aac5f232bb92..b01770762a89 100644 --- a/mobile/library/common/extensions/filters/http/assertion/filter.cc +++ b/mobile/test/common/http/filters/assertion/filter.cc @@ -1,4 +1,4 @@ -#include "library/common/extensions/filters/http/assertion/filter.h" +#include "test/common/http/filters/assertion/filter.h" #include "envoy/http/codes.h" #include "envoy/server/filter_config.h" diff --git a/mobile/library/common/extensions/filters/http/assertion/filter.h b/mobile/test/common/http/filters/assertion/filter.h similarity index 96% rename from mobile/library/common/extensions/filters/http/assertion/filter.h rename to mobile/test/common/http/filters/assertion/filter.h index d235eb5ac8f7..19f5c14abb43 100644 --- a/mobile/library/common/extensions/filters/http/assertion/filter.h +++ b/mobile/test/common/http/filters/assertion/filter.h @@ -5,7 +5,7 @@ #include "source/extensions/common/matcher/matcher.h" #include "source/extensions/filters/http/common/pass_through_filter.h" -#include "library/common/extensions/filters/http/assertion/filter.pb.h" +#include "test/common/http/filters/assertion/filter.pb.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/assertion/filter.proto b/mobile/test/common/http/filters/assertion/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/assertion/filter.proto rename to mobile/test/common/http/filters/assertion/filter.proto diff --git a/mobile/library/common/extensions/filters/http/route_cache_reset/BUILD b/mobile/test/common/http/filters/route_cache_reset/BUILD similarity index 86% rename from mobile/library/common/extensions/filters/http/route_cache_reset/BUILD rename to mobile/test/common/http/filters/route_cache_reset/BUILD index 44d4f60f2437..866454f1e06b 100644 --- a/mobile/library/common/extensions/filters/http/route_cache_reset/BUILD +++ b/mobile/test/common/http/filters/route_cache_reset/BUILD @@ -1,20 +1,20 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", srcs = ["filter.proto"], ) -envoy_cc_extension( +envoy_cc_library( name = "route_cache_reset_filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], @@ -28,7 +28,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], diff --git a/mobile/library/common/extensions/filters/http/route_cache_reset/config.cc b/mobile/test/common/http/filters/route_cache_reset/config.cc similarity index 83% rename from mobile/library/common/extensions/filters/http/route_cache_reset/config.cc rename to mobile/test/common/http/filters/route_cache_reset/config.cc index 84b6dfedb065..80455061b043 100644 --- a/mobile/library/common/extensions/filters/http/route_cache_reset/config.cc +++ b/mobile/test/common/http/filters/route_cache_reset/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/route_cache_reset/config.h" +#include "test/common/http/filters/route_cache_reset/config.h" -#include "library/common/extensions/filters/http/route_cache_reset/filter.h" +#include "test/common/http/filters/route_cache_reset/filter.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/route_cache_reset/config.h b/mobile/test/common/http/filters/route_cache_reset/config.h similarity index 84% rename from mobile/library/common/extensions/filters/http/route_cache_reset/config.h rename to mobile/test/common/http/filters/route_cache_reset/config.h index b29a9c4605c3..6a5734258e37 100644 --- a/mobile/library/common/extensions/filters/http/route_cache_reset/config.h +++ b/mobile/test/common/http/filters/route_cache_reset/config.h @@ -2,8 +2,8 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/route_cache_reset/filter.pb.h" -#include "library/common/extensions/filters/http/route_cache_reset/filter.pb.validate.h" +#include "test/common/http/filters/route_cache_reset/filter.pb.h" +#include "test/common/http/filters/route_cache_reset/filter.pb.validate.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/route_cache_reset/filter.cc b/mobile/test/common/http/filters/route_cache_reset/filter.cc similarity index 93% rename from mobile/library/common/extensions/filters/http/route_cache_reset/filter.cc rename to mobile/test/common/http/filters/route_cache_reset/filter.cc index 0ff7e304c95a..25f0cf3a0227 100644 --- a/mobile/library/common/extensions/filters/http/route_cache_reset/filter.cc +++ b/mobile/test/common/http/filters/route_cache_reset/filter.cc @@ -1,4 +1,4 @@ -#include "library/common/extensions/filters/http/route_cache_reset/filter.h" +#include "test/common/http/filters/route_cache_reset/filter.h" #include "envoy/server/filter_config.h" diff --git a/mobile/library/common/extensions/filters/http/route_cache_reset/filter.h b/mobile/test/common/http/filters/route_cache_reset/filter.h similarity index 94% rename from mobile/library/common/extensions/filters/http/route_cache_reset/filter.h rename to mobile/test/common/http/filters/route_cache_reset/filter.h index 52f0d8ed6c3f..e6a744523261 100644 --- a/mobile/library/common/extensions/filters/http/route_cache_reset/filter.h +++ b/mobile/test/common/http/filters/route_cache_reset/filter.h @@ -4,7 +4,7 @@ #include "source/common/common/logger.h" -#include "library/common/extensions/filters/http/route_cache_reset/filter.pb.h" +#include "test/common/http/filters/route_cache_reset/filter.pb.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/route_cache_reset/filter.proto b/mobile/test/common/http/filters/route_cache_reset/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/route_cache_reset/filter.proto rename to mobile/test/common/http/filters/route_cache_reset/filter.proto diff --git a/mobile/library/common/extensions/filters/http/test_accessor/BUILD b/mobile/test/common/http/filters/test_accessor/BUILD similarity index 88% rename from mobile/library/common/extensions/filters/http/test_accessor/BUILD rename to mobile/test/common/http/filters/test_accessor/BUILD index 977df4ab6783..90c55313131d 100644 --- a/mobile/library/common/extensions/filters/http/test_accessor/BUILD +++ b/mobile/test/common/http/filters/test_accessor/BUILD @@ -1,13 +1,13 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", @@ -17,7 +17,7 @@ envoy_proto_library( ], ) -envoy_cc_extension( +envoy_cc_library( name = "test_accessor_filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], @@ -32,7 +32,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], diff --git a/mobile/library/common/extensions/filters/http/test_accessor/config.cc b/mobile/test/common/http/filters/test_accessor/config.cc similarity index 85% rename from mobile/library/common/extensions/filters/http/test_accessor/config.cc rename to mobile/test/common/http/filters/test_accessor/config.cc index 44deda4b9561..9ff030337689 100644 --- a/mobile/library/common/extensions/filters/http/test_accessor/config.cc +++ b/mobile/test/common/http/filters/test_accessor/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/test_accessor/config.h" +#include "test/common/http/filters/test_accessor/config.h" -#include "library/common/extensions/filters/http/test_accessor/filter.h" +#include "test/common/http/filters/test_accessor/filter.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_accessor/config.h b/mobile/test/common/http/filters/test_accessor/config.h similarity index 79% rename from mobile/library/common/extensions/filters/http/test_accessor/config.h rename to mobile/test/common/http/filters/test_accessor/config.h index 44bd26007b76..a1ae5603426c 100644 --- a/mobile/library/common/extensions/filters/http/test_accessor/config.h +++ b/mobile/test/common/http/filters/test_accessor/config.h @@ -4,9 +4,9 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/test_accessor/filter.h" -#include "library/common/extensions/filters/http/test_accessor/filter.pb.h" -#include "library/common/extensions/filters/http/test_accessor/filter.pb.validate.h" +#include "test/common/http/filters/test_accessor/filter.h" +#include "test/common/http/filters/test_accessor/filter.pb.h" +#include "test/common/http/filters/test_accessor/filter.pb.validate.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.cc b/mobile/test/common/http/filters/test_accessor/filter.cc similarity index 93% rename from mobile/library/common/extensions/filters/http/test_accessor/filter.cc rename to mobile/test/common/http/filters/test_accessor/filter.cc index e35f152dd004..274dab56ea23 100644 --- a/mobile/library/common/extensions/filters/http/test_accessor/filter.cc +++ b/mobile/test/common/http/filters/test_accessor/filter.cc @@ -1,4 +1,4 @@ -#include "library/common/extensions/filters/http/test_accessor/filter.h" +#include "test/common/http/filters/test_accessor/filter.h" #include "envoy/server/filter_config.h" diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.h b/mobile/test/common/http/filters/test_accessor/filter.h similarity index 94% rename from mobile/library/common/extensions/filters/http/test_accessor/filter.h rename to mobile/test/common/http/filters/test_accessor/filter.h index d5a7355c19e3..599702db5259 100644 --- a/mobile/library/common/extensions/filters/http/test_accessor/filter.h +++ b/mobile/test/common/http/filters/test_accessor/filter.h @@ -4,9 +4,10 @@ #include "source/extensions/filters/http/common/pass_through_filter.h" +#include "test/common/http/filters/test_accessor/filter.pb.h" + #include "library/common/api/c_types.h" #include "library/common/api/external.h" -#include "library/common/extensions/filters/http/test_accessor/filter.pb.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_accessor/filter.proto b/mobile/test/common/http/filters/test_accessor/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/test_accessor/filter.proto rename to mobile/test/common/http/filters/test_accessor/filter.proto diff --git a/mobile/library/common/extensions/filters/http/test_event_tracker/BUILD b/mobile/test/common/http/filters/test_event_tracker/BUILD similarity index 88% rename from mobile/library/common/extensions/filters/http/test_event_tracker/BUILD rename to mobile/test/common/http/filters/test_event_tracker/BUILD index f015f035bba8..9c1315425c81 100644 --- a/mobile/library/common/extensions/filters/http/test_event_tracker/BUILD +++ b/mobile/test/common/http/filters/test_event_tracker/BUILD @@ -1,13 +1,13 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", @@ -17,7 +17,7 @@ envoy_proto_library( ], ) -envoy_cc_extension( +envoy_cc_library( name = "test_event_tracker_filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], @@ -33,7 +33,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], diff --git a/mobile/library/common/extensions/filters/http/test_event_tracker/config.cc b/mobile/test/common/http/filters/test_event_tracker/config.cc similarity index 85% rename from mobile/library/common/extensions/filters/http/test_event_tracker/config.cc rename to mobile/test/common/http/filters/test_event_tracker/config.cc index 8f68091d65fc..21854dfbff0c 100644 --- a/mobile/library/common/extensions/filters/http/test_event_tracker/config.cc +++ b/mobile/test/common/http/filters/test_event_tracker/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/test_event_tracker/config.h" +#include "test/common/http/filters/test_event_tracker/config.h" -#include "library/common/extensions/filters/http/test_event_tracker/filter.h" +#include "test/common/http/filters/test_event_tracker/filter.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_event_tracker/config.h b/mobile/test/common/http/filters/test_event_tracker/config.h similarity index 79% rename from mobile/library/common/extensions/filters/http/test_event_tracker/config.h rename to mobile/test/common/http/filters/test_event_tracker/config.h index 8d4746728fc3..d246c93ad750 100644 --- a/mobile/library/common/extensions/filters/http/test_event_tracker/config.h +++ b/mobile/test/common/http/filters/test_event_tracker/config.h @@ -4,9 +4,9 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/test_event_tracker/filter.h" -#include "library/common/extensions/filters/http/test_event_tracker/filter.pb.h" -#include "library/common/extensions/filters/http/test_event_tracker/filter.pb.validate.h" +#include "test/common/http/filters/test_event_tracker/filter.h" +#include "test/common/http/filters/test_event_tracker/filter.pb.h" +#include "test/common/http/filters/test_event_tracker/filter.pb.validate.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_event_tracker/filter.cc b/mobile/test/common/http/filters/test_event_tracker/filter.cc similarity index 93% rename from mobile/library/common/extensions/filters/http/test_event_tracker/filter.cc rename to mobile/test/common/http/filters/test_event_tracker/filter.cc index 24a76a53dd0d..5f5d1733c7dc 100644 --- a/mobile/library/common/extensions/filters/http/test_event_tracker/filter.cc +++ b/mobile/test/common/http/filters/test_event_tracker/filter.cc @@ -1,4 +1,4 @@ -#include "library/common/extensions/filters/http/test_event_tracker/filter.h" +#include "test/common/http/filters/test_event_tracker/filter.h" #include "library/common/api/external.h" #include "library/common/bridge/utility.h" diff --git a/mobile/library/common/extensions/filters/http/test_event_tracker/filter.h b/mobile/test/common/http/filters/test_event_tracker/filter.h similarity index 95% rename from mobile/library/common/extensions/filters/http/test_event_tracker/filter.h rename to mobile/test/common/http/filters/test_event_tracker/filter.h index 93bb5850104d..ffc5e18086d2 100644 --- a/mobile/library/common/extensions/filters/http/test_event_tracker/filter.h +++ b/mobile/test/common/http/filters/test_event_tracker/filter.h @@ -4,8 +4,9 @@ #include "source/extensions/filters/http/common/pass_through_filter.h" +#include "test/common/http/filters/test_event_tracker/filter.pb.h" + #include "library/common/api/c_types.h" -#include "library/common/extensions/filters/http/test_event_tracker/filter.pb.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_event_tracker/filter.proto b/mobile/test/common/http/filters/test_event_tracker/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/test_event_tracker/filter.proto rename to mobile/test/common/http/filters/test_event_tracker/filter.proto diff --git a/mobile/library/common/extensions/filters/http/test_kv_store/BUILD b/mobile/test/common/http/filters/test_kv_store/BUILD similarity index 89% rename from mobile/library/common/extensions/filters/http/test_kv_store/BUILD rename to mobile/test/common/http/filters/test_kv_store/BUILD index 418364d8c9ac..076bbb8fa330 100644 --- a/mobile/library/common/extensions/filters/http/test_kv_store/BUILD +++ b/mobile/test/common/http/filters/test_kv_store/BUILD @@ -1,13 +1,13 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", @@ -17,7 +17,7 @@ envoy_proto_library( ], ) -envoy_cc_extension( +envoy_cc_library( name = "test_kv_store_filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], @@ -33,7 +33,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], diff --git a/mobile/library/common/extensions/filters/http/test_kv_store/config.cc b/mobile/test/common/http/filters/test_kv_store/config.cc similarity index 86% rename from mobile/library/common/extensions/filters/http/test_kv_store/config.cc rename to mobile/test/common/http/filters/test_kv_store/config.cc index 54bfd918d6d3..8135dac6c91f 100644 --- a/mobile/library/common/extensions/filters/http/test_kv_store/config.cc +++ b/mobile/test/common/http/filters/test_kv_store/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/test_kv_store/config.h" +#include "test/common/http/filters/test_kv_store/config.h" -#include "library/common/extensions/filters/http/test_kv_store/filter.h" +#include "test/common/http/filters/test_kv_store/filter.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_kv_store/config.h b/mobile/test/common/http/filters/test_kv_store/config.h similarity index 80% rename from mobile/library/common/extensions/filters/http/test_kv_store/config.h rename to mobile/test/common/http/filters/test_kv_store/config.h index 67b84091ba6c..07b1c59e827b 100644 --- a/mobile/library/common/extensions/filters/http/test_kv_store/config.h +++ b/mobile/test/common/http/filters/test_kv_store/config.h @@ -4,9 +4,9 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/test_kv_store/filter.h" -#include "library/common/extensions/filters/http/test_kv_store/filter.pb.h" -#include "library/common/extensions/filters/http/test_kv_store/filter.pb.validate.h" +#include "test/common/http/filters/test_kv_store/filter.h" +#include "test/common/http/filters/test_kv_store/filter.pb.h" +#include "test/common/http/filters/test_kv_store/filter.pb.validate.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_kv_store/filter.cc b/mobile/test/common/http/filters/test_kv_store/filter.cc similarity index 95% rename from mobile/library/common/extensions/filters/http/test_kv_store/filter.cc rename to mobile/test/common/http/filters/test_kv_store/filter.cc index d20a0ecf805f..07e0d5905ac3 100644 --- a/mobile/library/common/extensions/filters/http/test_kv_store/filter.cc +++ b/mobile/test/common/http/filters/test_kv_store/filter.cc @@ -1,4 +1,4 @@ -#include "library/common/extensions/filters/http/test_kv_store/filter.h" +#include "test/common/http/filters/test_kv_store/filter.h" #include "envoy/server/filter_config.h" diff --git a/mobile/library/common/extensions/filters/http/test_kv_store/filter.h b/mobile/test/common/http/filters/test_kv_store/filter.h similarity index 96% rename from mobile/library/common/extensions/filters/http/test_kv_store/filter.h rename to mobile/test/common/http/filters/test_kv_store/filter.h index 6dfc29bd6ea7..912f0f961c86 100644 --- a/mobile/library/common/extensions/filters/http/test_kv_store/filter.h +++ b/mobile/test/common/http/filters/test_kv_store/filter.h @@ -4,9 +4,10 @@ #include "source/extensions/filters/http/common/pass_through_filter.h" +#include "test/common/http/filters/test_kv_store/filter.pb.h" + #include "library/common/api/c_types.h" #include "library/common/api/external.h" -#include "library/common/extensions/filters/http/test_kv_store/filter.pb.h" #include "library/common/extensions/key_value/platform/c_types.h" namespace Envoy { diff --git a/mobile/library/common/extensions/filters/http/test_kv_store/filter.proto b/mobile/test/common/http/filters/test_kv_store/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/test_kv_store/filter.proto rename to mobile/test/common/http/filters/test_kv_store/filter.proto diff --git a/mobile/library/common/extensions/filters/http/test_logger/BUILD b/mobile/test/common/http/filters/test_logger/BUILD similarity index 86% rename from mobile/library/common/extensions/filters/http/test_logger/BUILD rename to mobile/test/common/http/filters/test_logger/BUILD index 2a31e88bba96..93203f0d3a31 100644 --- a/mobile/library/common/extensions/filters/http/test_logger/BUILD +++ b/mobile/test/common/http/filters/test_logger/BUILD @@ -1,13 +1,13 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", @@ -17,7 +17,7 @@ envoy_proto_library( ], ) -envoy_cc_extension( +envoy_cc_library( name = "test_event_tracker_filter_lib", hdrs = ["filter.h"], repository = "@envoy", @@ -28,7 +28,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], diff --git a/mobile/library/common/extensions/filters/http/test_logger/config.cc b/mobile/test/common/http/filters/test_logger/config.cc similarity index 83% rename from mobile/library/common/extensions/filters/http/test_logger/config.cc rename to mobile/test/common/http/filters/test_logger/config.cc index 4e8c0086c110..e3f94b59eb71 100644 --- a/mobile/library/common/extensions/filters/http/test_logger/config.cc +++ b/mobile/test/common/http/filters/test_logger/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/test_logger/config.h" +#include "test/common/http/filters/test_logger/config.h" -#include "library/common/extensions/filters/http/test_logger/filter.h" +#include "test/common/http/filters/test_logger/filter.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_logger/config.h b/mobile/test/common/http/filters/test_logger/config.h similarity index 78% rename from mobile/library/common/extensions/filters/http/test_logger/config.h rename to mobile/test/common/http/filters/test_logger/config.h index b77bccb7eb06..91fcb8decdb7 100644 --- a/mobile/library/common/extensions/filters/http/test_logger/config.h +++ b/mobile/test/common/http/filters/test_logger/config.h @@ -4,9 +4,9 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/test_logger/filter.h" -#include "library/common/extensions/filters/http/test_logger/filter.pb.h" -#include "library/common/extensions/filters/http/test_logger/filter.pb.validate.h" +#include "test/common/http/filters/test_logger/filter.h" +#include "test/common/http/filters/test_logger/filter.pb.h" +#include "test/common/http/filters/test_logger/filter.pb.validate.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_logger/filter.h b/mobile/test/common/http/filters/test_logger/filter.h similarity index 88% rename from mobile/library/common/extensions/filters/http/test_logger/filter.h rename to mobile/test/common/http/filters/test_logger/filter.h index 28f1ece15281..3777407a0b76 100644 --- a/mobile/library/common/extensions/filters/http/test_logger/filter.h +++ b/mobile/test/common/http/filters/test_logger/filter.h @@ -4,7 +4,7 @@ #include "source/extensions/filters/http/common/pass_through_filter.h" -#include "library/common/extensions/filters/http/test_logger/filter.pb.h" +#include "test/common/http/filters/test_logger/filter.pb.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_logger/filter.proto b/mobile/test/common/http/filters/test_logger/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/test_logger/filter.proto rename to mobile/test/common/http/filters/test_logger/filter.proto diff --git a/mobile/library/common/extensions/filters/http/test_read/BUILD b/mobile/test/common/http/filters/test_read/BUILD similarity index 87% rename from mobile/library/common/extensions/filters/http/test_read/BUILD rename to mobile/test/common/http/filters/test_read/BUILD index 54324cca68ac..96743b875e87 100644 --- a/mobile/library/common/extensions/filters/http/test_read/BUILD +++ b/mobile/test/common/http/filters/test_read/BUILD @@ -1,13 +1,13 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", @@ -17,7 +17,7 @@ envoy_proto_library( ], ) -envoy_cc_extension( +envoy_cc_library( name = "test_read_filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], @@ -30,7 +30,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], diff --git a/mobile/library/common/extensions/filters/http/test_read/config.cc b/mobile/test/common/http/filters/test_read/config.cc similarity index 83% rename from mobile/library/common/extensions/filters/http/test_read/config.cc rename to mobile/test/common/http/filters/test_read/config.cc index 3c5ce3c402f8..ce75a5f1a60c 100644 --- a/mobile/library/common/extensions/filters/http/test_read/config.cc +++ b/mobile/test/common/http/filters/test_read/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/test_read/config.h" +#include "test/common/http/filters/test_read/config.h" -#include "library/common/extensions/filters/http/test_read/filter.h" +#include "test/common/http/filters/test_read/filter.h" namespace Envoy { namespace HttpFilters { diff --git a/mobile/library/common/extensions/filters/http/test_read/config.h b/mobile/test/common/http/filters/test_read/config.h similarity index 85% rename from mobile/library/common/extensions/filters/http/test_read/config.h rename to mobile/test/common/http/filters/test_read/config.h index 24e22d706cb1..291c63211ee7 100644 --- a/mobile/library/common/extensions/filters/http/test_read/config.h +++ b/mobile/test/common/http/filters/test_read/config.h @@ -4,8 +4,8 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/test_read/filter.pb.h" -#include "library/common/extensions/filters/http/test_read/filter.pb.validate.h" +#include "test/common/http/filters/test_read/filter.pb.h" +#include "test/common/http/filters/test_read/filter.pb.validate.h" namespace Envoy { namespace HttpFilters { diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.cc b/mobile/test/common/http/filters/test_read/filter.cc similarity index 96% rename from mobile/library/common/extensions/filters/http/test_read/filter.cc rename to mobile/test/common/http/filters/test_read/filter.cc index fb7c42752727..50b20cdf3a06 100644 --- a/mobile/library/common/extensions/filters/http/test_read/filter.cc +++ b/mobile/test/common/http/filters/test_read/filter.cc @@ -1,4 +1,4 @@ -#include "library/common/extensions/filters/http/test_read/filter.h" +#include "test/common/http/filters/test_read/filter.h" #include "envoy/server/filter_config.h" diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.h b/mobile/test/common/http/filters/test_read/filter.h similarity index 93% rename from mobile/library/common/extensions/filters/http/test_read/filter.h rename to mobile/test/common/http/filters/test_read/filter.h index dc5c2e73cea2..c59fdc4203ec 100644 --- a/mobile/library/common/extensions/filters/http/test_read/filter.h +++ b/mobile/test/common/http/filters/test_read/filter.h @@ -7,7 +7,7 @@ #include "source/common/stream_info/stream_info_impl.h" #include "source/extensions/filters/http/common/pass_through_filter.h" -#include "library/common/extensions/filters/http/test_read/filter.pb.h" +#include "test/common/http/filters/test_read/filter.pb.h" namespace Envoy { namespace HttpFilters { diff --git a/mobile/library/common/extensions/filters/http/test_read/filter.proto b/mobile/test/common/http/filters/test_read/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/test_read/filter.proto rename to mobile/test/common/http/filters/test_read/filter.proto diff --git a/mobile/library/common/extensions/filters/http/test_remote_response/BUILD b/mobile/test/common/http/filters/test_remote_response/BUILD similarity index 90% rename from mobile/library/common/extensions/filters/http/test_remote_response/BUILD rename to mobile/test/common/http/filters/test_remote_response/BUILD index 64ac60a4b6be..94c9f6df790b 100644 --- a/mobile/library/common/extensions/filters/http/test_remote_response/BUILD +++ b/mobile/test/common/http/filters/test_remote_response/BUILD @@ -1,20 +1,20 @@ load( "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_extension", - "envoy_extension_package", + "envoy_cc_library", + "envoy_package", "envoy_proto_library", ) licenses(["notice"]) # Apache 2 -envoy_extension_package() +envoy_package() envoy_proto_library( name = "filter", srcs = ["filter.proto"], ) -envoy_cc_extension( +envoy_cc_library( name = "test_remote_response_filter_lib", srcs = ["filter.cc"], hdrs = ["filter.h"], @@ -36,7 +36,7 @@ envoy_cc_extension( ], ) -envoy_cc_extension( +envoy_cc_library( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], diff --git a/mobile/library/common/extensions/filters/http/test_remote_response/config.cc b/mobile/test/common/http/filters/test_remote_response/config.cc similarity index 83% rename from mobile/library/common/extensions/filters/http/test_remote_response/config.cc rename to mobile/test/common/http/filters/test_remote_response/config.cc index abdcd38f18ef..384611e10fce 100644 --- a/mobile/library/common/extensions/filters/http/test_remote_response/config.cc +++ b/mobile/test/common/http/filters/test_remote_response/config.cc @@ -1,6 +1,6 @@ -#include "library/common/extensions/filters/http/test_remote_response/config.h" +#include "test/common/http/filters/test_remote_response/config.h" -#include "library/common/extensions/filters/http/test_remote_response/filter.h" +#include "test/common/http/filters/test_remote_response/filter.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_remote_response/config.h b/mobile/test/common/http/filters/test_remote_response/config.h similarity index 84% rename from mobile/library/common/extensions/filters/http/test_remote_response/config.h rename to mobile/test/common/http/filters/test_remote_response/config.h index 11a8c60ad84a..09642e21a59d 100644 --- a/mobile/library/common/extensions/filters/http/test_remote_response/config.h +++ b/mobile/test/common/http/filters/test_remote_response/config.h @@ -2,8 +2,8 @@ #include "source/extensions/filters/http/common/factory_base.h" -#include "library/common/extensions/filters/http/test_remote_response/filter.pb.h" -#include "library/common/extensions/filters/http/test_remote_response/filter.pb.validate.h" +#include "test/common/http/filters/test_remote_response/filter.pb.h" +#include "test/common/http/filters/test_remote_response/filter.pb.validate.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_remote_response/filter.cc b/mobile/test/common/http/filters/test_remote_response/filter.cc similarity index 96% rename from mobile/library/common/extensions/filters/http/test_remote_response/filter.cc rename to mobile/test/common/http/filters/test_remote_response/filter.cc index c350853ac497..7b1eb4235797 100644 --- a/mobile/library/common/extensions/filters/http/test_remote_response/filter.cc +++ b/mobile/test/common/http/filters/test_remote_response/filter.cc @@ -1,4 +1,4 @@ -#include "library/common/extensions/filters/http/test_remote_response/filter.h" +#include "test/common/http/filters/test_remote_response/filter.h" #include "envoy/http/header_map.h" #include "envoy/server/filter_config.h" diff --git a/mobile/library/common/extensions/filters/http/test_remote_response/filter.h b/mobile/test/common/http/filters/test_remote_response/filter.h similarity index 92% rename from mobile/library/common/extensions/filters/http/test_remote_response/filter.h rename to mobile/test/common/http/filters/test_remote_response/filter.h index 8e982982dd10..1ac0bf1a1ca3 100644 --- a/mobile/library/common/extensions/filters/http/test_remote_response/filter.h +++ b/mobile/test/common/http/filters/test_remote_response/filter.h @@ -5,7 +5,7 @@ #include "source/common/common/logger.h" #include "source/extensions/filters/http/common/pass_through_filter.h" -#include "library/common/extensions/filters/http/test_remote_response/filter.pb.h" +#include "test/common/http/filters/test_remote_response/filter.pb.h" namespace Envoy { namespace Extensions { diff --git a/mobile/library/common/extensions/filters/http/test_remote_response/filter.proto b/mobile/test/common/http/filters/test_remote_response/filter.proto similarity index 100% rename from mobile/library/common/extensions/filters/http/test_remote_response/filter.proto rename to mobile/test/common/http/filters/test_remote_response/filter.proto diff --git a/tools/code_format/check_format.py b/tools/code_format/check_format.py index 8484e89752ac..18297edba85e 100755 --- a/tools/code_format/check_format.py +++ b/tools/code_format/check_format.py @@ -551,7 +551,7 @@ def check_source_line(self, line, file_path, report_error): report_error( "Don't use ambiguous duration(value), use an explicit duration type, e.g. Event::TimeSystem::Milliseconds(value)" ) - if not self.allow_listed_for_register_factory(file_path): + if file_path.startswith("mobile") and not self.allow_listed_for_register_factory(file_path): if "Registry::RegisterFactory<" in line or "REGISTER_FACTORY" in line: report_error( "Don't use Registry::RegisterFactory or REGISTER_FACTORY in tests, " From 420b1e911bef4ea2355a6c0c43830d7caf5b3ec4 Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Tue, 30 May 2023 13:43:02 -0400 Subject: [PATCH 131/228] tests: Eliminate retry backoffs in the SDS integration tests (#27679) When the xDS cluster is specified after the cluster that depends on it (e.g. for SDS) in the Bootstrap config, the cluster isn't available when making the xDS request, causing a backoff retry after [0,1s). This adds an delays to the tests. This commit fixes the issue by specifying the xDS cluster first in order, before the static cluster that depends on it, in the Bootstrap config. There are about 120 tests in this file, so we save on average about 60 seconds of test runtime everytime the tests in this file are executed. Signed-off-by: Ali Beyad --- .../sds_dynamic_integration_test.cc | 198 +++++++++++------- 1 file changed, 120 insertions(+), 78 deletions(-) diff --git a/test/integration/sds_dynamic_integration_test.cc b/test/integration/sds_dynamic_integration_test.cc index 8b080d7c0064..92929dbf74bf 100644 --- a/test/integration/sds_dynamic_integration_test.cc +++ b/test/integration/sds_dynamic_integration_test.cc @@ -111,6 +111,9 @@ class SdsDynamicIntegrationBaseTest : public Grpc::BaseGrpcClientIntegrationPara Network::Address::IpVersion ipVersion() const override { return GetParam().ip_version; } Grpc::ClientType clientType() const override { return GetParam().sds_grpc_type; } + virtual std::unique_ptr& sdsUpstream() { return fake_upstreams_[0]; } + // Index in fake_upstreams_ vector of the data plane upstream. + int dataPlaneUpstreamIndex() { return 1; } protected: void createSdsStream(FakeUpstream&) { @@ -130,7 +133,7 @@ class SdsDynamicIntegrationBaseTest : public Grpc::BaseGrpcClientIntegrationPara api_config_source->set_api_type(envoy::config::core::v3::ApiConfigSource::GRPC); api_config_source->set_transport_api_version(envoy::config::core::v3::V3); auto* grpc_service = api_config_source->add_grpc_services(); - setGrpcService(*grpc_service, "sds_cluster.lyft.com", fake_upstreams_.back()->localAddress()); + setGrpcService(*grpc_service, "sds_cluster.lyft.com", sdsUpstream()->localAddress()); } envoy::extensions::transport_sockets::tls::v3::Secret getServerSecretRsa() { @@ -230,10 +233,14 @@ class SdsDynamicDownstreamIntegrationTest : public SdsDynamicIntegrationBaseTest }); config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - // Add a static sds cluster - auto* sds_cluster = bootstrap.mutable_static_resources()->add_clusters(); - sds_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); + // Add a static SDS cluster as the first cluster in the list. + // The SDS cluster needs to appear before the cluster that uses it for secrets, so that it + // gets initialized first. + bootstrap.mutable_static_resources()->add_clusters()->MergeFrom( + bootstrap.static_resources().clusters(0)); + auto* sds_cluster = bootstrap.mutable_static_resources()->mutable_clusters(0); sds_cluster->set_name("sds_cluster.lyft.com"); + sds_cluster->mutable_load_assignment()->set_cluster_name("sds_cluster.lyft.com"); ConfigHelper::setHttp2(*sds_cluster); }); @@ -321,8 +328,10 @@ version_info: "0" } void createUpstreams() override { - create_xds_upstream_ = true; - HttpIntegrationTest::createUpstreams(); + // SDS cluster is H2, while the data cluster is H1. + addFakeUpstream(Http::CodecType::HTTP2); + addFakeUpstream(Http::CodecType::HTTP1); + xds_upstream_ = fake_upstreams_.front().get(); } void waitForSdsUpdateStats(size_t times) { @@ -386,7 +395,7 @@ TEST_P(SdsDynamicKeyRotationIntegrationTest, BasicRotation) { {TestEnvironment::runfilesPath("test/integration/sds_dynamic_key_rotation_setup.sh")}); on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getCurrentServerSecret()); }; initialize(); @@ -398,7 +407,7 @@ TEST_P(SdsDynamicKeyRotationIntegrationTest, BasicRotation) { return makeSslClientConnection(); }; // First request with server{cert,key}.pem. - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); cleanupUpstreamAndDownstream(); // Rotate. TestEnvironment::renameFile(TestEnvironment::temporaryPath("root/new"), @@ -409,7 +418,7 @@ TEST_P(SdsDynamicKeyRotationIntegrationTest, BasicRotation) { EXPECT_EQ(0, test_server_->counter("sds.server_cert_rsa.update_rejected")->value()); // First request with server_ecdsa{cert,key}.pem. - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); } // Validate that rotating to a directory with missing certs is handled. @@ -419,7 +428,7 @@ TEST_P(SdsDynamicKeyRotationIntegrationTest, EmptyRotation) { {TestEnvironment::runfilesPath("test/integration/sds_dynamic_key_rotation_setup.sh")}); on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getCurrentServerSecret()); }; initialize(); @@ -431,7 +440,7 @@ TEST_P(SdsDynamicKeyRotationIntegrationTest, EmptyRotation) { return makeSslClientConnection(); }; // First request with server{cert,key}.pem. - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); cleanupUpstreamAndDownstream(); // Rotate to an empty directory, this should fail. @@ -444,14 +453,14 @@ TEST_P(SdsDynamicKeyRotationIntegrationTest, EmptyRotation) { EXPECT_EQ(0, test_server_->counter("sds.server_cert_rsa.update_rejected")->value()); // Requests continue to work with key/cert pair. - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); } // A test that SDS server send a good server secret for a static listener. // The first ssl request should be OK. TEST_P(SdsDynamicDownstreamIntegrationTest, BasicSuccess) { on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getServerSecretRsa()); }; initialize(); @@ -459,7 +468,7 @@ TEST_P(SdsDynamicDownstreamIntegrationTest, BasicSuccess) { ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.server_cert_rsa.update_success")->value()); @@ -468,7 +477,7 @@ TEST_P(SdsDynamicDownstreamIntegrationTest, BasicSuccess) { TEST_P(SdsDynamicDownstreamIntegrationTest, DualCert) { on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getServerSecretRsa()); }; @@ -484,7 +493,7 @@ TEST_P(SdsDynamicDownstreamIntegrationTest, DualCert) { .setTlsVersion(envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2) .setCipherSuites({"ECDHE-ECDSA-AES128-GCM-SHA256"}), context_manager_, *api_); - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); cleanupUpstreamAndDownstream(); client_ssl_ctx_ = createClientSslTransportSocketFactory( @@ -492,7 +501,7 @@ TEST_P(SdsDynamicDownstreamIntegrationTest, DualCert) { .setTlsVersion(envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2) .setCipherSuites({"ECDHE-RSA-AES128-GCM-SHA256"}), context_manager_, *api_); - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.server_cert_rsa.update_success")->value()); @@ -520,7 +529,7 @@ TEST_P(SdsDynamicDownstreamIntegrationTest, DualCert) { // via sds and give a simple case of selecting cert based on SNI. TEST_P(SdsDynamicDownstreamIntegrationTest, MultipleCerts) { on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getServerSecretRsa()); }; @@ -576,7 +585,7 @@ TEST_P(SdsDynamicDownstreamIntegrationTest, MultipleCerts) { // then SDS send a good server secret, the second request should be OK. TEST_P(SdsDynamicDownstreamIntegrationTest, WrongSecretFirst) { on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getWrongSecret(server_cert_rsa_)); }; initialize(); @@ -598,7 +607,7 @@ TEST_P(SdsDynamicDownstreamIntegrationTest, WrongSecretFirst) { ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.server_cert_rsa.update_success")->value()); @@ -621,10 +630,14 @@ class SdsDynamicDownstreamCertValidationContextTest : public SdsDynamicDownstrea configureInlinedCerts(&common_tls_context); }); - // Add a static sds cluster - auto* sds_cluster = bootstrap.mutable_static_resources()->add_clusters(); - sds_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); + // Add a static SDS cluster as the first cluster in the list. + // The SDS cluster needs to appear before the cluster that uses it for secrets, so that it + // gets initialized first. + bootstrap.mutable_static_resources()->add_clusters()->MergeFrom( + bootstrap.static_resources().clusters(0)); + auto* sds_cluster = bootstrap.mutable_static_resources()->mutable_clusters(0); sds_cluster->set_name("sds_cluster.lyft.com"); + sds_cluster->mutable_load_assignment()->set_cluster_name("sds_cluster.lyft.com"); ConfigHelper::setHttp2(*sds_cluster); envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext upstream_tls_context; @@ -641,8 +654,9 @@ class SdsDynamicDownstreamCertValidationContextTest : public SdsDynamicDownstrea TestEnvironment::runfilesPath("test/config/integration/certs/clientcert.pem")); upstream_tls_certificate->mutable_private_key()->set_filename( TestEnvironment::runfilesPath("test/config/integration/certs/clientkey.pem")); - auto* upstream_transport_socket = - bootstrap.mutable_static_resources()->mutable_clusters(0)->mutable_transport_socket(); + auto* upstream_transport_socket = bootstrap.mutable_static_resources() + ->mutable_clusters(dataPlaneUpstreamIndex()) + ->mutable_transport_socket(); upstream_transport_socket->set_name("envoy.transport_sockets.tls"); upstream_transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); }); @@ -681,9 +695,11 @@ class SdsDynamicDownstreamCertValidationContextTest : public SdsDynamicDownstrea } void createUpstreams() override { - // Fake upstream with SSL/TLS for the first cluster. + // SDS cluster for the first cluster. + addFakeUpstream(Http::CodecType::HTTP2); + // Fake upstream with SSL/TLS for the second cluster. addFakeUpstream(createUpstreamSslContext(), upstreamProtocol(), /*autonomous_upstream=*/false); - create_xds_upstream_ = true; + xds_upstream_ = fake_upstreams_.front().get(); } Network::DownstreamTransportSocketFactoryPtr createUpstreamSslContext() { @@ -726,7 +742,7 @@ INSTANTIATE_TEST_SUITE_P(IpVersionsClientType, SdsDynamicDownstreamCertValidatio // The first ssl request should be OK. TEST_P(SdsDynamicDownstreamCertValidationContextTest, BasicSuccess) { on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getCvcSecret()); }; initialize(); @@ -734,7 +750,7 @@ TEST_P(SdsDynamicDownstreamCertValidationContextTest, BasicSuccess) { ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.validation_secret.update_success")->value()); @@ -747,7 +763,7 @@ TEST_P(SdsDynamicDownstreamCertValidationContextTest, BasicSuccess) { TEST_P(SdsDynamicDownstreamCertValidationContextTest, CombinedCertValidationContextSuccess) { enableCombinedValidationContext(true); on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getCvcSecretWithOnlyTrustedCa()); }; initialize(); @@ -755,7 +771,7 @@ TEST_P(SdsDynamicDownstreamCertValidationContextTest, CombinedCertValidationCont ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.validation_secret.update_success")->value()); @@ -767,7 +783,7 @@ TEST_P(SdsDynamicDownstreamCertValidationContextTest, CombinedCertValidationCont TEST_P(SdsDynamicDownstreamCertValidationContextTest, BasicWithSharedSecret) { shareValidationSecret(true); on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getCvcSecret()); }; initialize(); @@ -781,7 +797,7 @@ TEST_P(SdsDynamicDownstreamCertValidationContextTest, BasicWithSharedSecret) { ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.validation_secret.update_success")->value()); @@ -794,7 +810,7 @@ TEST_P(SdsDynamicDownstreamCertValidationContextTest, CombinedValidationContextW enableCombinedValidationContext(true); shareValidationSecret(true); on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getCvcSecretWithOnlyTrustedCa()); }; initialize(); @@ -808,7 +824,7 @@ TEST_P(SdsDynamicDownstreamCertValidationContextTest, CombinedValidationContextW ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.validation_secret.update_success")->value()); @@ -826,20 +842,25 @@ class SdsDynamicUpstreamIntegrationTest : public SdsDynamicIntegrationBaseTest { setUpstreamProtocol(Http::CodecType::HTTP3); } config_helper_.addConfigModifier([this](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - // add sds cluster first. - auto* sds_cluster = bootstrap.mutable_static_resources()->add_clusters(); - sds_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); + // Add a static SDS cluster as the first cluster in the list. + // The SDS cluster needs to appear before the cluster that uses it for secrets, so that it + // gets initialized first. + bootstrap.mutable_static_resources()->add_clusters()->MergeFrom( + bootstrap.static_resources().clusters(0)); + auto* sds_cluster = bootstrap.mutable_static_resources()->mutable_clusters(0); sds_cluster->set_name("sds_cluster.lyft.com"); + sds_cluster->mutable_load_assignment()->set_cluster_name("sds_cluster.lyft.com"); ConfigHelper::setHttp2(*sds_cluster); - // Unwind Quic for sds cluster. + // Unwind Quic for SDS cluster. if (test_quic_) { sds_cluster->clear_transport_socket(); } // change the first cluster with ssl and sds. - auto* transport_socket = - bootstrap.mutable_static_resources()->mutable_clusters(0)->mutable_transport_socket(); + auto* transport_socket = bootstrap.mutable_static_resources() + ->mutable_clusters(dataPlaneUpstreamIndex()) + ->mutable_transport_socket(); envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext tls_context; tls_context.set_sni("lyft.com"); auto* secret_config = @@ -872,10 +893,12 @@ class SdsDynamicUpstreamIntegrationTest : public SdsDynamicIntegrationBaseTest { } void createUpstreams() override { - // This is for backend with ssl + // SDS cluster for the first cluster. + addFakeUpstream(Http::CodecType::HTTP2); + // FakeUpstream with SSL/TLS for the second cluster. addFakeUpstream(createUpstreamSslContext(context_manager_, *api_, test_quic_), upstreamProtocol(), /*autonomous_upstream=*/false); - create_xds_upstream_ = true; + xds_upstream_ = fake_upstreams_.front().get(); } }; @@ -886,7 +909,7 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, SdsDynamicUpstreamIntegrationTest, // The first request should work. TEST_P(SdsDynamicUpstreamIntegrationTest, BasicSuccess) { on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getClientSecret()); }; @@ -902,19 +925,19 @@ TEST_P(SdsDynamicUpstreamIntegrationTest, BasicSuccess) { test_server_->waitForCounterGe( "cluster.cluster_0.client_ssl_socket_factory.ssl_context_update_by_sds", 1); - testRouterHeaderOnlyRequestAndResponse(); + testRouterHeaderOnlyRequestAndResponse(/*create_connection=*/nullptr, dataPlaneUpstreamIndex()); // Success EXPECT_EQ(1, test_server_->counter("sds.client_cert.update_success")->value()); EXPECT_EQ(0, test_server_->counter("sds.client_cert.update_rejected")->value()); } -// To test a static cluster with sds. SDS send a bad client secret first. -// The first request should fail with 503, then SDS sends a good client secret, -// the second request should work. +// Tests a static cluster with SDS. +// SDS sends a bad client secret first, so the request fails with a 503. +// Then, SDS sends a good client secret, so the second request is successful. TEST_P(SdsDynamicUpstreamIntegrationTest, WrongSecretFirst) { on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getWrongSecret(client_cert_)); }; initialize(); @@ -928,7 +951,8 @@ TEST_P(SdsDynamicUpstreamIntegrationTest, WrongSecretFirst) { // Wait for the raw TCP connection with bad credentials and close it. if (upstreamProtocol() != Http::CodecType::HTTP3) { FakeRawConnectionPtr fake_upstream_connection; - ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection)); + ASSERT_TRUE( + fake_upstreams_[dataPlaneUpstreamIndex()]->waitForRawConnection(fake_upstream_connection)); ASSERT_TRUE(fake_upstream_connection->waitForDisconnect()); } @@ -943,7 +967,7 @@ TEST_P(SdsDynamicUpstreamIntegrationTest, WrongSecretFirst) { EXPECT_EQ(1, test_server_->counter("sds.client_cert.update_rejected")->value()); // Verify the update succeeded. - testRouterHeaderOnlyRequestAndResponse(); + testRouterHeaderOnlyRequestAndResponse(/*create_connection=*/nullptr, dataPlaneUpstreamIndex()); } // Test CDS with SDS. A cluster provided by CDS raises new SDS request for upstream cert. @@ -952,8 +976,34 @@ class SdsCdsIntegrationTest : public SdsDynamicIntegrationBaseTest { public: void initialize() override { config_helper_.addConfigModifier([this](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - // Create the dynamic cluster. This cluster will be using sds. - dynamic_cluster_ = bootstrap.mutable_static_resources()->clusters(0); + // The 1st cluster, which already exists in the Bootstrap config, will be the CDS cluster. + // The 2nd cluster, which will be added, will be the SDS cluster. + // The 3rd cluster, which will be added after that, will be the dynamic cluster, which will + // use SDS. + // The xDS clusters need to appear before the cluster that uses it, so that they get + // initialized first. + + // The SDS cluster. + auto* sds_cluster = bootstrap.mutable_static_resources()->add_clusters(); + sds_cluster->MergeFrom(bootstrap.static_resources().clusters(0)); + // The static cluster. + auto* static_cluster = bootstrap.mutable_static_resources()->add_clusters(); + static_cluster->MergeFrom(bootstrap.static_resources().clusters(0)); + // Make a copy of the static cluster to create and set up the dynamic cluster. + dynamic_cluster_ = *static_cluster; + + // Set up the first cluster, the CDS cluster. + auto* cds_cluster = bootstrap.mutable_static_resources()->mutable_clusters(0); + cds_cluster->set_name("cds_cluster"); + cds_cluster->mutable_load_assignment()->set_cluster_name("cds_cluster"); + ConfigHelper::setHttp2(*cds_cluster); + + // Set up the second cluster, the SDS cluster. + sds_cluster->set_name("sds_cluster.lyft.com"); + sds_cluster->mutable_load_assignment()->set_cluster_name("sds_cluster.lyft.com"); + ConfigHelper::setHttp2(*sds_cluster); + + // Set up the dynamic cluster to use SDS. dynamic_cluster_.set_name("dynamic"); dynamic_cluster_.mutable_connect_timeout()->MergeFrom( ProtobufUtil::TimeUtil::MillisecondsToDuration(500000)); @@ -966,17 +1016,7 @@ class SdsCdsIntegrationTest : public SdsDynamicIntegrationBaseTest { transport_socket->set_name("envoy.transport_sockets.tls"); transport_socket->mutable_typed_config()->PackFrom(tls_context); - // Add cds cluster first. - auto* cds_cluster = bootstrap.mutable_static_resources()->add_clusters(); - cds_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); - cds_cluster->set_name("cds_cluster"); - ConfigHelper::setHttp2(*cds_cluster); - // Then add sds cluster. - auto* sds_cluster = bootstrap.mutable_static_resources()->add_clusters(); - sds_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); - sds_cluster->set_name("sds_cluster.lyft.com"); - ConfigHelper::setHttp2(*sds_cluster); - + // Set up the Bootstrap's CDS config to fetch from the CDS cluster. const std::string cds_yaml = R"EOF( resource_api_version: V3 api_config_source: @@ -1010,14 +1050,18 @@ class SdsCdsIntegrationTest : public SdsDynamicIntegrationBaseTest { } void createUpstreams() override { - // Static cluster. - addFakeUpstream(Http::CodecType::HTTP1); - // Cds Cluster. + // CDS Cluster. addFakeUpstream(Http::CodecType::HTTP2); - // Sds Cluster. + // SDS Cluster. addFakeUpstream(Http::CodecType::HTTP2); + // Static cluster. + addFakeUpstream(Http::CodecType::HTTP1); + xds_upstream_ = fake_upstreams_.front().get(); } + std::unique_ptr& cdsUpstream() { return fake_upstreams_[0]; } + std::unique_ptr& sdsUpstream() override { return fake_upstreams_[1]; } + void sendCdsResponse() { EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().Cluster, "", {}, {}, {}, true)); sendDiscoveryResponse( @@ -1032,6 +1076,7 @@ class SdsCdsIntegrationTest : public SdsDynamicIntegrationBaseTest { discovery_response.add_resources()->PackFrom(secret); sds_stream.sendGrpcMessage(discovery_response); } + envoy::config::cluster::v3::Cluster dynamic_cluster_; FakeHttpConnectionPtr sds_connection_; FakeStreamPtr sds_stream_; @@ -1044,8 +1089,7 @@ TEST_P(SdsCdsIntegrationTest, BasicSuccess) { on_server_init_function_ = [this]() { { // CDS. - AssertionResult result = - fake_upstreams_[1]->waitForHttpConnection(*dispatcher_, xds_connection_); + AssertionResult result = cdsUpstream()->waitForHttpConnection(*dispatcher_, xds_connection_); RELEASE_ASSERT(result, result.message()); result = xds_connection_->waitForNewStream(*dispatcher_, xds_stream_); RELEASE_ASSERT(result, result.message()); @@ -1054,8 +1098,7 @@ TEST_P(SdsCdsIntegrationTest, BasicSuccess) { } { // SDS. - AssertionResult result = - fake_upstreams_[2]->waitForHttpConnection(*dispatcher_, sds_connection_); + AssertionResult result = sdsUpstream()->waitForHttpConnection(*dispatcher_, sds_connection_); RELEASE_ASSERT(result, result.message()); result = sds_connection_->waitForNewStream(*dispatcher_, sds_stream_); @@ -1122,7 +1165,7 @@ TEST_P(SdsDynamicDownstreamPrivateKeyIntegrationTest, BasicPrivateKeyProvider) { test_private_key_method_factory(test_factory); on_server_init_function_ = [this]() { - createSdsStream(*(fake_upstreams_[1])); + createSdsStream(*sdsUpstream()); sendSdsResponse(getCurrentServerPrivateKeyProviderSecret()); }; initialize(); @@ -1133,7 +1176,7 @@ TEST_P(SdsDynamicDownstreamPrivateKeyIntegrationTest, BasicPrivateKeyProvider) { ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { return makeSslClientConnection(); }; - testRouterHeaderOnlyRequestAndResponse(&creator); + testRouterHeaderOnlyRequestAndResponse(&creator, dataPlaneUpstreamIndex()); cleanupUpstreamAndDownstream(); } @@ -1184,8 +1227,7 @@ TEST_P(SdsCdsPrivateKeyIntegrationTest, BasicSdsCdsPrivateKeyProvider) { on_server_init_function_ = [this]() { { // CDS. - AssertionResult result = - fake_upstreams_[1]->waitForHttpConnection(*dispatcher_, xds_connection_); + AssertionResult result = cdsUpstream()->waitForHttpConnection(*dispatcher_, xds_connection_); EXPECT_TRUE(result); result = xds_connection_->waitForNewStream(*dispatcher_, xds_stream_); EXPECT_TRUE(result); @@ -1194,8 +1236,7 @@ TEST_P(SdsCdsPrivateKeyIntegrationTest, BasicSdsCdsPrivateKeyProvider) { } { // SDS. - AssertionResult result = - fake_upstreams_[2]->waitForHttpConnection(*dispatcher_, sds_connection_); + AssertionResult result = sdsUpstream()->waitForHttpConnection(*dispatcher_, sds_connection_); EXPECT_TRUE(result); result = sds_connection_->waitForNewStream(*dispatcher_, sds_stream_); @@ -1216,5 +1257,6 @@ TEST_P(SdsCdsPrivateKeyIntegrationTest, BasicSdsCdsPrivateKeyProvider) { // Successfully removed the dynamic cluster. test_server_->waitForGaugeEq("cluster_manager.active_clusters", 3); } + } // namespace Ssl } // namespace Envoy From b5acd8404aab2e495b7a6dcff9e7e0f0e7a0b440 Mon Sep 17 00:00:00 2001 From: danzh Date: Tue, 30 May 2023 13:58:59 -0400 Subject: [PATCH 132/228] dfp: request failed when cached in dns cache (#27641) In light of #27407, the DNS matched matches against host:port. But an entry is found in DNS cache, DFP filter call getHost() again on the cache with raw host. That call failed the lookup and causes dns_resolution_failure. Additional Description: remove mobile/test/kotlin/integration/MixedSchemeTest.kt which doesn't work under CI; And make Hello Envoy app on android runs with Android certification validation APIs. Risk Level: low Testing: add new test Docs Changes: N/A Release Notes: N/A Platform Specific Features: N/A Further Fixes #27331 Signed-off-by: Dan Zhang Co-authored-by: Alyssa Wilk --- .../java/hello_world/MainActivity.java | 22 ++-- .../kotlin/integration/MixedSchemeTest.kt | 101 ------------------ .../dynamic_forward_proxy/proxy_filter.cc | 6 +- .../proxy_filter_integration_test.cc | 30 +++++- .../proxy_filter_test.cc | 21 ---- 5 files changed, 47 insertions(+), 133 deletions(-) delete mode 100644 mobile/test/kotlin/integration/MixedSchemeTest.kt diff --git a/mobile/examples/java/hello_world/MainActivity.java b/mobile/examples/java/hello_world/MainActivity.java index 7f5d81f207d8..920508a04de9 100644 --- a/mobile/examples/java/hello_world/MainActivity.java +++ b/mobile/examples/java/hello_world/MainActivity.java @@ -35,7 +35,8 @@ public class MainActivity extends Activity { private static final String ENVOY_SERVER_HEADER = "server"; private static final String REQUEST_AUTHORITY = "api.lyft.com"; private static final String REQUEST_PATH = "/ping"; - private static final String REQUEST_SCHEME = "http"; + private static final String REQUEST_SCHEME_HTTP = "http"; + private static final String REQUEST_SCHEME_HTTPS = "https"; private static final Set FILTERED_HEADERS = new HashSet() { { add("server"); @@ -49,6 +50,7 @@ public class MainActivity extends Activity { private HandlerThread thread = new HandlerThread(REQUEST_HANDLER_THREAD_NAME); private ResponseRecyclerViewAdapter viewAdapter; + private Boolean clear_text = true; @Override protected void onCreate(Bundle savedInstanceState) { @@ -61,6 +63,7 @@ protected void onCreate(Bundle savedInstanceState) { Log.d("MainActivity", "Envoy async internal setup completed"); return null; }) + .enablePlatformCertificatesValidation(true) .build(); recyclerView = (RecyclerView)findViewById(R.id.recycler_view); @@ -95,14 +98,15 @@ private void makeRequest() { // Note: this request will use an http/1.1 stream for the upstream request. // The Kotlin example uses h2. This is done on purpose to test both paths in // end-to-end tests in CI. - RequestHeaders requestHeaders = new RequestHeadersBuilder(RequestMethod.GET, REQUEST_SCHEME, - REQUEST_AUTHORITY, REQUEST_PATH) - .build(); + String scheme = clear_text ? REQUEST_SCHEME_HTTP : REQUEST_SCHEME_HTTPS; + RequestHeaders requestHeaders = + new RequestHeadersBuilder(RequestMethod.GET, scheme, REQUEST_AUTHORITY, REQUEST_PATH) + .build(); engine.streamClient() .newStreamPrototype() .setOnResponseHeaders((responseHeaders, endStream, ignored) -> { Integer status = responseHeaders.getHttpStatus(); - String message = "received headers with status " + status; + String message = "received headers with status " + status + " for " + scheme + " request"; StringBuilder sb = new StringBuilder(); for (Map.Entry> entry : @@ -115,7 +119,9 @@ private void makeRequest() { String headerText = sb.toString(); Log.d("MainActivity", message); - if (status == 301) { + if ((scheme == REQUEST_SCHEME_HTTP && status == 301) || + (scheme == REQUEST_SCHEME_HTTPS && status == 200)) { + // The server returns 301 to http request and 200 to https request. String serverHeaderField = responseHeaders.value(ENVOY_SERVER_HEADER).get(0); recyclerView.post(() -> viewAdapter.add(new Success(message, headerText))); } else { @@ -125,13 +131,15 @@ private void makeRequest() { }) .setOnError((error, ignored) -> { String message = "failed with error after " + error.getAttemptCount() + - " attempts: " + error.getMessage(); + " attempts: " + error.getMessage() + " for " + scheme + " request"; Log.d("MainActivity", message); recyclerView.post(() -> viewAdapter.add(new Failure(message))); return Unit.INSTANCE; }) .start(Executors.newSingleThreadExecutor()) .sendHeaders(requestHeaders, true); + + clear_text = !clear_text; } private void recordStats() { diff --git a/mobile/test/kotlin/integration/MixedSchemeTest.kt b/mobile/test/kotlin/integration/MixedSchemeTest.kt deleted file mode 100644 index ec054681e1c4..000000000000 --- a/mobile/test/kotlin/integration/MixedSchemeTest.kt +++ /dev/null @@ -1,101 +0,0 @@ -package test.kotlin.integration - -import io.envoyproxy.envoymobile.LogLevel -import io.envoyproxy.envoymobile.Standard -import io.envoyproxy.envoymobile.EngineBuilder -import io.envoyproxy.envoymobile.RequestHeadersBuilder -import io.envoyproxy.envoymobile.RequestMethod -import io.envoyproxy.envoymobile.engine.JniLibrary -import java.nio.ByteBuffer -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.fail -import org.junit.Test - -private const val testResponseFilterType = "type.googleapis.com/envoymobile.extensions.filters.http.test_remote_response.TestRemoteResponse" - -class ReceiveDataTest { - - init { - JniLibrary.loadTestLibrary() - } - - @Test - fun `response headers and response data call onResponseHeaders and onResponseData`() { - - val engine = EngineBuilder(Standard()) - .addLogLevel(LogLevel.TRACE) - .build() - val client = engine.streamClient() - - // httpi - val headersExpectation2 = CountDownLatch(1) - val dataExpectation2 = CountDownLatch(1) - - var status2: Int? = null - - val requestHeaders2 = RequestHeadersBuilder( - method = RequestMethod.GET, - scheme = "http", - authority = "example.com", - path = "/" - ) - .build() - - client.newStreamPrototype() - .setOnResponseHeaders { responseHeaders, _, _ -> - status2 = responseHeaders.httpStatus - headersExpectation2.countDown() - } - .setOnResponseData { data, _, _ -> - dataExpectation2.countDown() - } - .setOnError { _, _ -> - fail("Unexpected error") - } - .start() - .sendHeaders(requestHeaders2, true) - - headersExpectation2.await(10, TimeUnit.SECONDS) - dataExpectation2.await(10, TimeUnit.SECONDS) - - assertThat(headersExpectation2.count).isEqualTo(0) - assertThat(dataExpectation2.count).isEqualTo(0) - - // https - val requestHeaders = RequestHeadersBuilder( - method = RequestMethod.GET, - scheme = "https", - authority = "example.com", - path = "/" - ) - .build() - - val headersExpectation = CountDownLatch(1) - val dataExpectation = CountDownLatch(1) - - var status: Int? = null - client.newStreamPrototype() - .setOnResponseHeaders { responseHeaders, _, _ -> - status = responseHeaders.httpStatus - headersExpectation.countDown() - } - .setOnResponseData { data, _, _ -> - dataExpectation.countDown() - } - .setOnError { _, _ -> fail("Unexpected error") } - .start() - .sendHeaders(requestHeaders, true) - - headersExpectation.await(10, TimeUnit.SECONDS) - dataExpectation.await(10, TimeUnit.SECONDS) - engine.terminate() - - assertThat(headersExpectation.count).isEqualTo(0) - assertThat(dataExpectation.count).isEqualTo(0) - - assertThat(status).isEqualTo(200) - assertThat(status2).isEqualTo(200) - } -} diff --git a/source/extensions/filters/http/dynamic_forward_proxy/proxy_filter.cc b/source/extensions/filters/http/dynamic_forward_proxy/proxy_filter.cc index 7b851c589df2..3ab49ca0bf26 100644 --- a/source/extensions/filters/http/dynamic_forward_proxy/proxy_filter.cc +++ b/source/extensions/filters/http/dynamic_forward_proxy/proxy_filter.cc @@ -84,7 +84,7 @@ LoadClusterEntryHandlePtr ProxyFilterConfig::addDynamicCluster( std::string version_info = ""; ENVOY_LOG(debug, "deliver dynamic cluster {} creation to main thread", cluster_name); main_thread_dispatcher_.post([this, cluster, version_info]() { - ENVOY_LOG(debug, "initilizing dynamic cluster {} creation in main thread", cluster.name()); + ENVOY_LOG(debug, "initializing dynamic cluster {} creation in main thread", cluster.name()); cluster_manager_.addOrUpdateCluster(cluster, version_info); }); } else { @@ -223,7 +223,7 @@ Http::FilterHeadersStatus ProxyFilter::decodeHeaders(Http::RequestHeaderMap& hea // using it, which is not a good usage, will end with ServiceUnavailable. // Thread local cluster is existing due to the thread local cache, and the main thread notify // work thread is on the way. - ENVOY_STREAM_LOG(debug, "dynamic foward cluster is gone", *this->decoder_callbacks_); + ENVOY_STREAM_LOG(debug, "dynamic forward cluster is gone", *this->decoder_callbacks_); this->decoder_callbacks_->sendLocalReply(Http::Code::ServiceUnavailable, ResponseStrings::get().DFPClusterIsGone, nullptr, absl::nullopt, RcDetails::get().DFPClusterIsGone); @@ -263,7 +263,7 @@ Http::FilterHeadersStatus ProxyFilter::decodeHeaders(Http::RequestHeaderMap& hea ASSERT(cache_load_handle_ == nullptr); ENVOY_STREAM_LOG(debug, "DNS cache entry already loaded, continuing", *decoder_callbacks_); - auto const& host = config_->cache().getHost(headers.Host()->value().getStringView()); + auto const& host = result.host_info_; latchTime(decoder_callbacks_, DNS_END); if (!host.has_value() || !host.value()->address()) { onDnsResolutionFail(); diff --git a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc index 8a4885eedf14..093e2ef2b782 100644 --- a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc +++ b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc @@ -258,7 +258,7 @@ name: envoy.clusters.dynamic_forward_proxy }; int64_t getHeaderValue(const Http::ResponseHeaderMap& headers, absl::string_view name) { - EXPECT_FALSE(headers.get(Http::LowerCaseString(name)).empty()) << "Mising " << name; + EXPECT_FALSE(headers.get(Http::LowerCaseString(name)).empty()) << "Missing " << name; int64_t val; if (!headers.get(Http::LowerCaseString(name)).empty() && absl::SimpleAtoi(headers.get(Http::LowerCaseString(name))[0]->value().getStringView(), @@ -488,6 +488,34 @@ TEST_P(ProxyFilterIntegrationTest, UpstreamCleartext) { checkSimpleRequestSuccess(0, 0, response.get()); } +// Regression test a bug where the host header was used for cache lookups rather than host:port key +TEST_P(ProxyFilterIntegrationTest, CacheSansPort) { + useAccessLog("%RESPONSE_CODE_DETAILS%"); + initializeWithArgs(); + codec_client_ = makeHttpConnection(lookupPort("http")); + const Http::TestRequestHeaderMapImpl request_headers{{":method", "POST"}, + {":path", "/test/long/url"}, + {":scheme", "http"}, + {":authority", "localhost"}}; + + // Send a request to localhost, with no port specified. The cluster will + // default to localhost:443, and the connection will fail. + auto response = codec_client_->makeHeaderOnlyRequest(request_headers); + ASSERT_TRUE(response->waitForEndStream()); + EXPECT_EQ("503", response->headers().getStatusValue()); + EXPECT_THAT(waitForAccessLog(access_log_name_), + HasSubstr("upstream_reset_before_response_started")); + EXPECT_EQ(1, test_server_->counter("dns_cache.foo.host_added")->value()); + + // Now try a second request and make sure it encounters the same error rather + // than dns_resolution_failure. + auto response2 = codec_client_->makeHeaderOnlyRequest(request_headers); + ASSERT_TRUE(response2->waitForEndStream()); + EXPECT_EQ("503", response2->headers().getStatusValue()); + EXPECT_THAT(waitForAccessLog(access_log_name_, 1), + HasSubstr("upstream_reset_before_response_started")); +} + // Verify that `override_auto_sni_header` can be used along with auto_sni to set // SNI from an arbitrary header. TEST_P(ProxyFilterIntegrationTest, UpstreamTlsWithAltHeaderSni) { diff --git a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_test.cc b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_test.cc index d4db4d0a1c08..fe546b87e102 100644 --- a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_test.cc +++ b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_test.cc @@ -560,13 +560,6 @@ TEST_F(UpstreamResolvedHostFilterStateHelper, AddResolvedHostFilterStateMetadata return MockLoadDnsCacheEntryResult{LoadDnsCacheEntryStatus::InCache, nullptr, host_info}; })); - EXPECT_CALL(*dns_cache_manager_->dns_cache_, getHost(_)) - .WillOnce( - Invoke([&](absl::string_view) - -> absl::optional { - return host_info; - })); - EXPECT_CALL(*host_info, address()).Times(2).WillRepeatedly(Return(host_info->address_)); // Host was resolved successfully, so continue filter iteration. @@ -618,13 +611,6 @@ TEST_F(UpstreamResolvedHostFilterStateHelper, UpdateResolvedHostFilterStateMetad return MockLoadDnsCacheEntryResult{LoadDnsCacheEntryStatus::InCache, nullptr, host_info}; })); - EXPECT_CALL(*dns_cache_manager_->dns_cache_, getHost(_)) - .WillOnce( - Invoke([&](absl::string_view) - -> absl::optional { - return host_info; - })); - EXPECT_CALL(*host_info, address()).Times(2).WillRepeatedly(Return(host_info->address_)); // Host was resolved successfully, so continue filter iteration. @@ -673,13 +659,6 @@ TEST_F(UpstreamResolvedHostFilterStateHelper, IgnoreFilterStateMetadataNullAddre return MockLoadDnsCacheEntryResult{LoadDnsCacheEntryStatus::InCache, nullptr, host_info}; })); - EXPECT_CALL(*dns_cache_manager_->dns_cache_, getHost(_)) - .WillOnce( - Invoke([&](absl::string_view) - -> absl::optional { - return host_info; - })); - EXPECT_CALL(*host_info, address()); EXPECT_CALL(callbacks_, sendLocalReply(Http::Code::ServiceUnavailable, Eq("DNS resolution failure"), _, _, From 047a8ff65774ed3239a0d14f2dc73a5793a43e8b Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 30 May 2023 15:19:46 -0400 Subject: [PATCH 133/228] test: making E-M e2e test work sans yaml (#27634) Signed-off-by: Alyssa Wilk --- .../workflows/mobile-compile_time_options.yml | 37 ++++++----- test/common/upstream/utility.h | 29 +++++--- test/config/utility.cc | 66 ++++++++++++++++++- .../health_checkers/redis/redis_test.cc | 4 +- test/integration/BUILD | 18 ++--- test/integration/base_integration_test.cc | 62 ++++++++++------- test/integration/ssl_utility.cc | 53 +++++---------- 7 files changed, 172 insertions(+), 97 deletions(-) diff --git a/.github/workflows/mobile-compile_time_options.yml b/.github/workflows/mobile-compile_time_options.yml index fc8ff2073781..5d2ee4083d5c 100644 --- a/.github/workflows/mobile-compile_time_options.yml +++ b/.github/workflows/mobile-compile_time_options.yml @@ -31,9 +31,9 @@ jobs: - name: 'Build C++ library' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Envoy Mobile build verifies that the build configuration where HTTP/3 is enabled and - # HTTP Datagrams are disabled works. run: | + # Envoy Mobile build which verifies that the build configuration where HTTP/3 is enabled and + # HTTP Datagrams are disabled works. cd mobile && ./bazelw test \ $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-linux") \ --define=signal_trace=disabled \ @@ -43,7 +43,22 @@ jobs: --define=google_grpc=disabled \ --@envoy//bazel:http3=False \ --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ - //test/cc/... + //test/cc/... \ + # Envoy Mobile build which verifies that the build configuration where YAML is disabled. + && ./bazelw test \ + $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ + --config=ci \ + --fat_apk_cpu=x86_64 \ + --define=signal_trace=disabled \ + --define=envoy_mobile_request_compression=disabled \ + --define=envoy_enable_http_datagrams=disabled \ + --define=google_grpc=disabled \ + --define=envoy_yaml=disabled \ + --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ + //test/java/integration:android_engine_socket_tag_test \ + //test/java/integration:android_engine_start_test \ + //test/java/io/envoyproxy/envoymobile/utilities:certificate_verification_tests + //test/common/integration:client_integration_test swift_build: if: ${{ needs.env.outputs.mobile_compile_time_options == 'true' }} needs: env @@ -103,18 +118,4 @@ jobs: --define=google_grpc=disabled \ --define=envoy_yaml=disabled \ --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ - //:android_dist \ - && ./bazelw test \ - $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ - --config=ci \ - --fat_apk_cpu=x86_64 \ - --define=signal_trace=disabled \ - --define=admin_html=enabled \ - --define=envoy_mobile_request_compression=disabled \ - --define=envoy_enable_http_datagrams=disabled \ - --define=google_grpc=disabled \ - --define=envoy_yaml=disabled \ - --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ - //test/java/integration:android_engine_socket_tag_test \ - //test/java/integration:android_engine_start_test \ - //test/java/io/envoyproxy/envoymobile/utilities:certificate_verification_tests + //:android_dist diff --git a/test/common/upstream/utility.h b/test/common/upstream/utility.h index 503b794b570a..0458f90a15db 100644 --- a/test/common/upstream/utility.h +++ b/test/common/upstream/utility.h @@ -57,24 +57,41 @@ inline std::string defaultStaticClusterJson(const std::string& name) { inline envoy::config::bootstrap::v3::Bootstrap parseBootstrapFromV3Json(const std::string& json_string) { envoy::config::bootstrap::v3::Bootstrap bootstrap; + // TODO(alyssawilk) rename to JSON +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromJson(json_string, bootstrap); +#else + PANIC("JSON compiled out: cannot parse " + json_string); +#endif return bootstrap; } inline envoy::config::cluster::v3::Cluster parseClusterFromV3Json(const std::string& json_string) { envoy::config::cluster::v3::Cluster cluster; +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromJson(json_string, cluster); +#else + PANIC("JSON compiled out: cannot parse " + json_string); +#endif return cluster; } inline envoy::config::cluster::v3::Cluster parseClusterFromV3Yaml(const std::string& yaml) { envoy::config::cluster::v3::Cluster cluster; +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(yaml, cluster); +#else + PANIC("JSON compiled out: cannot parse " + yaml); +#endif return cluster; } inline envoy::config::cluster::v3::Cluster defaultStaticCluster(const std::string& name) { +#ifdef ENVOY_ENABLE_YAML return parseClusterFromV3Json(defaultStaticClusterJson(name)); +#else + PANIC("JSON compiled out: cannot parse " + name); +#endif } inline HostSharedPtr makeTestHost(ClusterInfoConstSharedPtr cluster, const std::string& hostname, @@ -167,15 +184,11 @@ makeLocalityWeights(std::initializer_list locality_weights) { inline envoy::config::core::v3::HealthCheck parseHealthCheckFromV3Yaml(const std::string& yaml_string) { envoy::config::core::v3::HealthCheck health_check; +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYamlAndValidate(yaml_string, health_check); - return health_check; -} - -// For DEPRECATED TEST CASES -inline envoy::config::core::v3::HealthCheck -parseHealthCheckFromV2Yaml(const std::string& yaml_string) { - envoy::config::core::v3::HealthCheck health_check; - TestUtility::loadFromYamlAndValidate(yaml_string, health_check); +#else + PANIC("JSON compiled out: cannot parse " + yaml_string); +#endif return health_check; } diff --git a/test/config/utility.cc b/test/config/utility.cc index ca33b39059f4..b9b15c102ad3 100644 --- a/test/config/utility.cc +++ b/test/config/utility.cc @@ -33,7 +33,13 @@ namespace Envoy { namespace { envoy::config::bootstrap::v3::Bootstrap& basicBootstrap(envoy::config::bootstrap::v3::Bootstrap& bootstrap, const std::string& config) { +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(config, bootstrap); +#else + UNREFERENCED_PARAMETER(config); + UNREFERENCED_PARAMETER(bootstrap); + PANIC("JSON compiled out: can't load config"); +#endif return bootstrap; } } // namespace @@ -513,7 +519,6 @@ ConfigHelper::buildStaticCluster(const std::string& name, int port, const std::s (*cluster.mutable_typed_extension_protocol_options()) ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] .PackFrom(protocol_options); - return cluster; } @@ -576,7 +581,6 @@ ConfigHelper::buildTlsCluster(const std::string& name, TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcacert.pem")); socket->set_name("envoy.transport_sockets.tls"); socket->mutable_typed_config()->PackFrom(tls_socket); - return cluster; } @@ -623,6 +627,7 @@ envoy::config::listener::v3::Listener ConfigHelper::buildBaseListener(const std::string& name, const std::string& address, const std::string& filter_chains) { API_NO_BOOST(envoy::config::listener::v3::Listener) listener; +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(fmt::format( R"EOF( name: {} @@ -636,6 +641,12 @@ ConfigHelper::buildBaseListener(const std::string& name, const std::string& addr name, address, filter_chains), listener); return listener; +#else + UNREFERENCED_PARAMETER(name); + UNREFERENCED_PARAMETER(address); + UNREFERENCED_PARAMETER(filter_chains); + PANIC("YAML support compiled out"); +#endif } envoy::config::listener::v3::Listener ConfigHelper::buildListener(const std::string& name, @@ -667,6 +678,7 @@ envoy::config::listener::v3::Listener ConfigHelper::buildListener(const std::str envoy::config::route::v3::RouteConfiguration ConfigHelper::buildRouteConfig(const std::string& name, const std::string& cluster) { API_NO_BOOST(envoy::config::route::v3::RouteConfiguration) route; +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(fmt::format(R"EOF( name: "{}" virtual_hosts: @@ -679,6 +691,11 @@ ConfigHelper::buildRouteConfig(const std::string& name, const std::string& clust name, cluster), route); return route; +#else + UNREFERENCED_PARAMETER(name); + UNREFERENCED_PARAMETER(cluster); + PANIC("YAML support compiled out"); +#endif } envoy::config::endpoint::v3::Endpoint ConfigHelper::buildEndpoint(const std::string& address) { @@ -770,6 +787,7 @@ void ConfigHelper::addListenerTypedMetadata(absl::string_view key, ProtobufWkt:: void ConfigHelper::addClusterFilterMetadata(absl::string_view metadata_yaml, absl::string_view cluster_name) { +#ifdef ENVOY_ENABLE_YAML RELEASE_ASSERT(!finalized_, ""); ProtobufWkt::Struct cluster_metadata; TestUtility::loadFromYaml(std::string(metadata_yaml), cluster_metadata); @@ -787,6 +805,11 @@ void ConfigHelper::addClusterFilterMetadata(absl::string_view metadata_yaml, } break; } +#else + UNREFERENCED_PARAMETER(metadata_yaml); + UNREFERENCED_PARAMETER(cluster_name); + PANIC("YAML support compiled out"); +#endif } void ConfigHelper::setConnectConfig( @@ -1163,7 +1186,13 @@ void ConfigHelper::prependFilter(const std::string& config, bool downstream) { loadHttpConnectionManager(hcm_config); auto* filter_list_back = hcm_config.add_http_filters(); +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(config, *filter_list_back); +#else + UNREFERENCED_PARAMETER(config); + UNREFERENCED_PARAMETER(filter_list_back); + PANIC("YAML support compiled out"); +#endif // Now move it to the front. for (int i = hcm_config.http_filters_size() - 1; i > 0; --i) { @@ -1188,7 +1217,12 @@ void ConfigHelper::prependFilter(const std::string& config, bool downstream) { old_protocol_options.add_http_filters()->set_name("envoy.filters.http.upstream_codec"); } auto* filter_list_back = old_protocol_options.add_http_filters(); +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(config, *filter_list_back); +#else + UNREFERENCED_PARAMETER(filter_list_back); + PANIC("YAML support compiled out"); +#endif for (int i = old_protocol_options.http_filters_size() - 1; i > 0; --i) { old_protocol_options.mutable_http_filters()->SwapElements(i, i - 1); } @@ -1400,7 +1434,12 @@ void ConfigHelper::initializeTls( filename: "{{ test_rundir }}/test/config/integration/certs/intermediate_partial_ca_cert_chain.pem" )EOF"; } +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(TestEnvironment::substitute(cert_yaml), *validation_context); +#else + UNREFERENCED_PARAMETER(cert_yaml); + PANIC("YAML support compiled out"); +#endif if (options.max_verify_depth_.has_value()) { validation_context->mutable_max_verify_depth()->set_value( options.max_verify_depth_.value()); @@ -1478,7 +1517,13 @@ void ConfigHelper::addNetworkFilter(const std::string& filter_yaml) { auto* filter_chain = bootstrap_.mutable_static_resources()->mutable_listeners(0)->mutable_filter_chains(0); auto* filter_list_back = filter_chain->add_filters(); +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(filter_yaml, *filter_list_back); +#else + UNREFERENCED_PARAMETER(filter_list_back); + UNREFERENCED_PARAMETER(filter_yaml); + PANIC("YAML support compiled out"); +#endif // Now move it to the front. for (int i = filter_chain->filters_size() - 1; i > 0; --i) { @@ -1490,7 +1535,13 @@ void ConfigHelper::addListenerFilter(const std::string& filter_yaml) { RELEASE_ASSERT(!finalized_, ""); auto* listener = bootstrap_.mutable_static_resources()->mutable_listeners(0); auto* filter_list_back = listener->add_listener_filters(); +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(filter_yaml, *filter_list_back); +#else + UNREFERENCED_PARAMETER(filter_list_back); + UNREFERENCED_PARAMETER(filter_yaml); + PANIC("YAML support compiled out"); +#endif // Now move it to the front. for (int i = listener->listener_filters_size() - 1; i > 0; --i) { @@ -1501,7 +1552,13 @@ void ConfigHelper::addListenerFilter(const std::string& filter_yaml) { void ConfigHelper::addBootstrapExtension(const std::string& config) { RELEASE_ASSERT(!finalized_, ""); auto* extension = bootstrap_.add_bootstrap_extensions(); +#ifdef ENVOY_ENABLE_YAML TestUtility::loadFromYaml(config, *extension); +#else + UNREFERENCED_PARAMETER(extension); + UNREFERENCED_PARAMETER(config); + PANIC("YAML support compiled out"); +#endif } bool ConfigHelper::loadHttpConnectionManager( @@ -1548,9 +1605,14 @@ void ConfigHelper::setLds(absl::string_view version_info) { const std::string lds_filename = bootstrap().dynamic_resources().lds_config().path_config_source().path(); +#ifdef ENVOY_ENABLE_YAML std::string file = TestEnvironment::writeStringToFileForTest( "new_lds_file", MessageUtil::getJsonStringFromMessageOrError(lds)); TestEnvironment::renameFile(file, lds_filename); +#else + UNREFERENCED_PARAMETER(lds_filename); + PANIC("YAML support compiled out"); +#endif } void ConfigHelper::setDownstreamOutboundFramesLimits(uint32_t max_all_frames, diff --git a/test/extensions/health_checkers/redis/redis_test.cc b/test/extensions/health_checkers/redis/redis_test.cc index 1bcb4e5ba783..c564838a30bb 100644 --- a/test/extensions/health_checkers/redis/redis_test.cc +++ b/test/extensions/health_checkers/redis/redis_test.cc @@ -79,7 +79,7 @@ class RedisHealthCheckerTest "@type": type.googleapis.com/envoy.extensions.health_checkers.redis.v3.Redis )EOF"; - const auto& health_check_config = Upstream::parseHealthCheckFromV2Yaml(yaml); + const auto& health_check_config = Upstream::parseHealthCheckFromV3Yaml(yaml); const auto& redis_config = getRedisHealthCheckConfig( health_check_config, ProtobufMessage::getStrictValidationVisitor()); @@ -164,7 +164,7 @@ class RedisHealthCheckerTest key: foo )EOF"; - const auto& health_check_config = Upstream::parseHealthCheckFromV2Yaml(yaml); + const auto& health_check_config = Upstream::parseHealthCheckFromV3Yaml(yaml); const auto& redis_config = getRedisHealthCheckConfig( health_check_config, ProtobufMessage::getStrictValidationVisitor()); diff --git a/test/integration/BUILD b/test/integration/BUILD index fbcbfbfaf828..c918f09fadf1 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -1053,7 +1053,6 @@ envoy_cc_test_library( "//source/common/config:api_version_lib", "//source/extensions/clusters/eds:eds_lib", "//source/extensions/clusters/static:static_cluster_lib", - "//source/extensions/config_subscription/filesystem:filesystem_subscription_lib", "//source/extensions/config_subscription/grpc:grpc_collection_subscription_lib", "//source/extensions/config_subscription/grpc:grpc_subscription_lib", "//source/extensions/load_balancing_policies/maglev:config", @@ -1081,7 +1080,9 @@ envoy_cc_test_library( ] + select({ "//bazel:apple": ["//source/extensions/network/dns_resolver/apple:config"], "//conditions:default": [], - }), + }) + envoy_select_enable_yaml([ + "//source/extensions/config_subscription/filesystem:filesystem_subscription_lib", + ]), ) envoy_cc_test_library( @@ -1101,12 +1102,14 @@ envoy_cc_test_library( name = "utility_lib", srcs = [ "server.cc", + "ssl_utility.cc", "utility.cc", - ] + envoy_select_enable_yaml(["ssl_utility.cc"]), + ], hdrs = [ "server.h", + "ssl_utility.h", "utility.h", - ] + envoy_select_enable_yaml(["ssl_utility.h"]), + ], data = ["//test/common/runtime:filesystem_test_data"], deps = [ ":server_stats_interface", @@ -1140,6 +1143,8 @@ envoy_cc_test_library( "//source/server:options_lib", "//source/server:process_context_lib", "//source/server:server_lib", + "//test/common/upstream:utility_lib", + "//test/config:utility_lib", "//test/mocks:common_lib", "//test/mocks/event:event_mocks", "//test/mocks/runtime:runtime_mocks", @@ -1157,10 +1162,7 @@ envoy_cc_test_library( "@envoy_api//envoy/config/listener/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/transport_sockets/quic/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/transport_sockets/tls/v3:pkg_cc_proto", - ] + envoy_select_enable_yaml([ - "//test/common/upstream:utility_lib", - "//test/config:utility_lib", - ]), + ], ) envoy_cc_test_library( diff --git a/test/integration/base_integration_test.cc b/test/integration/base_integration_test.cc index a90bf2210a43..5a2bbfa161fa 100644 --- a/test/integration/base_integration_test.cc +++ b/test/integration/base_integration_test.cc @@ -30,9 +30,14 @@ namespace Envoy { envoy::config::bootstrap::v3::Bootstrap configToBootstrap(const std::string& config) { +#ifdef ENVOY_ENABLE_YAML envoy::config::bootstrap::v3::Bootstrap bootstrap; TestUtility::loadFromYaml(config, bootstrap); return bootstrap; +#else + UNREFERENCED_PARAMETER(config); + PANIC("YAML support compiled out: can't parse YAML"); +#endif } using ::testing::_; @@ -131,19 +136,17 @@ void BaseIntegrationTest::initialize() { Network::DownstreamTransportSocketFactoryPtr BaseIntegrationTest::createUpstreamTlsContext(const FakeUpstreamConfig& upstream_config) { envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext tls_context; - const std::string yaml = absl::StrFormat( - R"EOF( -common_tls_context: - tls_certificates: - - certificate_chain: { filename: "%s" } - private_key: { filename: "%s" } - validation_context: - trusted_ca: { filename: "%s" } -)EOF", - TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcert.pem"), - TestEnvironment::runfilesPath("test/config/integration/certs/upstreamkey.pem"), - TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); - TestUtility::loadFromYaml(yaml, tls_context); + const std::string rundir = TestEnvironment::runfilesDirectory(); + tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_trusted_ca() + ->set_filename(rundir + "/test/config/integration/certs/cacert.pem"); + auto* certs = tls_context.mutable_common_tls_context()->add_tls_certificates(); + certs->mutable_certificate_chain()->set_filename( + rundir + "/test/config/integration/certs/upstreamcert.pem"); + certs->mutable_private_key()->set_filename(rundir + + "/test/config/integration/certs/upstreamkey.pem"); + if (upstream_config.upstream_protocol_ == Http::CodecType::HTTP2) { tls_context.mutable_common_tls_context()->add_alpn_protocols("h2"); } else if (upstream_config.upstream_protocol_ == Http::CodecType::HTTP1) { @@ -221,15 +224,22 @@ std::string BaseIntegrationTest::finalizeConfigWithPorts(ConfigHelper& config_he ProtobufWkt::Any* resource = lds.add_resources(); resource->PackFrom(listener); } +#ifdef ENVOY_ENABLE_YAML TestEnvironment::writeStringToFileForTest( lds_path, MessageUtil::getJsonStringFromMessageOrError(lds), true); - +#else + PANIC("YAML support compiled out: can't parse YAML"); +#endif // Now that the listeners have been written to the lds file, remove them from static resources // or they will not be reloadable. bootstrap.mutable_static_resources()->mutable_listeners()->Clear(); } +#ifdef ENVOY_ENABLE_YAML ENVOY_LOG_MISC(debug, "Running Envoy with configuration:\n{}", MessageUtil::getYamlStringFromMessage(bootstrap)); +#else + ENVOY_LOG_MISC(debug, "Running Envoy with configuration:\n{}", bootstrap.DebugString()); +#endif const std::string bootstrap_path = TestEnvironment::writeStringToFileForTest( "bootstrap.pb", TestUtility::getProtobufBinaryStringFromMessage(bootstrap)); @@ -426,7 +436,11 @@ std::string getListenerDetails(Envoy::Server::Instance& server) { const auto& cbs_maps = server.admin()->getConfigTracker().getCallbacksMap(); ProtobufTypes::MessagePtr details = cbs_maps.at("listeners")(Matchers::UniversalStringMatcher()); auto listener_info = Protobuf::down_cast(*details); +#ifdef ENVOY_ENABLE_YAML return MessageUtil::getYamlStringFromMessage(listener_info.dynamic_listeners(0).error_state()); +#else + return listener_info.dynamic_listeners(0).error_state().DebugString(); +#endif } void BaseIntegrationTest::createGeneratedApiTestServer( @@ -766,16 +780,16 @@ AssertionResult BaseIntegrationTest::compareDeltaDiscoveryRequest( // Attempt to heuristically discover missing tag-extraction rules when new stats are added. // This is done by looking through the entire config for fields named `stat_prefix`, and then // validating that those values do not appear in the tag-extracted name of any stat. The alternate -// approach of looking for the prefix in the extracted tags was more difficult because in the tests -// some prefix values are reused (leading to false negatives) and some tests have base configuration -// that sets a stat_prefix but don't produce any stats at all with that configuration (leading to -// false positives). +// approach of looking for the prefix in the extracted tags was more difficult because in the +// tests some prefix values are reused (leading to false negatives) and some tests have base +// configuration that sets a stat_prefix but don't produce any stats at all with that +// configuration (leading to false positives). // // To add a rule, see `source/common/config/well_known_names.cc`. // -// This is done in all integration tests because it is testing new stats and scopes that are created -// for which the author isn't aware that tag extraction rules need to be written, and thus the -// author wouldn't think to write tests for that themselves. +// This is done in all integration tests because it is testing new stats and scopes that are +// created for which the author isn't aware that tag extraction rules need to be written, and thus +// the author wouldn't think to write tests for that themselves. void BaseIntegrationTest::checkForMissingTagExtractionRules() { BufferingStreamDecoderPtr response = IntegrationUtil::makeSingleRequest( test_server_->adminAddress(), "GET", "/config_dump", "", Http::CodecType::HTTP1); @@ -791,9 +805,9 @@ void BaseIntegrationTest::checkForMissingTagExtractionRules() { std::vector stat_prefixes; Json::ObjectCallback find_stat_prefix = [&](const std::string& name, const Json::Object& root) -> bool { - // Looking for `stat_prefix` is based on precedent for how this is usually named in the config. - // If there are other names used for a similar purpose, this check could be expanded to add them - // also. + // Looking for `stat_prefix` is based on precedent for how this is usually named in the + // config. If there are other names used for a similar purpose, this check could be expanded + // to add them also. if (name == "stat_prefix") { auto prefix = root.asString(); if (!prefix.empty()) { diff --git a/test/integration/ssl_utility.cc b/test/integration/ssl_utility.cc index af93ec2c3a48..6727632d99f1 100644 --- a/test/integration/ssl_utility.cc +++ b/test/integration/ssl_utility.cc @@ -25,47 +25,30 @@ namespace Ssl { void initializeUpstreamTlsContextConfig( const ClientSslTransportOptions& options, envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext& tls_context) { - std::string yaml_plain = R"EOF( - common_tls_context: - validation_context: - trusted_ca: - filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" -)EOF"; + const std::string rundir = TestEnvironment::runfilesDirectory(); + tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_trusted_ca() + ->set_filename(rundir + "/test/config/integration/certs/cacert.pem"); + auto* certs = tls_context.mutable_common_tls_context()->add_tls_certificates(); + std::string chain; + std::string key; if (options.client_ecdsa_cert_) { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/config/integration/certs/client_ecdsacert.pem" - private_key: - filename: "{{ test_rundir }}/test/config/integration/certs/client_ecdsakey.pem" -)EOF"; + chain = rundir + "/test/config/integration/certs/client_ecdsacert.pem"; + key = rundir + "/test/config/integration/certs/client_ecdsakey.pem"; } else if (options.use_expired_spiffe_cert_) { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem" - private_key: - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_key.pem" -)EOF"; + chain = rundir + "/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem"; + key = rundir + "/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_key.pem"; } else if (options.client_with_intermediate_cert_) { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/config/integration/certs/client2_chain.pem" - private_key: - filename: "{{ test_rundir }}/test/config/integration/certs/client2key.pem" -)EOF"; + chain = rundir + "/test/config/integration/certs/client2_chain.pem"; + key = rundir + "/test/config/integration/certs/client2key.pem"; } else { - yaml_plain += R"EOF( - tls_certificates: - certificate_chain: - filename: "{{ test_rundir }}/test/config/integration/certs/clientcert.pem" - private_key: - filename: "{{ test_rundir }}/test/config/integration/certs/clientkey.pem" -)EOF"; + chain = rundir + "/test/config/integration/certs/clientcert.pem"; + key = rundir + "/test/config/integration/certs/clientkey.pem"; } + certs->mutable_certificate_chain()->set_filename(chain); + certs->mutable_private_key()->set_filename(key); - TestUtility::loadFromYaml(TestEnvironment::substitute(yaml_plain), tls_context); auto* common_context = tls_context.mutable_common_tls_context(); if (options.alpn_) { From 5673f1adcdf9b79a23c011d902e2a21c5db45bd1 Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Wed, 31 May 2023 03:36:01 +0800 Subject: [PATCH 134/228] golang filter: always use GC finalizer to delete the req object in C++ (#27630) It could be safer since people may still use the request object in Go even after it told C++ it had already finished processing. Signed-off-by: doujiang24 --- contrib/golang/filters/http/source/go/pkg/http/shim.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/contrib/golang/filters/http/source/go/pkg/http/shim.go b/contrib/golang/filters/http/source/go/pkg/http/shim.go index fc208a77c982..fe0cb3751792 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/shim.go +++ b/contrib/golang/filters/http/source/go/pkg/http/shim.go @@ -215,10 +215,4 @@ func envoyGoFilterOnHttpDestroy(r *C.httpRequest, reason uint64) { f.OnDestroy(v) Requests.DeleteReq(r) - - // no one is using req now, we can remove it manually, for better performance. - if v == api.Normal { - runtime.SetFinalizer(req, nil) - req.Finalize(api.GCFinalize) - } } From 1c85fe6a6d4f94313384b953c7ad610b65aaa1f2 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 31 May 2023 08:11:45 +0100 Subject: [PATCH 135/228] ci/examples: Minor cleanup (#27686) Signed-off-by: Ryan Northey --- ci/do_ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 21fd47eae66d..b0f178293f05 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -163,7 +163,7 @@ function run_ci_verify () { # by a strong umask (ie only group readable by default). umask 027 chmod -R o-rwx examples/ - "${ENVOY_SRCDIR}/ci/verify_examples.sh" "${@}" || exit + "${ENVOY_SRCDIR}/ci/verify_examples.sh" "${@}" } CI_TARGET=$1 From fac75f32d961a9ae7264935ef983e8bfa027cf96 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 31 May 2023 09:26:40 +0100 Subject: [PATCH 136/228] ci: Add github workflow POLICY (#27600) Signed-off-by: Ryan Northey --- .github/workflows/POLICY.md | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 .github/workflows/POLICY.md diff --git a/.github/workflows/POLICY.md b/.github/workflows/POLICY.md new file mode 100644 index 000000000000..86d775493dc9 --- /dev/null +++ b/.github/workflows/POLICY.md @@ -0,0 +1,59 @@ +# Envoy Github workflows + +## Trusted workflows + +Github workflows that are **not** triggered by a `pull_request` generally run with +the repository context/permissions. + +In various ways, these workflows can be triggered as the result of a `pull_request` +and/or be made to run untrusted code (ie PR code). + +This can be useful, but carries significant risks. + +In particular this can effect: + +- `pull_request_target` +- `workflow_run` +- `workflow_dispatch` + +Do not use these trigger events unless they are required. + +## Restrict global permissions and secrets in trusted workflows + +If a job requires specific permissions, these should be added on per-job basis. + +Global permissions should be set as follows: + +```yaml +permissions: + contents: read +``` + +Likewise, any secrets that a job requires should be set per-job. + +## Restrict access to `workflow_dispatch` + +It is important to restrict who can trigger these types of workflow. + +Do not allow any bots or app users to do so, unless this is specifically required. + +For example, you could add a `job` condition to prevent any bots from triggering the workflow: + +```yaml + if: | + ${{ + github.repository == 'envoyproxy/envoy' + && (github.event.schedule + || !contains(github.actor, '[bot]')) + }} +``` + +## Trusted/untrusted CI jobs + +If a trusted workflow is used to run untrusted code, then the entire job that runs this code +should be treated as untrusted. + +In this case, it is **essential** to ensure: + +- no write permissions in the untrusted job +- no secrets in the untrusted job From 13e5514911a6e63220fa991b64ae7691533875ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 09:31:26 +0100 Subject: [PATCH 137/228] build(deps): bump otel/opentelemetry-collector from `5c3a03d` to `32edac6` in /examples/opentelemetry (#27716) build(deps): bump otel/opentelemetry-collector Bumps otel/opentelemetry-collector from `5c3a03d` to `32edac6`. --- updated-dependencies: - dependency-name: otel/opentelemetry-collector dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/opentelemetry/Dockerfile-opentelemetry | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/opentelemetry/Dockerfile-opentelemetry b/examples/opentelemetry/Dockerfile-opentelemetry index 177882fbdf92..ad03819c59e4 100644 --- a/examples/opentelemetry/Dockerfile-opentelemetry +++ b/examples/opentelemetry/Dockerfile-opentelemetry @@ -1,7 +1,7 @@ FROM alpine:3.18@sha256:02bb6f428431fbc2809c5d1b41eab5a68350194fb508869a33cb1af4444c9b11 as otelc_curl RUN apk --update add curl -FROM otel/opentelemetry-collector:latest@sha256:5c3a03dac40b1f37069c63a2ee75d7bd8c7ba81fc42831085053b1c70e528349 +FROM otel/opentelemetry-collector:latest@sha256:32edac6fe9479c4a33a60be226af0a3ee9f69a5b79d935835b37bf9b25e4b5ce COPY --from=otelc_curl / / From de2ef460d88b2f703a5bfcae9e6b35304ec83906 Mon Sep 17 00:00:00 2001 From: code Date: Wed, 31 May 2023 19:07:42 +0800 Subject: [PATCH 138/228] generic proxy: add support to the original dst cluster and subset lb (#27502) Signed-off-by: wbpcode --- .../filters/network/source/interface/filter.h | 5 ++ .../filters/network/source/proxy.cc | 4 ++ .../filters/network/source/proxy.h | 1 + .../filters/network/source/router/BUILD | 2 + .../filters/network/source/router/router.cc | 23 ++++++++ .../filters/network/source/router/router.h | 6 +++ .../filters/network/test/mocks/filter.h | 1 + .../filters/network/test/proxy_test.cc | 21 ++++++++ .../network/test/router/router_test.cc | 54 +++++++++++++++++++ 9 files changed, 117 insertions(+) diff --git a/contrib/generic_proxy/filters/network/source/interface/filter.h b/contrib/generic_proxy/filters/network/source/interface/filter.h index 36f0f30698d0..e8bcdb06c861 100644 --- a/contrib/generic_proxy/filters/network/source/interface/filter.h +++ b/contrib/generic_proxy/filters/network/source/interface/filter.h @@ -75,6 +75,11 @@ class StreamFilterCallbacks { * @return absl::optional the extended options from upstream response. */ virtual absl::optional responseOptions() const PURE; + + /** + * @return const Network::Connection* downstream connection. + */ + virtual const Network::Connection* connection() const PURE; }; class UpstreamBindingCallback { diff --git a/contrib/generic_proxy/filters/network/source/proxy.cc b/contrib/generic_proxy/filters/network/source/proxy.cc index c8e03e87c13d..7925d27b54a5 100644 --- a/contrib/generic_proxy/filters/network/source/proxy.cc +++ b/contrib/generic_proxy/filters/network/source/proxy.cc @@ -137,6 +137,10 @@ OptRef ActiveStream::ActiveDecoderFilter::boundUpstreamConn() { return parent_.parent_.boundUpstreamConn(); } +const Network::Connection* ActiveStream::ActiveFilterBase::connection() const { + return &parent_.parent_.connection(); +} + void ActiveStream::continueEncoding() { if (active_stream_reset_ || local_or_upstream_response_stream_ == nullptr) { return; diff --git a/contrib/generic_proxy/filters/network/source/proxy.h b/contrib/generic_proxy/filters/network/source/proxy.h index 3de767b737e9..964815908dc3 100644 --- a/contrib/generic_proxy/filters/network/source/proxy.h +++ b/contrib/generic_proxy/filters/network/source/proxy.h @@ -130,6 +130,7 @@ class ActiveStream : public FilterChainManager, absl::optional responseOptions() const override { return parent_.local_or_upstream_response_options_; } + const Network::Connection* connection() const override; bool isDualFilter() const { return is_dual_; } diff --git a/contrib/generic_proxy/filters/network/source/router/BUILD b/contrib/generic_proxy/filters/network/source/router/BUILD index e78d581f9cf0..0b06176425b0 100644 --- a/contrib/generic_proxy/filters/network/source/router/BUILD +++ b/contrib/generic_proxy/filters/network/source/router/BUILD @@ -25,6 +25,8 @@ envoy_cc_library( "//source/common/buffer:buffer_lib", "//source/common/common:linked_object", "//source/common/common:minimal_logger_lib", + "//source/common/config:well_known_names", + "//source/common/router:metadatamatchcriteria_lib", "//source/common/stream_info:stream_info_lib", "//source/common/tracing:tracer_lib", "//source/common/upstream:load_balancer_lib", diff --git a/contrib/generic_proxy/filters/network/source/router/router.cc b/contrib/generic_proxy/filters/network/source/router/router.cc index 8a24acbf3f67..eff84ef125a0 100644 --- a/contrib/generic_proxy/filters/network/source/router/router.cc +++ b/contrib/generic_proxy/filters/network/source/router/router.cc @@ -4,6 +4,8 @@ #include "envoy/network/connection.h" #include "source/common/common/assert.h" +#include "source/common/config/well_known_names.h" +#include "source/common/router/metadatamatchcriteria_impl.h" #include "source/common/tracing/tracer_impl.h" #include "contrib/generic_proxy/filters/network/source/interface/filter.h" @@ -395,6 +397,27 @@ FilterStatus RouterFilter::onStreamDecoded(Request& request) { return FilterStatus::StopIteration; } +const Envoy::Router::MetadataMatchCriteria* RouterFilter::metadataMatchCriteria() { + // Have we been called before? If so, there's no need to recompute. + if (metadata_match_ != nullptr) { + return metadata_match_.get(); + } + + const auto& request_metadata = callbacks_->streamInfo().dynamicMetadata().filter_metadata(); + const auto filter_it = request_metadata.find(Envoy::Config::MetadataFilters::get().ENVOY_LB); + + if (filter_it == request_metadata.end()) { + return nullptr; + } + + metadata_match_ = std::make_unique(filter_it->second); + return metadata_match_.get(); +} + +const Network::Connection* RouterFilter::downstreamConnection() const { + return callbacks_ != nullptr ? callbacks_->connection() : nullptr; +} + } // namespace Router } // namespace GenericProxy } // namespace NetworkFilters diff --git a/contrib/generic_proxy/filters/network/source/router/router.h b/contrib/generic_proxy/filters/network/source/router/router.h index 9d6905c9519b..8666fb44124a 100644 --- a/contrib/generic_proxy/filters/network/source/router/router.h +++ b/contrib/generic_proxy/filters/network/source/router/router.h @@ -142,6 +142,10 @@ class RouterFilter : public DecoderFilter, std::list& upstreamRequestsForTest() { return upstream_requests_; } + // Upstream::LoadBalancerContextBase + const Envoy::Router::MetadataMatchCriteria* metadataMatchCriteria() override; + const Network::Connection* downstreamConnection() const override; + private: friend class UpstreamRequest; friend class UpstreamManagerImpl; @@ -159,6 +163,8 @@ class RouterFilter : public DecoderFilter, Upstream::ClusterInfoConstSharedPtr cluster_; Request* request_{}; + Envoy::Router::MetadataMatchCriteriaConstPtr metadata_match_; + RequestEncoderPtr request_encoder_; std::list upstream_requests_; diff --git a/contrib/generic_proxy/filters/network/test/mocks/filter.h b/contrib/generic_proxy/filters/network/test/mocks/filter.h index bf861429c15d..4f563c6416dc 100644 --- a/contrib/generic_proxy/filters/network/test/mocks/filter.h +++ b/contrib/generic_proxy/filters/network/test/mocks/filter.h @@ -115,6 +115,7 @@ template class MockStreamFilterCallbacks : public Base { MOCK_METHOD(OptRef, tracingConfig, (), (const)); MOCK_METHOD(absl::optional, requestOptions, (), (const)); MOCK_METHOD(absl::optional, responseOptions, (), (const)); + MOCK_METHOD(const Network::Connection*, connection, (), (const)); }; class MockUpstreamManager : public UpstreamManager { diff --git a/contrib/generic_proxy/filters/network/test/proxy_test.cc b/contrib/generic_proxy/filters/network/test/proxy_test.cc index 2a547fe1abc7..4020b27542c7 100644 --- a/contrib/generic_proxy/filters/network/test/proxy_test.cc +++ b/contrib/generic_proxy/filters/network/test/proxy_test.cc @@ -427,6 +427,27 @@ TEST_F(FilterTest, ActiveStreamPerFilterConfigNoRouteEntry) { EXPECT_EQ(nullptr, active_stream->decoderFiltersForTest()[0]->perFilterConfig()); } +TEST_F(FilterTest, ActiveStreamConnection) { + mock_stream_filters_.push_back( + {"fake_test_filter_name_0", std::make_shared>()}); + + initializeFilter(); + + auto request = std::make_unique(); + filter_->newDownstreamRequest(std::move(request), ExtendedOptions()); + EXPECT_EQ(1, filter_->activeStreamsForTest().size()); + + auto active_stream = filter_->activeStreamsForTest().begin()->get(); + + EXPECT_EQ(1, active_stream->decoderFiltersForTest().size()); + EXPECT_EQ(1, active_stream->encoderFiltersForTest().size()); + EXPECT_EQ(1, active_stream->nextDecoderFilterIndexForTest()); + EXPECT_EQ(0, active_stream->nextEncoderFilterIndexForTest()); + + EXPECT_EQ(&filter_callbacks_.connection_, + active_stream->decoderFiltersForTest()[0]->connection()); +} + TEST_F(FilterTest, ActiveStreamAddFilters) { initializeFilter(); diff --git a/contrib/generic_proxy/filters/network/test/router/router_test.cc b/contrib/generic_proxy/filters/network/test/router/router_test.cc index ff979fdecca6..62384272689e 100644 --- a/contrib/generic_proxy/filters/network/test/router/router_test.cc +++ b/contrib/generic_proxy/filters/network/test/router/router_test.cc @@ -276,6 +276,42 @@ class RouterFilterTest : public testing::TestWithParam { EXPECT_EQ(1, filter_->upstreamRequestsForTest().size()); } + void verifyMetadataMatchCriteria() { + ProtobufWkt::Struct request_struct; + ProtobufWkt::Value val; + + // Populate metadata like StreamInfo.setDynamicMetadata() would. + auto& fields_map = *request_struct.mutable_fields(); + val.set_string_value("v3.1"); + fields_map["version"] = val; + val.set_string_value("devel"); + fields_map["stage"] = val; + val.set_string_value("1"); + fields_map["xkey_in_request"] = val; + (*mock_stream_info_.metadata_ + .mutable_filter_metadata())[Envoy::Config::MetadataFilters::get().ENVOY_LB] = + request_struct; + + auto match = filter_->metadataMatchCriteria()->metadataMatchCriteria(); + + EXPECT_EQ(match.size(), 3); + auto it = match.begin(); + + // Note: metadataMatchCriteria() keeps its entries sorted, so the order for checks + // below matters. + + EXPECT_EQ((*it)->name(), "stage"); + EXPECT_EQ((*it)->value().value().string_value(), "devel"); + it++; + + EXPECT_EQ((*it)->name(), "version"); + EXPECT_EQ((*it)->value().value().string_value(), "v3.1"); + it++; + + EXPECT_EQ((*it)->name(), "xkey_in_request"); + EXPECT_EQ((*it)->value().value().string_value(), "1"); + } + NiceMock factory_context_; NiceMock dispatcher_; @@ -707,6 +743,24 @@ TEST_P(RouterFilterTest, UpstreamRequestPoolReadyAndResponseDecodingFailure) { notifyDecodingFailure(); } +TEST_P(RouterFilterTest, LoadBalancerContextDownstreamConnection) { + setup(); + EXPECT_CALL(mock_filter_callback_, connection()); + filter_->downstreamConnection(); +} + +TEST_P(RouterFilterTest, LoadBalancerContextNoMetadataMatchCriteria) { + setup(); + + // No metadata match criteria by default. + EXPECT_EQ(nullptr, filter_->metadataMatchCriteria()); +} + +TEST_P(RouterFilterTest, LoadBalancerContextMetadataMatchCriteria) { + setup(); + verifyMetadataMatchCriteria(); +} + } // namespace } // namespace Router } // namespace GenericProxy From 26797819a34cc4461d8cf2c0019463ab4d04509f Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 31 May 2023 13:52:55 +0100 Subject: [PATCH 139/228] mobile/ci: Fix/cleanup yaml config (#27720) Signed-off-by: Ryan Northey --- .github/workflows/mobile-compile_time_options.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mobile-compile_time_options.yml b/.github/workflows/mobile-compile_time_options.yml index 5d2ee4083d5c..ae6b82e4ec57 100644 --- a/.github/workflows/mobile-compile_time_options.yml +++ b/.github/workflows/mobile-compile_time_options.yml @@ -34,7 +34,8 @@ jobs: run: | # Envoy Mobile build which verifies that the build configuration where HTTP/3 is enabled and # HTTP Datagrams are disabled works. - cd mobile && ./bazelw test \ + cd mobile + ./bazelw test \ $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-linux") \ --define=signal_trace=disabled \ --define=admin_html=enabled \ @@ -43,9 +44,9 @@ jobs: --define=google_grpc=disabled \ --@envoy//bazel:http3=False \ --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ - //test/cc/... \ - # Envoy Mobile build which verifies that the build configuration where YAML is disabled. - && ./bazelw test \ + //test/cc/... + # Envoy Mobile build which verifies that the build configuration where YAML is disabled. + ./bazelw test \ $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ --config=ci \ --fat_apk_cpu=x86_64 \ @@ -57,7 +58,7 @@ jobs: --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ //test/java/integration:android_engine_socket_tag_test \ //test/java/integration:android_engine_start_test \ - //test/java/io/envoyproxy/envoymobile/utilities:certificate_verification_tests + //test/java/io/envoyproxy/envoymobile/utilities:certificate_verification_tests \ //test/common/integration:client_integration_test swift_build: if: ${{ needs.env.outputs.mobile_compile_time_options == 'true' }} From 0ae464feb4b3d1655baed1087cc97339fc644712 Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 1 Jun 2023 00:37:35 +1000 Subject: [PATCH 140/228] docs: fix xDS RPC variant list (#27715) In restructured text, nested lists need a blank line separator to make them render as lists rather than as paragraph content. Signed-off-by: James Peach --- docs/root/api-docs/xds_protocol.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/root/api-docs/xds_protocol.rst b/docs/root/api-docs/xds_protocol.rst index bc2a3db82cac..0ba5abb942ed 100644 --- a/docs/root/api-docs/xds_protocol.rst +++ b/docs/root/api-docs/xds_protocol.rst @@ -162,27 +162,42 @@ Each of these RPC services can provide a method for each of the SotW and Increme variants. Here are the RPC services and methods for each resource type: - Listener: Listener Discovery Service (LDS) + - SotW: ListenerDiscoveryService.StreamListeners - Incremental: ListenerDiscoveryService.DeltaListeners + - RouteConfiguration: Route Discovery Service (RDS) + - SotW: RouteDiscoveryService.StreamRoutes - Incremental: RouteDiscoveryService.DeltaRoutes + - ScopedRouteConfiguration: Scoped Route Discovery Service (SRDS) + - SotW: ScopedRouteDiscoveryService.StreamScopedRoutes - Incremental: ScopedRouteDiscoveryService.DeltaScopedRoutes + - VirtualHost: Virtual Host Discovery Service (VHDS) + - SotW: N/A - Incremental: VirtualHostDiscoveryService.DeltaVirtualHosts + - Cluster: Cluster Discovery Service (CDS) + - SotW: ClusterDiscoveryService.StreamClusters - Incremental: ClusterDiscoveryService.DeltaClusters + - ClusterLoadAssignment: Endpoint Discovery Service (EDS) + - SotW: EndpointDiscoveryService.StreamEndpoints - Incremental: EndpointDiscoveryService.DeltaEndpoints + - Secret: Secret Discovery Service (SDS) + - SotW: SecretDiscoveryService.StreamSecrets - Incremental: SecretDiscoveryService.DeltaSecrets + - Runtime: Runtime Discovery Service (RTDS) + - SotW: RuntimeDiscoveryService.StreamRuntime - Incremental: RuntimeDiscoveryService.DeltaRuntime From 644e991d2b3a6bfdfed4da7c55da957cd18db57e Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 31 May 2023 19:05:24 +0100 Subject: [PATCH 141/228] ci/examples: Add diskspace hack (github version) (#27734) Signed-off-by: Ryan Northey --- .github/workflows/envoy-verify.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/envoy-verify.yml b/.github/workflows/envoy-verify.yml index 7682fe649507..5460797233b5 100644 --- a/.github/workflows/envoy-verify.yml +++ b/.github/workflows/envoy-verify.yml @@ -38,6 +38,23 @@ jobs: runs-on: ubuntu-20.04 needs: check steps: + - run: | + echo "Disk space before cruft removal" + df -h + + TO_REMOVE=( + /opt/hostedtoolcache + /usr/local/lib/android + /usr/local/.ghcup) + + for removal in "${TO_REMOVE[@]}"; do + echo "Removing: ${removal} ..." + sudo rm -rf "$removal" + done + + echo "Disk space after cruft removal" + df -h + # Checkout the repo at provided commit - name: 'Checkout Repository' uses: actions/checkout@v3 From 702edcd142ce1cd3b9b325159bca9a51de6d4451 Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Wed, 31 May 2023 14:06:02 -0400 Subject: [PATCH 142/228] matcher: Implement CEL matcher (#27527) Signed-off-by: tyxia --- CODEOWNERS | 4 + bazel/repository_locations.bzl | 6 +- changelogs/current.yaml | 4 + .../advanced/matching/matching_api.rst | 10 + source/extensions/extensions_build_config.bzl | 6 + source/extensions/extensions_metadata.yaml | 14 + .../extensions/filters/common/expr/context.h | 32 +- .../filters/common/expr/evaluator.h | 26 +- .../extensions/matching/http/cel_input/BUILD | 25 + .../matching/http/cel_input/cel_input.cc | 18 + .../matching/http/cel_input/cel_input.h | 82 +++ .../matching/input_matchers/cel_matcher/BUILD | 34 ++ .../input_matchers/cel_matcher/config.cc | 15 + .../input_matchers/cel_matcher/config.h | 53 ++ .../input_matchers/cel_matcher/matcher.cc | 54 ++ .../input_matchers/cel_matcher/matcher.h | 54 ++ .../matching/input_matchers/cel_matcher/BUILD | 36 ++ .../cel_matcher/cel_matcher_test.cc | 401 +++++++++++++ .../cel_matcher/cel_matcher_test.h | 554 ++++++++++++++++++ test/per_file_coverage.sh | 1 + tools/extensions/extensions_schema.yaml | 1 + 21 files changed, 1401 insertions(+), 29 deletions(-) create mode 100644 source/extensions/matching/http/cel_input/BUILD create mode 100644 source/extensions/matching/http/cel_input/cel_input.cc create mode 100644 source/extensions/matching/http/cel_input/cel_input.h create mode 100644 source/extensions/matching/input_matchers/cel_matcher/BUILD create mode 100644 source/extensions/matching/input_matchers/cel_matcher/config.cc create mode 100644 source/extensions/matching/input_matchers/cel_matcher/config.h create mode 100644 source/extensions/matching/input_matchers/cel_matcher/matcher.cc create mode 100644 source/extensions/matching/input_matchers/cel_matcher/matcher.h create mode 100644 test/extensions/matching/input_matchers/cel_matcher/BUILD create mode 100644 test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc create mode 100644 test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h diff --git a/CODEOWNERS b/CODEOWNERS index e9a63bb15179..33b257f22307 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -167,10 +167,14 @@ extensions/filters/http/oauth2 @derekargueta @snowp /*/extensions/matching/input_matchers/consistent_hashing @snowp @donyu # runtime fraction input matcher /*/extensions/matching/input_matchers/runtime_fraction @ravenblackx @UNOWNED +# CEL input matcher +/*/extensions/matching/input_matchers/cel_matcher @tyxia @UNOWNED # environment generic input /*/extensions/matching/common_inputs/environment @snowp @donyu # format string matching /*/extensions/matching/actions/format_string @kyessenov @UNOWNED +# CEL data input +/*/extensions/matching/http/cel_input @tyxia @UNOWNED # user space socket pair, event, connection and listener /*/extensions/io_socket/user_space @kyessenov @UNOWNED /*/extensions/bootstrap/internal_listener @kyessenov @adisuissa diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index a401e54c11af..6ea53a224d09 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1102,13 +1102,15 @@ REPOSITORY_LOCATIONS_SPEC = dict( "envoy.stat_sinks.wasm", "envoy.rbac.matchers.upstream_ip_port", "envoy.formatter.cel", + "envoy.matching.inputs.cel_data_input", + "envoy.matching.matchers.cel_matcher", ], release_date = "2023-03-08", cpe = "N/A", ), com_github_google_flatbuffers = dict( project_name = "FlatBuffers", - project_desc = "Cross platform serialization library architected for maximum memory efficiency", + project_desc = "FlatBuffers is a cross platform serialization library architected for maximum memory efficiency", project_url = "https://github.com/google/flatbuffers", version = "23.3.3", sha256 = "8aff985da30aaab37edf8e5b02fda33ed4cbdd962699a8e2af98fdef306f4e4d", @@ -1127,6 +1129,8 @@ REPOSITORY_LOCATIONS_SPEC = dict( "envoy.filters.network.wasm", "envoy.stat_sinks.wasm", "envoy.rbac.matchers.upstream_ip_port", + "envoy.matching.inputs.cel_data_input", + "envoy.matching.matchers.cel_matcher", ], release_date = "2023-03-03", cpe = "cpe:2.3:a:google:flatbuffers:*", diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 0a5f3aadd377..3db18423ae73 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -251,6 +251,10 @@ new_features: change: | added new field ``filter_metadata ` + and :ref:`CEL input matcher `. deprecated: - area: access_log diff --git a/docs/root/intro/arch_overview/advanced/matching/matching_api.rst b/docs/root/intro/arch_overview/advanced/matching/matching_api.rst index 3566c9176fff..767261840667 100644 --- a/docs/root/intro/arch_overview/advanced/matching/matching_api.rst +++ b/docs/root/intro/arch_overview/advanced/matching/matching_api.rst @@ -88,6 +88,16 @@ are available in some contexts: * :ref:`Trie-based IP matcher ` applies to network inputs. +* `Common Expression Language `_ (CEL) based matching: + +.. _extension_envoy.matching.inputs.cel_data_input: + + * CEL matching data input: :ref:`CEL data input value `. + +.. _extension_envoy.matching.matchers.cel_matcher: + + * CEL matching input matcher: :ref:`CEL input matcher `. + Matching actions ################ diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index 1cccfe090b8b..49f995c7bc32 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -79,6 +79,7 @@ EXTENSIONS = { "envoy.matching.matchers.consistent_hashing": "//source/extensions/matching/input_matchers/consistent_hashing:config", "envoy.matching.matchers.ip": "//source/extensions/matching/input_matchers/ip:config", "envoy.matching.matchers.runtime_fraction": "//source/extensions/matching/input_matchers/runtime_fraction:config", + "envoy.matching.matchers.cel_matcher": "//source/extensions/matching/input_matchers/cel_matcher:config", # # Network Matchers @@ -102,6 +103,11 @@ EXTENSIONS = { "envoy.matching.common_inputs.environment_variable": "//source/extensions/matching/common_inputs/environment_variable:config", + # + # CEL Matching Input + # + "envoy.matching.inputs.cel_data_input": "//source/extensions/matching/http/cel_input:cel_input_lib", + # # Matching actions # diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 0a19fb24bfbc..0d8f55d9fe26 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -885,6 +885,13 @@ envoy.matching.matchers.runtime_fraction: status: stable type_urls: - envoy.extensions.matching.input_matchers.runtime_fraction.v3.RuntimeFraction +envoy.matching.matchers.cel_matcher: + categories: + - envoy.matching.input_matchers + security_posture: robust_to_untrusted_downstream_and_upstream + status: stable + type_urls: + - xds.type.matcher.v3.CelMatcher envoy.path.match.uri_template.uri_template_matcher: categories: - envoy.path.match @@ -1349,6 +1356,13 @@ envoy.matching.inputs.query_params: status: alpha type_urls: - envoy.type.matcher.v3.HttpRequestQueryParamMatchInput +envoy.matching.inputs.cel_data_input: + categories: + - envoy.matching.http.input + security_posture: unknown + status: alpha + type_urls: + - xds.type.matcher.v3.HttpAttributesCelMatchInput envoy.matching.inputs.destination_ip: categories: - envoy.matching.http.input diff --git a/source/extensions/filters/common/expr/context.h b/source/extensions/filters/common/expr/context.h index 187f8455619d..7257655ffb77 100644 --- a/source/extensions/filters/common/expr/context.h +++ b/source/extensions/filters/common/expr/context.h @@ -99,10 +99,10 @@ using WrapperFields = ConstSingleton; class RequestWrapper; -absl::optional convertHeaderEntry(const Http::HeaderEntry* header); +absl::optional convertHeaderEntry(const ::Envoy::Http::HeaderEntry* header); absl::optional convertHeaderEntry(Protobuf::Arena& arena, - Http::HeaderUtility::GetAllOfHeaderAsStringResult&& result); + ::Envoy::Http::HeaderUtility::GetAllOfHeaderAsStringResult&& result); template class HeadersWrapper : public google::api::expr::runtime::CelMap { public: @@ -112,12 +112,12 @@ template class HeadersWrapper : public google::api::expr::runtime::Cel return {}; } auto str = std::string(key.StringOrDie().value()); - if (!Http::validHeaderString(str)) { + if (!::Envoy::Http::validHeaderString(str)) { // Reject key if it is an invalid header string return {}; } - return convertHeaderEntry( - arena_, Http::HeaderUtility::getAllOfHeaderAsString(*value_, Http::LowerCaseString(str))); + return convertHeaderEntry(arena_, ::Envoy::Http::HeaderUtility::getAllOfHeaderAsString( + *value_, ::Envoy::Http::LowerCaseString(str))); } int size() const override { return ListKeys().value()->size(); } bool empty() const override { return value_ == nullptr ? true : value_->empty(); } @@ -126,10 +126,11 @@ template class HeadersWrapper : public google::api::expr::runtime::Cel return &WrapperFields::get().Empty; } absl::flat_hash_set keys; - value_->iterate([&keys](const Http::HeaderEntry& header) -> Http::HeaderMap::Iterate { - keys.insert(header.key().getStringView()); - return Http::HeaderMap::Iterate::Continue; - }); + value_->iterate( + [&keys](const ::Envoy::Http::HeaderEntry& header) -> ::Envoy::Http::HeaderMap::Iterate { + keys.insert(header.key().getStringView()); + return ::Envoy::Http::HeaderMap::Iterate::Continue; + }); std::vector values; values.reserve(keys.size()); for (const auto& key : keys) { @@ -163,26 +164,27 @@ class BaseWrapper : public google::api::expr::runtime::CelMap { class RequestWrapper : public BaseWrapper { public: - RequestWrapper(Protobuf::Arena& arena, const Http::RequestHeaderMap* headers, + RequestWrapper(Protobuf::Arena& arena, const ::Envoy::Http::RequestHeaderMap* headers, const StreamInfo::StreamInfo& info) : BaseWrapper(arena), headers_(arena, headers), info_(info) {} absl::optional operator[](CelValue key) const override; private: - const HeadersWrapper headers_; + const HeadersWrapper<::Envoy::Http::RequestHeaderMap> headers_; const StreamInfo::StreamInfo& info_; }; class ResponseWrapper : public BaseWrapper { public: - ResponseWrapper(Protobuf::Arena& arena, const Http::ResponseHeaderMap* headers, - const Http::ResponseTrailerMap* trailers, const StreamInfo::StreamInfo& info) + ResponseWrapper(Protobuf::Arena& arena, const ::Envoy::Http::ResponseHeaderMap* headers, + const ::Envoy::Http::ResponseTrailerMap* trailers, + const StreamInfo::StreamInfo& info) : BaseWrapper(arena), headers_(arena, headers), trailers_(arena, trailers), info_(info) {} absl::optional operator[](CelValue key) const override; private: - const HeadersWrapper headers_; - const HeadersWrapper trailers_; + const HeadersWrapper<::Envoy::Http::ResponseHeaderMap> headers_; + const HeadersWrapper<::Envoy::Http::ResponseTrailerMap> trailers_; const StreamInfo::StreamInfo& info_; }; diff --git a/source/extensions/filters/common/expr/evaluator.h b/source/extensions/filters/common/expr/evaluator.h index 4df508dae2ae..63ed1e1266b8 100644 --- a/source/extensions/filters/common/expr/evaluator.h +++ b/source/extensions/filters/common/expr/evaluator.h @@ -27,9 +27,9 @@ using ExpressionPtr = std::unique_ptr; class StreamActivation : public google::api::expr::runtime::BaseActivation { public: StreamActivation(const StreamInfo::StreamInfo& info, - const Http::RequestHeaderMap* request_headers, - const Http::ResponseHeaderMap* response_headers, - const Http::ResponseTrailerMap* response_trailers) + const ::Envoy::Http::RequestHeaderMap* request_headers, + const ::Envoy::Http::ResponseHeaderMap* response_headers, + const ::Envoy::Http::ResponseTrailerMap* response_trailers) : activation_info_(&info), activation_request_headers_(request_headers), activation_response_headers_(response_headers), activation_response_trailers_(response_trailers) {} @@ -45,17 +45,17 @@ class StreamActivation : public google::api::expr::runtime::BaseActivation { protected: void resetActivation() const; mutable const StreamInfo::StreamInfo* activation_info_{nullptr}; - mutable const Http::RequestHeaderMap* activation_request_headers_{nullptr}; - mutable const Http::ResponseHeaderMap* activation_response_headers_{nullptr}; - mutable const Http::ResponseTrailerMap* activation_response_trailers_{nullptr}; + mutable const ::Envoy::Http::RequestHeaderMap* activation_request_headers_{nullptr}; + mutable const ::Envoy::Http::ResponseHeaderMap* activation_response_headers_{nullptr}; + mutable const ::Envoy::Http::ResponseTrailerMap* activation_response_trailers_{nullptr}; }; // Creates an activation providing the common context attributes. // The activation lazily creates wrappers during an evaluation using the evaluation arena. ActivationPtr createActivation(const StreamInfo::StreamInfo& info, - const Http::RequestHeaderMap* request_headers, - const Http::ResponseHeaderMap* response_headers, - const Http::ResponseTrailerMap* response_trailers); + const ::Envoy::Http::RequestHeaderMap* request_headers, + const ::Envoy::Http::ResponseHeaderMap* response_headers, + const ::Envoy::Http::ResponseTrailerMap* response_trailers); // Creates an expression builder. The optional arena is used to enable constant folding // for intermediate evaluation results. @@ -70,14 +70,14 @@ ExpressionPtr createExpression(Builder& builder, const google::api::expr::v1alph // results and potentially the final value. absl::optional evaluate(const Expression& expr, Protobuf::Arena& arena, const StreamInfo::StreamInfo& info, - const Http::RequestHeaderMap* request_headers, - const Http::ResponseHeaderMap* response_headers, - const Http::ResponseTrailerMap* response_trailers); + const ::Envoy::Http::RequestHeaderMap* request_headers, + const ::Envoy::Http::ResponseHeaderMap* response_headers, + const ::Envoy::Http::ResponseTrailerMap* response_trailers); // Evaluates an expression and returns true if the expression evaluates to "true". // Returns false if the expression fails to evaluate. bool matches(const Expression& expr, const StreamInfo::StreamInfo& info, - const Http::RequestHeaderMap& headers); + const ::Envoy::Http::RequestHeaderMap& headers); // Returns a string for a CelValue. std::string print(CelValue value); diff --git a/source/extensions/matching/http/cel_input/BUILD b/source/extensions/matching/http/cel_input/BUILD new file mode 100644 index 000000000000..0c283b322866 --- /dev/null +++ b/source/extensions/matching/http/cel_input/BUILD @@ -0,0 +1,25 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_extension( + name = "cel_input_lib", + srcs = ["cel_input.cc"], + hdrs = ["cel_input.h"], + extra_visibility = [ + ], + deps = [ + "//envoy/http:filter_interface", + "//envoy/http:header_map_interface", + "//source/common/http:header_utility_lib", + "//source/common/http:utility_lib", + "//source/extensions/filters/common/expr:evaluator_lib", + "@envoy_api//envoy/type/matcher/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/matching/http/cel_input/cel_input.cc b/source/extensions/matching/http/cel_input/cel_input.cc new file mode 100644 index 000000000000..2e4ceeb0ad25 --- /dev/null +++ b/source/extensions/matching/http/cel_input/cel_input.cc @@ -0,0 +1,18 @@ +#include "source/extensions/matching/http/cel_input/cel_input.h" + +#include "envoy/registry/registry.h" + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace Http { +namespace CelInput { + +REGISTER_FACTORY(HttpCelDataInputFactory, + Matcher::DataInputFactory<::Envoy::Http::HttpMatchingData>); + +} // namespace CelInput +} // namespace Http +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/matching/http/cel_input/cel_input.h b/source/extensions/matching/http/cel_input/cel_input.h new file mode 100644 index 000000000000..0e5707c4e2e4 --- /dev/null +++ b/source/extensions/matching/http/cel_input/cel_input.h @@ -0,0 +1,82 @@ +#pragma once + +#include "envoy/http/filter.h" +#include "envoy/matcher/matcher.h" +#include "envoy/server/factory_context.h" +#include "envoy/type/matcher/v3/http_inputs.pb.h" +#include "envoy/type/matcher/v3/http_inputs.pb.validate.h" + +#include "source/common/http/header_utility.h" +#include "source/common/http/utility.h" +#include "source/extensions/filters/common/expr/evaluator.h" + +#include "xds/type/matcher/v3/http_inputs.pb.h" + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace Http { +namespace CelInput { + +using ::Envoy::Http::RequestHeaderMapOptConstRef; +using ::Envoy::Http::ResponseHeaderMapOptConstRef; +using ::Envoy::Http::ResponseTrailerMapOptConstRef; + +using BaseActivationPtr = std::unique_ptr; + +// CEL matcher specific matching data +class CelMatchData : public ::Envoy::Matcher::CustomMatchData { +public: + explicit CelMatchData(BaseActivationPtr activation) : activation_(std::move(activation)) {} + BaseActivationPtr activation_; +}; + +class HttpCelDataInput : public Matcher::DataInput { +public: + HttpCelDataInput() = default; + Matcher::DataInputGetResult get(const Envoy::Http::HttpMatchingData& data) const override { + RequestHeaderMapOptConstRef maybe_request_headers = data.requestHeaders(); + ResponseHeaderMapOptConstRef maybe_response_headers = data.responseHeaders(); + ResponseTrailerMapOptConstRef maybe_response_trailers = data.responseTrailers(); + + // Returns NotAvailable state when all of three below are empty. + if (!maybe_request_headers && !maybe_response_headers && !maybe_response_trailers) { + return {Matcher::DataInputGetResult::DataAvailability::NotAvailable, absl::monostate()}; + } + + // CEL library supports mixed matching condition of request headers, response headers and + // response trailers. + std::unique_ptr activation = + Extensions::Filters::Common::Expr::createActivation( + data.streamInfo(), maybe_request_headers.ptr(), maybe_response_headers.ptr(), + maybe_response_trailers.ptr()); + + return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, + std::make_unique(std::move(activation))}; + } + + absl::string_view dataInputType() const override { return "cel_data_input"; } +}; + +class HttpCelDataInputFactory : public Matcher::DataInputFactory { +public: + HttpCelDataInputFactory() = default; + std::string name() const override { return "envoy.matching.inputs.cel_data_input"; } + + Matcher::DataInputFactoryCb + createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { + return [] { return std::make_unique(); }; + } + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } +}; + +DECLARE_FACTORY(HttpCelDataInputFactory); + +} // namespace CelInput +} // namespace Http +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/matching/input_matchers/cel_matcher/BUILD b/source/extensions/matching/input_matchers/cel_matcher/BUILD new file mode 100644 index 000000000000..748641ef45e6 --- /dev/null +++ b/source/extensions/matching/input_matchers/cel_matcher/BUILD @@ -0,0 +1,34 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_library( + name = "cel_matcher_lib", + srcs = ["matcher.cc"], + hdrs = ["matcher.h"], + deps = [ + "//envoy/matcher:matcher_interface", + "//source/common/protobuf:utility_lib", + "//source/extensions/filters/common/expr:evaluator_lib", + "//source/extensions/matching/http/cel_input:cel_input_lib", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + deps = [ + ":cel_matcher_lib", + "//envoy/matcher:matcher_interface", + "//envoy/registry", + "//envoy/server:factory_context_interface", + ], +) diff --git a/source/extensions/matching/input_matchers/cel_matcher/config.cc b/source/extensions/matching/input_matchers/cel_matcher/config.cc new file mode 100644 index 000000000000..d2f961a314c7 --- /dev/null +++ b/source/extensions/matching/input_matchers/cel_matcher/config.cc @@ -0,0 +1,15 @@ +#include "source/extensions/matching/input_matchers/cel_matcher/config.h" + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace InputMatchers { +namespace CelMatcher { + +REGISTER_FACTORY(CelInputMatcherFactory, Envoy::Matcher::InputMatcherFactory); + +} // namespace CelMatcher +} // namespace InputMatchers +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/matching/input_matchers/cel_matcher/config.h b/source/extensions/matching/input_matchers/cel_matcher/config.h new file mode 100644 index 000000000000..d894ebe7cb8a --- /dev/null +++ b/source/extensions/matching/input_matchers/cel_matcher/config.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include + +#include "envoy/matcher/matcher.h" + +#include "source/common/protobuf/utility.h" +#include "source/extensions/matching/input_matchers/cel_matcher/matcher.h" + +#include "xds/type/matcher/v3/cel.pb.h" + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace InputMatchers { +namespace CelMatcher { + +class CelInputMatcherFactory : public ::Envoy::Matcher::InputMatcherFactory { +public: + InputMatcherFactoryCb + createInputMatcherFactoryCb(const Protobuf::Message& config, + Server::Configuration::ServerFactoryContext&) override { + if (expr_builder_ == nullptr) { + expr_builder_ = Extensions::Filters::Common::Expr::createBuilder(nullptr); + } + + const auto& cel_matcher_config = + dynamic_cast(config); + CelMatcherSharedPtr cel_matcher = + std::make_shared<::xds::type::matcher::v3::CelMatcher>(cel_matcher_config); + + return [cel_matcher = std::move(cel_matcher), this] { + return std::make_unique(cel_matcher, *expr_builder_); + }; + } + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + + std::string name() const override { return "envoy.matching.matchers.cel_matcher"; } + +private: + // Expression builder must outlive the compiled expression. + BuilderPtr expr_builder_; +}; + +} // namespace CelMatcher +} // namespace InputMatchers +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/matching/input_matchers/cel_matcher/matcher.cc b/source/extensions/matching/input_matchers/cel_matcher/matcher.cc new file mode 100644 index 000000000000..d6d61bc81142 --- /dev/null +++ b/source/extensions/matching/input_matchers/cel_matcher/matcher.cc @@ -0,0 +1,54 @@ +#include "source/extensions/matching/input_matchers/cel_matcher/matcher.h" + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace InputMatchers { +namespace CelMatcher { + +using ::Envoy::Extensions::Matching::Http::CelInput::CelMatchData; +using ::xds::type::v3::CelExpression; + +CelInputMatcher::CelInputMatcher(CelMatcherSharedPtr cel_matcher, Builder& builder) + : cel_matcher_(std::move(cel_matcher)) { + const CelExpression& input_expr = cel_matcher_->expr_match(); + switch (input_expr.expr_specifier_case()) { + case CelExpression::ExprSpecifierCase::kParsedExpr: + compiled_expr_ = + Filters::Common::Expr::createExpression(builder, input_expr.parsed_expr().expr()); + return; + case CelExpression::ExprSpecifierCase::kCheckedExpr: + compiled_expr_ = + Filters::Common::Expr::createExpression(builder, input_expr.checked_expr().expr()); + return; + case CelExpression::ExprSpecifierCase::EXPR_SPECIFIER_NOT_SET: + PANIC_DUE_TO_PROTO_UNSET; + } + PANIC_DUE_TO_CORRUPT_ENUM; +} + +bool CelInputMatcher::match(const MatchingDataType& input) { + Protobuf::Arena arena; + if (auto* ptr = absl::get_if>(&input); + ptr != nullptr) { + CelMatchData* cel_data = dynamic_cast((*ptr).get()); + // Compiled expression should not be nullptr at this point because the program should have + // encountered a panic in the constructor earlier if any such error cases occurred. CEL matching + // data should also not be nullptr since any errors should have been thrown by the CEL library + // already. + ASSERT(compiled_expr_ != nullptr && cel_data != nullptr); + + auto eval_result = compiled_expr_->Evaluate(*cel_data->activation_, &arena); + if (eval_result.ok() && eval_result.value().IsBool()) { + return eval_result.value().BoolOrDie(); + } + } + + return false; +} + +} // namespace CelMatcher +} // namespace InputMatchers +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/matching/input_matchers/cel_matcher/matcher.h b/source/extensions/matching/input_matchers/cel_matcher/matcher.h new file mode 100644 index 000000000000..5ac9e366c675 --- /dev/null +++ b/source/extensions/matching/input_matchers/cel_matcher/matcher.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include + +#include "envoy/matcher/matcher.h" + +#include "source/common/protobuf/utility.h" +#include "source/extensions/filters/common/expr/evaluator.h" +#include "source/extensions/matching/http/cel_input/cel_input.h" + +#include "absl/types/variant.h" +#include "xds/type/matcher/v3/cel.pb.h" + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace InputMatchers { +namespace CelMatcher { + +using ::Envoy::Matcher::InputMatcher; +using ::Envoy::Matcher::InputMatcherFactoryCb; +using ::Envoy::Matcher::MatchingDataType; + +using CelMatcher = ::xds::type::matcher::v3::CelMatcher; +using CompiledExpressionPtr = std::unique_ptr; +using BaseActivationPtr = std::unique_ptr; +using Builder = google::api::expr::runtime::CelExpressionBuilder; +using BuilderPtr = std::unique_ptr; +using CelMatcherSharedPtr = std::shared_ptr<::xds::type::matcher::v3::CelMatcher>; + +class CelInputMatcher : public InputMatcher, public Logger::Loggable { +public: + CelInputMatcher(CelMatcherSharedPtr cel_matcher, Builder& builder); + + bool match(const MatchingDataType& input) override; + + // TODO(tyxia) Formalize the validation approach. Use fixed string for now. + absl::flat_hash_set supportedDataInputTypes() const override { + return absl::flat_hash_set{"cel_data_input"}; + } + +private: + // Expression proto must outlive the compiled expression. + CelMatcherSharedPtr cel_matcher_; + CompiledExpressionPtr compiled_expr_; +}; + +} // namespace CelMatcher +} // namespace InputMatchers +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/matching/input_matchers/cel_matcher/BUILD b/test/extensions/matching/input_matchers/cel_matcher/BUILD new file mode 100644 index 000000000000..bd175a3dea4b --- /dev/null +++ b/test/extensions/matching/input_matchers/cel_matcher/BUILD @@ -0,0 +1,36 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_extension_cc_test( + name = "cel_matcher_test", + srcs = [ + "cel_matcher_test.cc", + "cel_matcher_test.h", + ], + extension_names = ["envoy.matching.matchers.cel_matcher"], + deps = [ + "//source/common/matcher:matcher_lib", + "//source/extensions/matching/http/cel_input:cel_input_lib", + "//source/extensions/matching/input_matchers/cel_matcher:cel_matcher_lib", + "//source/extensions/matching/input_matchers/cel_matcher:config", + "//test/common/matcher:test_utility_lib", + "//test/mocks/http:http_mocks", + "//test/mocks/matcher:matcher_mocks", + "//test/mocks/server:factory_context_mocks", + "//test/mocks/stream_info:stream_info_mocks", + "//test/test_common:registry_lib", + "@com_github_cncf_udpa//xds/type/matcher/v3:pkg_cc_proto", + "@envoy_api//envoy/config/common/matcher/v3:pkg_cc_proto", + "@envoy_api//envoy/config/core/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc new file mode 100644 index 000000000000..f1d3378a800d --- /dev/null +++ b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc @@ -0,0 +1,401 @@ +#include "test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h" + +#include +#include + +#include "envoy/config/common/matcher/v3/matcher.pb.validate.h" +#include "envoy/config/core/v3/extension.pb.h" +#include "envoy/matcher/matcher.h" +#include "envoy/registry/registry.h" + +#include "source/common/matcher/matcher.h" +#include "source/common/protobuf/utility.h" +#include "source/extensions/matching/http/cel_input/cel_input.h" +#include "source/extensions/matching/input_matchers/cel_matcher/config.h" +#include "source/extensions/matching/input_matchers/cel_matcher/matcher.h" + +#include "test/common/matcher/test_utility.h" +#include "test/mocks/matcher/mocks.h" +#include "test/mocks/server/factory_context.h" +#include "test/test_common/registry.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" +#include "xds/type/matcher/v3/matcher.pb.validate.h" + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace InputMatchers { +namespace CelMatcher { + +using ::Envoy::Http::LowerCaseString; +using ::Envoy::Http::TestRequestHeaderMapImpl; +using ::Envoy::Http::TestResponseHeaderMapImpl; +using ::Envoy::Http::TestResponseTrailerMapImpl; + +enum class ExpressionType { + CheckedExpression = 0, + ParsedExpression = 1, + NoExpression = 2, +}; + +class CelMatcherTest : public ::testing::Test { +public: + CelMatcherTest() + : inject_action_(action_factory_), + data_(Envoy::Http::Matching::HttpMatchingDataImpl(stream_info_)) {} + + void buildCustomHeader(const absl::flat_hash_map& custom_value_pairs, + TestRequestHeaderMapImpl& headers) { + // Add custom_value_pairs to the request header. + for (auto const& pair : custom_value_pairs) { + headers.setCopy(LowerCaseString(pair.first), pair.second); + } + } + + Matcher::MatchTreeSharedPtr + buildMatcherTree(const std::string& cel_expr_config, + ExpressionType expr_type = ExpressionType::CheckedExpression) { + xds::type::matcher::v3::CelMatcher cel_matcher; + switch (expr_type) { + case ExpressionType::CheckedExpression: { + google::api::expr::v1alpha1::CheckedExpr checked_expr; + Protobuf::TextFormat::ParseFromString(cel_expr_config, &checked_expr); + cel_matcher.mutable_expr_match()->mutable_checked_expr()->MergeFrom(checked_expr); + break; + } + case ExpressionType::ParsedExpression: { + google::api::expr::v1alpha1::ParsedExpr parsed_expr; + Protobuf::TextFormat::ParseFromString(cel_expr_config, &parsed_expr); + cel_matcher.mutable_expr_match()->mutable_parsed_expr()->MergeFrom(parsed_expr); + break; + } + case ExpressionType::NoExpression: + break; + } + + xds::type::matcher::v3::Matcher matcher; + auto* inner_matcher = matcher.mutable_matcher_list()->add_matchers(); + auto* single_predicate = inner_matcher->mutable_predicate()->mutable_single_predicate(); + + xds::type::matcher::v3::HttpAttributesCelMatchInput cel_match_input; + single_predicate->mutable_input()->set_name("envoy.matching.inputs.cel_data_input"); + single_predicate->mutable_input()->mutable_typed_config()->PackFrom(cel_match_input); + + auto* custom_matcher = single_predicate->mutable_custom_match(); + custom_matcher->mutable_typed_config()->PackFrom(cel_matcher); + + xds::type::matcher::v3::Matcher::OnMatch on_match; + std::string on_match_config = R"EOF( + action: + name: test_action + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue + value: match!! + )EOF"; + MessageUtil::loadFromYaml(on_match_config, on_match, + ProtobufMessage::getStrictValidationVisitor()); + + inner_matcher->mutable_on_match()->MergeFrom(on_match); + + auto string_factory_on_match = Matcher::TestDataInputStringFactory("value"); + + Matcher::MockMatchTreeValidationVisitor validation_visitor; + EXPECT_CALL(validation_visitor, + performDataInputValidation( + _, "type.googleapis.com/xds.type.matcher.v3.HttpAttributesCelMatchInput")); + Matcher::MatchTreeFactory matcher_factory( + context_, factory_context_, validation_visitor); + auto match_tree = matcher_factory.create(matcher); + + return match_tree(); + } + + Matcher::StringActionFactory action_factory_; + Registry::InjectFactory> inject_action_; + testing::NiceMock stream_info_; + absl::string_view context_ = ""; + testing::NiceMock factory_context_; + + TestRequestHeaderMapImpl default_headers_{ + {":method", "GET"}, {":scheme", "http"}, {":authority", "host"}}; + + Envoy::Http::Matching::HttpMatchingDataImpl data_; +}; + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderMatched) { + auto matcher_tree = buildMatcherTree(RequestHeaderCelExprString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"authenticated_user", "staging"}}, request_headers); + data_.onRequestHeaders(request_headers); + // data.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderNotMatched) { + auto matcher_tree = buildMatcherTree(RequestHeaderCelExprString); + + // Build header with request header value field mismatched case. + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"authenticated_user", "NOT_MATCHED"}}, request_headers); + data_.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); + + // Build header with request header key field mismatched case. + TestRequestHeaderMapImpl request_headers_2 = default_headers_; + buildCustomHeader({{"NOT_MATCHED", "staging"}}, request_headers_2); + Envoy::Http::Matching::HttpMatchingDataImpl data_2 = + Envoy::Http::Matching::HttpMatchingDataImpl(stream_info_); + data_2.onRequestHeaders(request_headers_2); + const auto result_2 = matcher_tree->match(data_2); + // The match was completed, no match found. + EXPECT_EQ(result_2.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result_2.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherNoRequestAttributes) { + auto matcher_tree = buildMatcherTree(RequestHeaderCelExprString); + + // No request attributes added to matching data. + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::UnableToMatch); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderPathMatched) { + auto matcher_tree = buildMatcherTree(RequestPathCelExprString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{":path", "/foo"}}, request_headers); + data_.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderPathNotMatched) { + auto matcher_tree = buildMatcherTree(RequestPathCelExprString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + // The matching condition is: request.path == '/foo'. + buildCustomHeader({{":path", "/bar"}}, request_headers); + data_.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherResponseHeaderMatched) { + auto matcher_tree = buildMatcherTree(ReponseHeaderCelExprString); + + TestResponseHeaderMapImpl response_headers; + response_headers.addCopy(LowerCaseString(":status"), "200"); + response_headers.addCopy(LowerCaseString("content-type"), "text/plain"); + response_headers.addCopy(LowerCaseString("content-length"), "3"); + data_.onResponseHeaders(response_headers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherResponseHeaderNotMatched) { + auto matcher_tree = buildMatcherTree(ReponseHeaderCelExprString); + + TestResponseHeaderMapImpl response_headers = {{"content-type", "text/html"}}; + data_.onResponseHeaders(response_headers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherResponseTrailerMatched) { + auto matcher_tree = buildMatcherTree(ReponseTrailerCelExprString); + + TestResponseTrailerMapImpl response_trailers = {{"transfer-encoding", "chunked"}}; + data_.onResponseTrailers(response_trailers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherResponseTrailerNotMatched) { + auto matcher_tree = buildMatcherTree(ReponseTrailerCelExprString); + + TestResponseTrailerMapImpl response_trailers = {{"transfer-encoding", "chunked_not_matched"}}; + data_.onResponseTrailers(response_trailers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderAndPathMatched) { + auto matcher_tree = buildMatcherTree(RequestHeaderAndPathCelString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "staging"}, {":path", "/foo"}}, request_headers); + data_.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderAndPathNotMatched) { + auto matcher_tree = buildMatcherTree(RequestHeaderAndPathCelString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "prod"}, {":path", "/foo"}}, request_headers); + data_.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderOrPathMatched) { + auto matcher_tree = buildMatcherTree(RequestHeaderOrPathCelString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "prod"}, {":path", "/foo"}}, request_headers); + data_.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherRequestHeaderOrPathNotMatched) { + auto matcher_tree = buildMatcherTree(RequestHeaderOrPathCelString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "prod"}, {":path", "/bar"}}, request_headers); + data_.onRequestHeaders(request_headers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherRequestResponseMatched) { + auto matcher_tree = buildMatcherTree(RequestAndResponseCelString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "staging"}}, request_headers); + data_.onRequestHeaders(request_headers); + + TestResponseHeaderMapImpl response_headers = {{"content-type", "text/plain"}}; + data_.onResponseHeaders(response_headers); + + TestResponseTrailerMapImpl response_trailers = {{"transfer-encoding", "chunked"}}; + data_.onResponseTrailers(response_trailers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherRequestResponseNotMatched) { + auto matcher_tree = buildMatcherTree(RequestAndResponseCelString); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "staging"}}, request_headers); + data_.onRequestHeaders(request_headers); + + TestResponseHeaderMapImpl response_headers = {{"content-type", "text/html"}}; + data_.onResponseHeaders(response_headers); + + TestResponseTrailerMapImpl response_trailers = {{"transfer-encoding", "chunked"}}; + data_.onResponseTrailers(response_trailers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, CelMatcherRequestResponseMatchedWithParsedExpr) { + auto matcher_tree = + buildMatcherTree(RequestAndResponseCelString, ExpressionType::ParsedExpression); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "staging"}}, request_headers); + data_.onRequestHeaders(request_headers); + + TestResponseHeaderMapImpl response_headers = {{"content-type", "text/plain"}}; + data_.onResponseHeaders(response_headers); + + TestResponseTrailerMapImpl response_trailers = {{"transfer-encoding", "chunked"}}; + data_.onResponseTrailers(response_trailers); + + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherRequestResponseNotMatchedWithParsedExpr) { + auto matcher_tree = + buildMatcherTree(RequestAndResponseCelString, ExpressionType::ParsedExpression); + + TestRequestHeaderMapImpl request_headers = default_headers_; + buildCustomHeader({{"user", "staging"}}, request_headers); + data_.onRequestHeaders(request_headers); + + TestResponseHeaderMapImpl response_headers = {{"content-type", "text/html"}}; + data_.onResponseHeaders(response_headers); + + TestResponseTrailerMapImpl response_trailers = {{"transfer-encoding", "chunked"}}; + data_.onResponseTrailers(response_trailers); + + const auto result = matcher_tree->match(data_); + // The match was completed, no match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_EQ(result.on_match_, absl::nullopt); +} + +TEST_F(CelMatcherTest, NoCelExpression) { + EXPECT_DEATH(buildMatcherTree(RequestHeaderCelExprString, ExpressionType::NoExpression), + ".*panic: unset oneof.*"); +} + +} // namespace CelMatcher +} // namespace InputMatchers +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h new file mode 100644 index 000000000000..efadd414fe34 --- /dev/null +++ b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h @@ -0,0 +1,554 @@ +#pragma once + +namespace Envoy { +namespace Extensions { +namespace Matching { +namespace InputMatchers { +namespace CelMatcher { + +// Compiled CEL expression string: request.headers['authenticated_user'] == 'staging' +inline constexpr char RequestHeaderCelExprString[] = R"pb( + expr { + id: 8 + call_expr { + function: "_==_" + args { + id: 6 + call_expr { + function: "_[_]" + args { + id: 5 + select_expr { + operand { + id: 4 + ident_expr {name: "request"} + } + field: "headers" + } + } + args { + id: 7 + const_expr { + string_value: "authenticated_user" + } + } + } + } + args { + id: 9 + const_expr { string_value: "staging" } + } + } + } +)pb"; + +// Compiled CEL expression string: request.path == '/foo' +inline constexpr char RequestPathCelExprString[] = R"pb( + expr { + id: 3 + call_expr { + function: "_==_" + args { + id: 2 + select_expr { + operand { + id: 1 + ident_expr { + name: "request" + } + } + field: "path" + } + } + args { + id: 4 + const_expr { + string_value: "/foo" + } + } + } + } +)pb"; + +// Compiled CEL expression string: response.headers['content-type'] == 'text/plain' +inline constexpr char ReponseHeaderCelExprString[] = R"pb( + expr { + id: 8 + call_expr { + function: "_==_" + args { + id: 6 + call_expr { + function: "_[_]" + args { + id: 5 + select_expr { + operand { + id: 4 + ident_expr {name: "response"} + } + field: "headers" + } + } + args { + id: 7 + const_expr { + string_value: "content-type" + } + } + } + } + args { + id: 9 + const_expr { string_value: "text/plain" } + } + } + } +)pb"; + +// Compiled CEL expression string: request.path == '/foo' && request.headers['user'] == +// 'staging'. +// Note, source_info is not required for evaluation process that happens in data plane, which is +// confirmed by test cases above. However, it will be included as part of result from parsing and +// checking process passed to data plane. Thus, the entire compiled CEL result is also tested. +inline constexpr char RequestHeaderAndPathCelString[] = R"pb( + expr { + id: 11 + call_expr { + function: "_&&_" + args { + id: 3 + call_expr { + function: "_==_" + args { + id: 2 + select_expr { + operand { + id: 1 + ident_expr { + name: "request" + } + } + field: "path" + } + } + args { + id: 4 + const_expr { + string_value: "/foo" + } + } + } + } + args { + id: 9 + call_expr { + function: "_==_" + args { + id: 7 + call_expr { + function: "_[_]" + args { + id: 6 + select_expr { + operand { + id: 5 + ident_expr { + name: "request" + } + } + field: "headers" + } + } + args { + id: 8 + const_expr { + string_value: "user" + } + } + } + } + args { + id: 10 + const_expr { + string_value: "staging" + } + } + } + } + } + } + source_info { + location: "" + line_offsets: 57 + positions { + key: 1 + value: 0 + } + positions { + key: 2 + value: 7 + } + positions { + key: 3 + value: 12 + } + positions { + key: 4 + value: 14 + } + positions { + key: 5 + value: 22 + } + positions { + key: 6 + value: 29 + } + positions { + key: 7 + value: 37 + } + positions { + key: 8 + value: 38 + } + positions { + key: 9 + value: 45 + } + positions { + key: 10 + value: 47 + } + positions { + key: 11 + value: 20 + } + } +)pb"; + +// Compiled CEL expression string: response.trailers['transfer-encoding']=='chunked' +inline constexpr char ReponseTrailerCelExprString[] = R"pb( + expr { + id: 5 + call_expr { + function: "_==_" + args { + id: 3 + call_expr { + function: "_[_]" + args { + id: 2 + select_expr { + operand { + id: 1 + ident_expr { + name: "response" + } + } + field: "trailers" + } + } + args { + id: 4 + const_expr { + string_value: "transfer-encoding" + } + } + } + } + args { + id: 6 + const_expr { + string_value: "chunked" + } + } + } + } +)pb"; + +// Compiled CEL expression string: request.path == '/foo' || request.headers['user'] == +// 'staging'. +inline constexpr char RequestHeaderOrPathCelString[] = R"pb( + expr { + id: 11 + call_expr { + function: "_||_" + args { + id: 3 + call_expr { + function: "_==_" + args { + id: 2 + select_expr { + operand { + id: 1 + ident_expr { + name: "request" + } + } + field: "path" + } + } + args { + id: 4 + const_expr { + string_value: "/foo" + } + } + } + } + args { + id: 9 + call_expr { + function: "_==_" + args { + id: 7 + call_expr { + function: "_[_]" + args { + id: 6 + select_expr { + operand { + id: 5 + ident_expr { + name: "request" + } + } + field: "headers" + } + } + args { + id: 8 + const_expr { + string_value: "user" + } + } + } + } + args { + id: 10 + const_expr { + string_value: "staging" + } + } + } + } + } + } +)pb"; + +// request.headers['user']=='staging'&&response.headers['content-type']=='text/plain'&&response.trailers['transfer-encoding']=='chunked' +inline constexpr char RequestAndResponseCelString[] = R"pb( + expr { + id: 20 + call_expr { + function: "_&&_" + args { + id: 13 + call_expr { + function: "_&&_" + args { + id: 5 + call_expr { + function: "_==_" + args { + id: 3 + call_expr { + function: "_[_]" + args { + id: 2 + select_expr { + operand { + id: 1 + ident_expr { + name: "request" + } + } + field: "headers" + } + } + args { + id: 4 + const_expr { + string_value: "user" + } + } + } + } + args { + id: 6 + const_expr { + string_value: "staging" + } + } + } + } + args { + id: 11 + call_expr { + function: "_==_" + args { + id: 9 + call_expr { + function: "_[_]" + args { + id: 8 + select_expr { + operand { + id: 7 + ident_expr { + name: "response" + } + } + field: "headers" + } + } + args { + id: 10 + const_expr { + string_value: "content-type" + } + } + } + } + args { + id: 12 + const_expr { + string_value: "text/plain" + } + } + } + } + } + } + args { + id: 18 + call_expr { + function: "_==_" + args { + id: 16 + call_expr { + function: "_[_]" + args { + id: 15 + select_expr { + operand { + id: 14 + ident_expr { + name: "response" + } + } + field: "trailers" + } + } + args { + id: 17 + const_expr { + string_value: "transfer-encoding" + } + } + } + } + args { + id: 19 + const_expr { + string_value: "chunked" + } + } + } + } + } + } + source_info { + location: "" + line_offsets: 134 + positions { + key: 1 + value: 0 + } + positions { + key: 2 + value: 7 + } + positions { + key: 3 + value: 15 + } + positions { + key: 4 + value: 16 + } + positions { + key: 5 + value: 23 + } + positions { + key: 6 + value: 25 + } + positions { + key: 7 + value: 36 + } + positions { + key: 8 + value: 44 + } + positions { + key: 9 + value: 52 + } + positions { + key: 10 + value: 53 + } + positions { + key: 11 + value: 68 + } + positions { + key: 12 + value: 70 + } + positions { + key: 13 + value: 34 + } + positions { + key: 14 + value: 84 + } + positions { + key: 15 + value: 92 + } + positions { + key: 16 + value: 101 + } + positions { + key: 17 + value: 102 + } + positions { + key: 18 + value: 122 + } + positions { + key: 19 + value: 124 + } + positions { + key: 20 + value: 82 + } + } +)pb"; + +} // namespace CelMatcher +} // namespace InputMatchers +} // namespace Matching +} // namespace Extensions +} // namespace Envoy diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index 3c31ef8fed8a..e26c99615b49 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -83,6 +83,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/config_subscription/rest:94.3" "source/extensions/config_subscription:94.8" "source/extensions/config_subscription/grpc:94.0" +"source/extensions/matching/input_matchers/cel_matcher:90.7" #Death tests don't report LCOV ) [[ -z "${SRCDIR}" ]] && SRCDIR="${PWD}" diff --git a/tools/extensions/extensions_schema.yaml b/tools/extensions/extensions_schema.yaml index 030939c667b9..6262a972cd70 100644 --- a/tools/extensions/extensions_schema.yaml +++ b/tools/extensions/extensions_schema.yaml @@ -11,6 +11,7 @@ builtin: - envoy.matching.inputs.response_headers - envoy.matching.inputs.response_trailers - envoy.matching.inputs.query_params +- envoy.matching.inputs.cel_data_input - envoy.matching.inputs.destination_ip - envoy.matching.inputs.destination_port - envoy.matching.inputs.source_ip From 7e6031d2a16210660b01531b54bc2dc14b1b6e61 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 31 May 2023 19:56:34 +0100 Subject: [PATCH 143/228] ci/mobile: Set build images in one place (#27733) Signed-off-by: Ryan Northey --- .github/workflows/env.yml | 49 +++++++++++++++------- .github/workflows/mobile-android_build.yml | 2 +- .github/workflows/mobile-android_tests.yml | 2 +- .github/workflows/mobile-asan.yml | 2 +- .github/workflows/mobile-cc_tests.yml | 2 +- .github/workflows/mobile-core.yml | 8 +++- .github/workflows/mobile-coverage.yml | 2 +- .github/workflows/mobile-docs.yml | 8 +++- .github/workflows/mobile-format.yml | 2 +- .github/workflows/mobile-perf.yml | 6 +-- .github/workflows/mobile-tsan.yml | 2 +- .github/workflows/mobile_release.yml | 2 +- 12 files changed, 60 insertions(+), 27 deletions(-) diff --git a/.github/workflows/env.yml b/.github/workflows/env.yml index a0caaa67cfb6..27149302a3d6 100644 --- a/.github/workflows/env.yml +++ b/.github/workflows/env.yml @@ -3,42 +3,48 @@ name: Environment on: workflow_call: outputs: + build_image_ubuntu: + value: ${{ jobs.repo.outputs.build_image_ubuntu }} + build_image_ubuntu_mobile: + value: ${{ jobs.repo.outputs.build_image_ubuntu_mobile }} mobile_android_build: - value: ${{ jobs.mobile.outputs.mobile_android_build }} + value: ${{ jobs.repo.outputs.mobile_android_build }} mobile_android_build_all: - value: ${{ jobs.mobile.outputs.mobile_android_build_all }} + value: ${{ jobs.repo.outputs.mobile_android_build_all }} mobile_android_tests: - value: ${{ jobs.mobile.outputs.mobile_android_tests }} + value: ${{ jobs.repo.outputs.mobile_android_tests }} mobile_asan: - value: ${{ jobs.mobile.outputs.mobile_asan }} + value: ${{ jobs.repo.outputs.mobile_asan }} mobile_cc_tests: - value: ${{ jobs.mobile.outputs.mobile_cc_tests }} + value: ${{ jobs.repo.outputs.mobile_cc_tests }} mobile_compile_time_options: - value: ${{ jobs.mobile.outputs.mobile_compile_time_options }} + value: ${{ jobs.repo.outputs.mobile_compile_time_options }} mobile_coverage: - value: ${{ jobs.mobile.outputs.mobile_coverage }} + value: ${{ jobs.repo.outputs.mobile_coverage }} mobile_formatting: - value: ${{ jobs.mobile.outputs.mobile_formatting }} + value: ${{ jobs.repo.outputs.mobile_formatting }} mobile_ios_build: - value: ${{ jobs.mobile.outputs.mobile_ios_build }} + value: ${{ jobs.repo.outputs.mobile_ios_build }} mobile_ios_build_all: - value: ${{ jobs.mobile.outputs.mobile_ios_build_all }} + value: ${{ jobs.repo.outputs.mobile_ios_build_all }} mobile_ios_tests: - value: ${{ jobs.mobile.outputs.mobile_ios_tests }} + value: ${{ jobs.repo.outputs.mobile_ios_tests }} mobile_release_validation: - value: ${{ jobs.mobile.outputs.mobile_release_validation }} + value: ${{ jobs.repo.outputs.mobile_release_validation }} mobile_tsan: - value: ${{ jobs.mobile.outputs.mobile_tsan }} + value: ${{ jobs.repo.outputs.mobile_tsan }} concurrency: group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }}-env cancel-in-progress: true jobs: - mobile: + repo: if: github.repository == 'envoyproxy/envoy' runs-on: ubuntu-20.04 outputs: + build_image_ubuntu: ${{ steps.build_image.outputs.build_image_ubuntu }} + build_image_ubuntu_mobile: ${{ steps.build_image.outputs.build_image_ubuntu_mobile }} mobile_android_build: ${{ steps.should_run.outputs.mobile_android_build }} mobile_android_build_all: ${{ steps.should_run.outputs.mobile_android_build_all }} mobile_android_tests: ${{ steps.should_run.outputs.mobile_android_tests }} @@ -58,6 +64,21 @@ jobs: fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy + + - id: build_image + name: 'Check current build images' + run: | + { + echo "build_image_ubuntu=${BUILD_IMAGE_UBUNTU_REPO}:${BUILD_IMAGE_UBUNTU}@sha256:${BUILD_IMAGE_UBUNTU_SHA}" + echo "build_image_ubuntu_mobile=${BUILD_IMAGE_UBUNTU_REPO}:mobile-${BUILD_IMAGE_UBUNTU}@sha256:${BUILD_IMAGE_UBUNTU_MOBILE_SHA}" + } >> "$GITHUB_OUTPUT" + env: + # TODO(phlax): derive these from a config file + BUILD_IMAGE_UBUNTU_REPO: envoyproxy/envoy-build-ubuntu + BUILD_IMAGE_UBUNTU: 41c5a05d708972d703661b702a63ef5060125c33 + BUILD_IMAGE_UBUNTU_SHA: 50337314a150ed12447c87c1622eac6f611a069888722fb9a426e21ed161cc26 + BUILD_IMAGE_UBUNTU_MOBILE_SHA: ca26ff05bd3f3a09468242faaf38ae48315e57f0a87c102352162f95ac620e6f + - id: should_run name: 'Check what to run' run: | diff --git a/.github/workflows/mobile-android_build.yml b/.github/workflows/mobile-android_build.yml index 8f5c71a7d978..f791676c9084 100644 --- a/.github/workflows/mobile-android_build.yml +++ b/.github/workflows/mobile-android_build.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu_mobile }} env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile-android_tests.yml b/.github/workflows/mobile-android_tests.yml index 9baf8b9922a7..93129f5b9e86 100644 --- a/.github/workflows/mobile-android_tests.yml +++ b/.github/workflows/mobile-android_tests.yml @@ -83,7 +83,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu_mobile }} env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile-asan.yml b/.github/workflows/mobile-asan.yml index e5a9378c262e..e6e72fcb3967 100644 --- a/.github/workflows/mobile-asan.yml +++ b/.github/workflows/mobile-asan.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 180 container: - image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu_mobile }} env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile-cc_tests.yml b/.github/workflows/mobile-cc_tests.yml index c824fc8f6ece..99e1951fde1b 100644 --- a/.github/workflows/mobile-cc_tests.yml +++ b/.github/workflows/mobile-cc_tests.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} steps: - uses: actions/checkout@v3 - name: Add safe directory diff --git a/.github/workflows/mobile-core.yml b/.github/workflows/mobile-core.yml index 7c111e04a88b..31383adf4752 100644 --- a/.github/workflows/mobile-core.yml +++ b/.github/workflows/mobile-core.yml @@ -11,13 +11,19 @@ concurrency: cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + unittests: if: ${{ github.repository == 'envoyproxy/envoy' }} + needs: env name: unit_tests runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} steps: - uses: actions/checkout@v3 - name: Ensure no listener leaks diff --git a/.github/workflows/mobile-coverage.yml b/.github/workflows/mobile-coverage.yml index 8ff027449a9e..f628f2d62134 100644 --- a/.github/workflows/mobile-coverage.yml +++ b/.github/workflows/mobile-coverage.yml @@ -26,7 +26,7 @@ jobs: run: shell: bash container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} steps: - uses: actions/checkout@v3 - name: Add safe directory diff --git a/.github/workflows/mobile-docs.yml b/.github/workflows/mobile-docs.yml index 093b5f29740c..31554d189288 100644 --- a/.github/workflows/mobile-docs.yml +++ b/.github/workflows/mobile-docs.yml @@ -11,12 +11,18 @@ concurrency: cancel-in-progress: true jobs: + env: + if: ${{ github.repository == 'envoyproxy/envoy' }} + uses: ./.github/workflows/env.yml + secrets: inherit + docs: if: ${{ github.repository == 'envoyproxy/envoy' }} + needs: env runs-on: ubuntu-20.04 timeout-minutes: 20 container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} steps: - uses: actions/checkout@v3 - name: Add safe directory diff --git a/.github/workflows/mobile-format.yml b/.github/workflows/mobile-format.yml index ac48d4308063..54b57cddbcf4 100644 --- a/.github/workflows/mobile-format.yml +++ b/.github/workflows/mobile-format.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 45 container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} env: CLANG_FORMAT: /opt/llvm/bin/clang-format BUILDIFIER_BIN: /usr/local/bin/buildifier diff --git a/.github/workflows/mobile-perf.yml b/.github/workflows/mobile-perf.yml index b1c142bf2c1b..9da97dbb0016 100644 --- a/.github/workflows/mobile-perf.yml +++ b/.github/workflows/mobile-perf.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ @@ -76,7 +76,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 30 container: - image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu }} steps: - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 diff --git a/.github/workflows/mobile-tsan.yml b/.github/workflows/mobile-tsan.yml index 918613f15146..713e9a27d720 100644 --- a/.github/workflows/mobile-tsan.yml +++ b/.github/workflows/mobile-tsan.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 90 container: - image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu_mobile }} env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ diff --git a/.github/workflows/mobile_release.yml b/.github/workflows/mobile_release.yml index df91222186e8..e2f6f7b947b6 100644 --- a/.github/workflows/mobile_release.yml +++ b/.github/workflows/mobile_release.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:mobile-41c5a05d708972d703661b702a63ef5060125c33 + image: ${{ needs.env.outputs.build_image_ubuntu_mobile }} env: CC: /opt/llvm/bin/clang CXX: /opt/llvm/bin/clang++ From 842c20238440f88f33167e4bc024e2e113cbb0e8 Mon Sep 17 00:00:00 2001 From: Kevin Baichoo Date: Wed, 31 May 2023 15:07:43 -0400 Subject: [PATCH 144/228] Overload Manager: Validate configured overload actions. (#27711) Validate configured actions to prevent silent failures. Signed-off-by: Kevin Baichoo --- changelogs/current.yaml | 7 ++ envoy/server/overload/overload_manager.h | 11 +++ source/common/runtime/runtime_features.cc | 1 + source/server/overload_manager_impl.cc | 11 +++ test/server/overload_manager_impl_test.cc | 95 ++++++++++++++++------- 5 files changed, 96 insertions(+), 29 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 3db18423ae73..478fd07c9b7e 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -70,6 +70,13 @@ minor_behavior_changes: the cookie is still accepted, but is planned to be obsoleted in the future. This behavior change can be reverted by setting ``envoy.reloadable_features.stateful_session_encode_ttl_in_cookie`` to ``false``. +- area: overload manager + change: | + Changed behavior of the overload manager to error on unknown overload + manager actions. Prior it would silently fail. This change can be reverted + temporarily by setting the runtime guard + ``envoy.reloadable_features.overload_manager_error_unknown_action`` to + false. - area: router change: | Added check for existing metadata before setting metadata due to 'auto_sni', 'auto_san_validation', or diff --git a/envoy/server/overload/overload_manager.h b/envoy/server/overload/overload_manager.h index f65163c0ad15..bc71798a5ac8 100644 --- a/envoy/server/overload/overload_manager.h +++ b/envoy/server/overload/overload_manager.h @@ -38,6 +38,17 @@ class OverloadActionNameValues { // Overload action to reset streams using excessive memory. const std::string ResetStreams = "envoy.overload_actions.reset_high_memory_stream"; + + // This should be kept current with the Overload actions available. + // This is the last member of this class to duplicating the strings with + // proper lifetime guarantees. + const std::array WellKnownActions = {StopAcceptingRequests, + DisableHttpKeepAlive, + StopAcceptingConnections, + RejectIncomingConnections, + ShrinkHeap, + ReduceTimeouts, + ResetStreams}; }; using OverloadActionNames = ConstSingleton; diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 5d6d318e0b55..0571c4ef20fe 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -59,6 +59,7 @@ RUNTIME_GUARD(envoy_reloadable_features_oauth_make_token_cookie_httponly); RUNTIME_GUARD(envoy_reloadable_features_oauth_use_standard_max_age_value); RUNTIME_GUARD(envoy_reloadable_features_oauth_use_url_encoding); RUNTIME_GUARD(envoy_reloadable_features_original_dst_rely_on_idle_timeout); +RUNTIME_GUARD(envoy_reloadable_features_overload_manager_error_unknown_action); RUNTIME_GUARD(envoy_reloadable_features_prohibit_route_refresh_after_response_headers_sent); RUNTIME_GUARD(envoy_reloadable_features_quic_defer_logging_to_ack_listener); RUNTIME_GUARD(envoy_reloadable_features_reject_require_client_certificate_with_quic); diff --git a/source/server/overload_manager_impl.cc b/source/server/overload_manager_impl.cc index e277abd50b43..0eea1311f14f 100644 --- a/source/server/overload_manager_impl.cc +++ b/source/server/overload_manager_impl.cc @@ -413,6 +413,17 @@ OverloadManagerImpl::OverloadManagerImpl(Event::Dispatcher& dispatcher, Stats::S const auto& name = action.name(); const auto symbol = action_symbol_table_.get(name); ENVOY_LOG(debug, "Adding overload action {}", name); + + // Validate that this is a well known overload action. + if (Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.overload_manager_error_unknown_action")) { + auto& well_known_actions = OverloadActionNames::get().WellKnownActions; + if (std::find(well_known_actions.begin(), well_known_actions.end(), name) == + well_known_actions.end()) { + throw EnvoyException(absl::StrCat("Unknown Overload Manager Action ", name)); + } + } + // TODO: use in place construction once https://github.com/abseil/abseil-cpp/issues/388 is // addressed // We cannot currently use in place construction as the OverloadAction constructor may throw, diff --git a/test/server/overload_manager_impl_test.cc b/test/server/overload_manager_impl_test.cc index b43e8f41c388..081f66f6dc44 100644 --- a/test/server/overload_manager_impl_test.cc +++ b/test/server/overload_manager_impl_test.cc @@ -262,7 +262,7 @@ constexpr char kRegularStateConfig[] = R"YAML( - name: envoy.resource_monitors.fake_resource3 - name: envoy.resource_monitors.fake_resource4 actions: - - name: envoy.overload_actions.dummy_action + - name: envoy.overload_actions.stop_accepting_requests triggers: - name: envoy.resource_monitors.fake_resource1 threshold: @@ -287,7 +287,7 @@ constexpr char proactiveResourceConfig[] = R"YAML( - name: envoy.resource_monitors.fake_resource1 - name: envoy.resource_monitors.global_downstream_max_connections actions: - - name: envoy.overload_actions.dummy_action + - name: envoy.overload_actions.shrink_heap triggers: - name: envoy.resource_monitors.fake_resource1 threshold: @@ -300,11 +300,13 @@ TEST_F(OverloadManagerImplTest, CallbackOnlyFiresWhenStateChanges) { auto manager(createOverloadManager(kRegularStateConfig)); bool is_active = false; int cb_count = 0; - manager->registerForAction("envoy.overload_actions.dummy_action", dispatcher_, + manager->registerForAction("envoy.overload_actions.stop_accepting_requests", dispatcher_, [&](OverloadActionState state) { is_active = state.isSaturated(); cb_count++; }); + // This overload action callback should never be fired as the action is + // unknown and unconfigured to a trigger. manager->registerForAction("envoy.overload_actions.unknown_action", dispatcher_, [&](OverloadActionState) { EXPECT_TRUE(false); }); manager->start(); @@ -312,10 +314,11 @@ TEST_F(OverloadManagerImplTest, CallbackOnlyFiresWhenStateChanges) { EXPECT_FALSE(manager->getThreadLocalOverloadState().isResourceMonitorEnabled( OverloadProactiveResourceName::GlobalDownstreamMaxConnections)); - Stats::Gauge& active_gauge = stats_.gauge("overload.envoy.overload_actions.dummy_action.active", - Stats::Gauge::ImportMode::Accumulate); + Stats::Gauge& active_gauge = + stats_.gauge("overload.envoy.overload_actions.stop_accepting_requests.active", + Stats::Gauge::ImportMode::Accumulate); Stats::Gauge& scale_percent_gauge = - stats_.gauge("overload.envoy.overload_actions.dummy_action.scale_percent", + stats_.gauge("overload.envoy.overload_actions.stop_accepting_requests.scale_percent", Stats::Gauge::ImportMode::Accumulate); Stats::Gauge& pressure_gauge1 = stats_.gauge("overload.envoy.resource_monitors.fake_resource1.pressure", @@ -323,8 +326,8 @@ TEST_F(OverloadManagerImplTest, CallbackOnlyFiresWhenStateChanges) { Stats::Gauge& pressure_gauge2 = stats_.gauge("overload.envoy.resource_monitors.fake_resource2.pressure", Stats::Gauge::ImportMode::NeverImport); - const OverloadActionState& action_state = - manager->getThreadLocalOverloadState().getState("envoy.overload_actions.dummy_action"); + const OverloadActionState& action_state = manager->getThreadLocalOverloadState().getState( + "envoy.overload_actions.stop_accepting_requests"); // Update does not exceed fake_resource1 trigger threshold, no callback expected factory1_.monitor_->setPressure(0.5); @@ -410,12 +413,13 @@ TEST_F(OverloadManagerImplTest, ScaledTrigger) { auto manager(createOverloadManager(kRegularStateConfig)); manager->start(); - const auto& action_state = - manager->getThreadLocalOverloadState().getState("envoy.overload_actions.dummy_action"); - Stats::Gauge& active_gauge = stats_.gauge("overload.envoy.overload_actions.dummy_action.active", - Stats::Gauge::ImportMode::Accumulate); + const auto& action_state = manager->getThreadLocalOverloadState().getState( + "envoy.overload_actions.stop_accepting_requests"); + Stats::Gauge& active_gauge = + stats_.gauge("overload.envoy.overload_actions.stop_accepting_requests.active", + Stats::Gauge::ImportMode::Accumulate); Stats::Gauge& scale_percent_gauge = - stats_.gauge("overload.envoy.overload_actions.dummy_action.scale_percent", + stats_.gauge("overload.envoy.overload_actions.stop_accepting_requests.scale_percent", Stats::Gauge::ImportMode::Accumulate); factory3_.monitor_->setPressure(0.5); @@ -471,8 +475,8 @@ TEST_F(OverloadManagerImplTest, AggregatesMultipleResourceUpdates) { auto manager(createOverloadManager(kRegularStateConfig)); manager->start(); - const OverloadActionState& action_state = - manager->getThreadLocalOverloadState().getState("envoy.overload_actions.dummy_action"); + const OverloadActionState& action_state = manager->getThreadLocalOverloadState().getState( + "envoy.overload_actions.stop_accepting_requests"); factory1_.monitor_->setUpdateAsync(true); @@ -493,8 +497,8 @@ TEST_F(OverloadManagerImplTest, DelayedUpdatesAreCoalesced) { auto manager(createOverloadManager(kRegularStateConfig)); manager->start(); - const OverloadActionState& action_state = - manager->getThreadLocalOverloadState().getState("envoy.overload_actions.dummy_action"); + const OverloadActionState& action_state = manager->getThreadLocalOverloadState().getState( + "envoy.overload_actions.stop_accepting_requests"); factory3_.monitor_->setUpdateAsync(true); factory4_.monitor_->setUpdateAsync(true); @@ -517,8 +521,8 @@ TEST_F(OverloadManagerImplTest, FlushesUpdatesEvenWithOneUnresponsive) { auto manager(createOverloadManager(kRegularStateConfig)); manager->start(); - const OverloadActionState& action_state = - manager->getThreadLocalOverloadState().getState("envoy.overload_actions.dummy_action"); + const OverloadActionState& action_state = manager->getThreadLocalOverloadState().getState( + "envoy.overload_actions.stop_accepting_requests"); // Set monitor 1 to async, but never publish updates for it. factory1_.monitor_->setUpdateAsync(true); @@ -662,8 +666,8 @@ TEST_F(OverloadManagerImplTest, DuplicateProactiveResourceMonitor) { TEST_F(OverloadManagerImplTest, DuplicateOverloadAction) { const std::string config = R"EOF( actions: - - name: "envoy.overload_actions.dummy_action" - - name: "envoy.overload_actions.dummy_action" + - name: "envoy.overload_actions.shrink_heap" + - name: "envoy.overload_actions.shrink_heap" )EOF"; EXPECT_THROW_WITH_REGEX(createOverloadManager(config), EnvoyException, @@ -673,7 +677,7 @@ TEST_F(OverloadManagerImplTest, DuplicateOverloadAction) { TEST_F(OverloadManagerImplTest, ActionWithUnexpectedTypedConfig) { const std::string config = R"EOF( actions: - - name: "envoy.overload_actions.dummy_action" + - name: "envoy.overload_actions.shrink_heap" typed_config: "@type": type.googleapis.com/google.protobuf.Empty )EOF"; @@ -722,7 +726,7 @@ TEST_F(OverloadManagerImplTest, ScaledTriggerSaturationLessThanScalingThreshold) resource_monitors: - name: "envoy.resource_monitors.fake_resource1" actions: - - name: "envoy.overload_actions.dummy_action" + - name: "envoy.overload_actions.shrink_heap" triggers: - name: "envoy.resource_monitors.fake_resource1" scaled: @@ -740,7 +744,7 @@ TEST_F(OverloadManagerImplTest, ScaledTriggerThresholdsEqual) { resource_monitors: - name: "envoy.resource_monitors.fake_resource1" actions: - - name: "envoy.overload_actions.dummy_action" + - name: "envoy.overload_actions.shrink_heap" triggers: - name: "envoy.resource_monitors.fake_resource1" scaled: @@ -752,10 +756,43 @@ TEST_F(OverloadManagerImplTest, ScaledTriggerThresholdsEqual) { "scaling_threshold must be less than saturation_threshold.*"); } +TEST_F(OverloadManagerImplTest, UnknownActionShouldError) { + const std::string config = R"EOF( + resource_monitors: + - name: "envoy.resource_monitors.fake_resource1" + actions: + - name: "envoy.overload_actions.not_a_valid_action" + triggers: + - name: "envoy.resource_monitors.fake_resource1" + threshold: + value: 0.9 + )EOF"; + + EXPECT_THROW_WITH_REGEX(createOverloadManager(config), EnvoyException, + "Unknown Overload Manager Action .*"); +} + +TEST_F(OverloadManagerImplTest, LegacyUnknownActionShouldSilentlyFail) { + scoped_runtime_.mergeValues( + {{"envoy.reloadable_features.overload_manager_error_unknown_action", "false"}}); + const std::string config = R"EOF( + resource_monitors: + - name: "envoy.resource_monitors.fake_resource1" + actions: + - name: "envoy.overload_actions.not_a_valid_action" + triggers: + - name: "envoy.resource_monitors.fake_resource1" + threshold: + value: 0.9 + )EOF"; + + auto overload_manager = createOverloadManager(config); +} + TEST_F(OverloadManagerImplTest, UnknownTrigger) { const std::string config = R"EOF( actions: - - name: "envoy.overload_actions.dummy_action" + - name: "envoy.overload_actions.shrink_heap" triggers: - name: "envoy.resource_monitors.fake_resource1" threshold: @@ -771,7 +808,7 @@ TEST_F(OverloadManagerImplTest, DuplicateTrigger) { resource_monitors: - name: "envoy.resource_monitors.fake_resource1" actions: - - name: "envoy.overload_actions.dummy_action" + - name: "envoy.overload_actions.shrink_heap" triggers: - name: "envoy.resource_monitors.fake_resource1" threshold: @@ -807,7 +844,7 @@ TEST_F(OverloadManagerImplTest, Shutdown) { TEST_F(OverloadManagerImplTest, MissingConfigTriggerType) { constexpr char missingTriggerTypeConfig[] = R"YAML( actions: - - name: envoy.overload_actions.dummy_action + - name: envoy.overload_actions.shrink_heap triggers: - name: envoy.resource_monitors.fake_resource1 )YAML"; @@ -1048,7 +1085,7 @@ TEST_F(OverloadManagerLoadShedPointImplTest, LoadShedPointShouldUseCurrentReadin scaling_threshold: 0.5 saturation_threshold: 1.0 actions: - - name: envoy.overload_actions.dummy_action + - name: envoy.overload_actions.shrink_heap triggers: - name: envoy.resource_monitors.fake_resource1 scaled: @@ -1062,7 +1099,7 @@ TEST_F(OverloadManagerLoadShedPointImplTest, LoadShedPointShouldUseCurrentReadin std::vector overload_action_states; manager->registerForAction( - "envoy.overload_actions.dummy_action", *other_dispatcher, + "envoy.overload_actions.shrink_heap", *other_dispatcher, [&](OverloadActionState state) { overload_action_states.push_back(state.value()); }); manager->start(); From d4ce0e93af517d388dce5b398f123e9d03121a1d Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 31 May 2023 16:19:49 -0400 Subject: [PATCH 145/228] mobile: compile time options fix (#27732) reinstating compile time options build (broken by bad yaml) removing linux !h3 tests as we have swift e2e. I could add it to the kotlin build if we have concerns otherwise moving linux compile time options build to mimic common test options, and simplifying down to client integration test (avoid a bunch of flakey android deps and macos constraints) now that the client integration test works. Signed-off-by: Alyssa Wilk --- .../workflows/mobile-compile_time_options.yml | 33 ++++--------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/.github/workflows/mobile-compile_time_options.yml b/.github/workflows/mobile-compile_time_options.yml index ae6b82e4ec57..c6c246432436 100644 --- a/.github/workflows/mobile-compile_time_options.yml +++ b/.github/workflows/mobile-compile_time_options.yml @@ -23,43 +23,22 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 120 container: - image: envoyproxy/envoy-build-ubuntu:b0ff77ae3f25b0bf595f9b8bba46b489723ab446 + image: envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 steps: - uses: actions/checkout@v3 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - name: 'Build C++ library' + - name: 'Building C++ library' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Envoy Mobile build which verifies that the build configuration where YAML is disabled. run: | - # Envoy Mobile build which verifies that the build configuration where HTTP/3 is enabled and - # HTTP Datagrams are disabled works. - cd mobile - ./bazelw test \ + cd mobile && ./bazelw test \ $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-linux") \ - --define=signal_trace=disabled \ - --define=admin_html=enabled \ - --define=envoy_mobile_request_compression=disabled \ - --define=envoy_enable_http_datagrams=disabled \ - --define=google_grpc=disabled \ - --@envoy//bazel:http3=False \ - --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ - //test/cc/... - # Envoy Mobile build which verifies that the build configuration where YAML is disabled. - ./bazelw test \ - $([ -z $GITHUB_TOKEN ] || echo "--config=remote-ci-macos") \ --config=ci \ - --fat_apk_cpu=x86_64 \ - --define=signal_trace=disabled \ - --define=envoy_mobile_request_compression=disabled \ - --define=envoy_enable_http_datagrams=disabled \ - --define=google_grpc=disabled \ --define=envoy_yaml=disabled \ - --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor= \ - //test/java/integration:android_engine_socket_tag_test \ - //test/java/integration:android_engine_start_test \ - //test/java/io/envoyproxy/envoymobile/utilities:certificate_verification_tests \ - //test/common/integration:client_integration_test + --test_env=ENVOY_IP_TEST_VERSIONS=v4only \ + //test/common/integration:client_integration_test --test_output=all swift_build: if: ${{ needs.env.outputs.mobile_compile_time_options == 'true' }} needs: env From 9ecf7611bdace7d7ff77959fdb607b59012c6a6d Mon Sep 17 00:00:00 2001 From: code Date: Thu, 1 Jun 2023 10:07:38 +0800 Subject: [PATCH 146/228] router: deprecate optional http filters and add route/vh level `is_optional` support in the typed_per_filter_config (#27263) * router: remove optional http filters because it's hcm dependent Signed-off-by: wbpcode * Revert "router: remove optional http filters because it's hcm dependent" This reverts commit 1725ce7d259d8586b0ba298e7e9a50953163fa73. Signed-off-by: wbpcode * add runtime guard/tests/change log Signed-off-by: wbpcode * fix more test Signed-off-by: wbpcode * add route/virual host level optional flag support and test and change log Signed-off-by: wbpcode * fix format Signed-off-by: wbpcode * fix docs Signed-off-by: wbpcode * fix test Signed-off-by: wbpcode * Update changelogs/current.yaml Co-authored-by: Adi (Suissa) Peleg Signed-off-by: code * address all comments Signed-off-by: wbpcode * fix conflict Signed-off-by: wbpcode * address comment Signed-off-by: wbpcode * address comments Signed-off-by: wbpcode * fix test and add new test to cover the new exception throwing Signed-off-by: wbpcode --------- Signed-off-by: wbpcode Signed-off-by: code Co-authored-by: Adi (Suissa) Peleg --- .../config/route/v3/route_components.proto | 3 +- .../v3/http_connection_manager.proto | 1 - changelogs/current.yaml | 18 +++ source/common/router/config_impl.cc | 57 ++++++-- source/common/router/config_impl.h | 3 +- source/common/runtime/runtime_features.cc | 1 + test/common/router/BUILD | 2 + test/common/router/config_impl_test.cc | 137 +++++++++++++++++- test/common/router/rds_impl_test.cc | 116 ++++++++++++++- test/common/router/scoped_rds_test.cc | 6 + .../http_typed_per_filter_config_test.cc | 30 +++- .../scoped_rds_integration_test.cc | 4 + 12 files changed, 361 insertions(+), 17 deletions(-) diff --git a/api/envoy/config/route/v3/route_components.proto b/api/envoy/config/route/v3/route_components.proto index a38bdccac97b..56686a096050 100644 --- a/api/envoy/config/route/v3/route_components.proto +++ b/api/envoy/config/route/v3/route_components.proto @@ -2376,7 +2376,6 @@ message InternalRedirectPolicy { // :ref:`Route.typed_per_filter_config`, // or :ref:`WeightedCluster.ClusterWeight.typed_per_filter_config` // to add additional flags to the filter. -// [#not-implemented-hide:] message FilterConfig { // The filter config. google.protobuf.Any config = 1; @@ -2398,5 +2397,7 @@ message FilterConfig { // created and it is too late to change the chain. // // This field only make sense for the downstream HTTP filters for now. + // + // [#not-implemented-hide:] bool disabled = 3; } diff --git a/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto b/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto index 041db6ff60bf..f86be41f0493 100644 --- a/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto +++ b/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto @@ -1145,7 +1145,6 @@ message HttpFilter { // If true, clients that do not support this filter may ignore the // filter but otherwise accept the config. // Otherwise, clients that do not support this filter must reject the config. - // This is also same with typed per filter config. bool is_optional = 6; } diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 478fd07c9b7e..c6eff7753bf3 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -113,6 +113,18 @@ bug_fixes: Fixed the bug that updating :ref:`scope_key_builder ` of SRDS config doesn't work and multiple HCM share the same ``scope_key_builder``. +- area: http + change: | + The :ref:`is_optional + ` + field of HTTP filter can only be used for configuration loading of + :ref:`HTTP filter ` + and will be ignored for loading of route or virtual host level filter config. This behavioral change + can be temporarily reverted by setting runtime guard + ``envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config`` to false. + You can also use + :ref:`route/virtual host optional flag ` + as a replacement of the feature. - area: logging change: | Do not display GRPC_STATUS_NUMBER for non gRPC requests. @@ -245,6 +257,12 @@ new_features: - area: admin change: | Adds a new admin stats html bucket-mode ``detailed`` to generate all recorded buckets and summary percentiles. +- area: http + change: | + Add support to the route/virtual host level + :ref:`is_optional ` field. + A route/virtual host level per filter config can be marked as optional, which means that if + the filter fails to load, the configuration will no be rejected. - area: upstream change: | Added :ref:`cluster provided extension diff --git a/source/common/router/config_impl.cc b/source/common/router/config_impl.cc index 014920a35bcd..e854bd3507b6 100644 --- a/source/common/router/config_impl.cc +++ b/source/common/router/config_impl.cc @@ -2104,11 +2104,10 @@ RouteConstSharedPtr ConfigImpl::route(const RouteCallback& cb, } RouteSpecificFilterConfigConstSharedPtr PerFilterConfigs::createRouteSpecificFilterConfig( - const std::string& name, const ProtobufWkt::Any& typed_config, - const OptionalHttpFilters& optional_http_filters, + const std::string& name, const ProtobufWkt::Any& typed_config, bool is_optional, Server::Configuration::ServerFactoryContext& factory_context, ProtobufMessage::ValidationVisitor& validator) { - bool is_optional = (optional_http_filters.find(name) != optional_http_filters.end()); + Server::Configuration::NamedHttpFilterConfigFactory* factory = Envoy::Config::Utility::getFactoryByType( typed_config); @@ -2148,12 +2147,52 @@ PerFilterConfigs::PerFilterConfigs( const OptionalHttpFilters& optional_http_filters, Server::Configuration::ServerFactoryContext& factory_context, ProtobufMessage::ValidationVisitor& validator) { - for (const auto& it : typed_configs) { - const auto& name = it.first; - auto object = createRouteSpecificFilterConfig(name, it.second, optional_http_filters, - factory_context, validator); - if (object != nullptr) { - configs_[name] = std::move(object); + + const bool ignore_optional_option_from_hcm_for_route_config(Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config")); + + absl::string_view filter_config_type = + envoy::config::route::v3::FilterConfig::default_instance().GetDescriptor()->full_name(); + + for (const auto& per_filter_config : typed_configs) { + const std::string& name = per_filter_config.first; + RouteSpecificFilterConfigConstSharedPtr config; + + // There are two ways to mark a route/virtual host per filter configuration as optional: + // 1. Mark it as optional in the HTTP filter of HCM. This way is deprecated but still works + // when the runtime flag + // `envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config` + // is explicitly set to false. + // 2. Mark it as optional in the route/virtual host per filter configuration. This way is + // recommended. + // + // We check the first way first to ensure if this filter configuration is marked as optional + // or not. This will be true if the runtime flag is explicitly reverted to false and the + // config name is in the optional http filter list. + bool is_optional_by_hcm = !ignore_optional_option_from_hcm_for_route_config && + (optional_http_filters.find(name) != optional_http_filters.end()); + + if (TypeUtil::typeUrlToDescriptorFullName(per_filter_config.second.type_url()) == + filter_config_type) { + envoy::config::route::v3::FilterConfig filter_config; + Envoy::Config::Utility::translateOpaqueConfig(per_filter_config.second, validator, + filter_config); + + if (!filter_config.has_config()) { + throw EnvoyException( + fmt::format("Empty route/virtual host per filter configuration for {} filter", name)); + } + + config = createRouteSpecificFilterConfig(name, filter_config.config(), + is_optional_by_hcm || filter_config.is_optional(), + factory_context, validator); + } else { + config = createRouteSpecificFilterConfig(name, per_filter_config.second, is_optional_by_hcm, + factory_context, validator); + } + + if (config != nullptr) { + configs_[name] = std::move(config); } } } diff --git a/source/common/router/config_impl.h b/source/common/router/config_impl.h index e5f570e3cfe8..3f31ce43a986 100644 --- a/source/common/router/config_impl.h +++ b/source/common/router/config_impl.h @@ -91,10 +91,9 @@ class PerFilterConfigs : public Logger::Loggable { private: RouteSpecificFilterConfigConstSharedPtr createRouteSpecificFilterConfig(const std::string& name, const ProtobufWkt::Any& typed_config, - const OptionalHttpFilters& optional_http_filters, + bool is_optional, Server::Configuration::ServerFactoryContext& factory_context, ProtobufMessage::ValidationVisitor& validator); - absl::node_hash_map configs_; }; diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 0571c4ef20fe..f0e2429dccce 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -51,6 +51,7 @@ RUNTIME_GUARD(envoy_reloadable_features_http_ext_auth_failure_mode_allow_header_ RUNTIME_GUARD(envoy_reloadable_features_http_filter_avoid_reentrant_local_reply); RUNTIME_GUARD(envoy_reloadable_features_http_reject_path_with_fragment); RUNTIME_GUARD(envoy_reloadable_features_http_strip_fragment_from_path_unsafe_if_disabled); +RUNTIME_GUARD(envoy_reloadable_features_ignore_optional_option_from_hcm_for_route_config); RUNTIME_GUARD(envoy_reloadable_features_initialize_upstream_filters); RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name); RUNTIME_GUARD(envoy_reloadable_features_no_full_scan_certs_on_sni_mismatch); diff --git a/test/common/router/BUILD b/test/common/router/BUILD index affe611e5150..f7a93e02fd26 100644 --- a/test/common/router/BUILD +++ b/test/common/router/BUILD @@ -123,6 +123,7 @@ envoy_cc_test( "//test/mocks/server:instance_mocks", "//test/mocks/thread_local:thread_local_mocks", "//test/test_common:simulated_time_system_lib", + "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", "@envoy_api//envoy/admin/v3:pkg_cc_proto", "@envoy_api//envoy/config/route/v3:pkg_cc_proto", @@ -169,6 +170,7 @@ envoy_cc_test( "//test/mocks/router:router_mocks", "//test/mocks/server:instance_mocks", "//test/test_common:simulated_time_system_lib", + "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", "@envoy_api//envoy/admin/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index 122c00f7ccc5..dae94a11bb91 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -10288,6 +10288,11 @@ TEST_F(PerFilterConfigsTest, DefaultFilterImplementationAnyWithCheckPerVirtualHo } TEST_F(PerFilterConfigsTest, OptionalDefaultFilterImplementationAnyWithCheckPerVirtualHost) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + const std::string yaml = R"EOF( virtual_hosts: - name: bar @@ -10330,6 +10335,11 @@ TEST_F(PerFilterConfigsTest, DefaultFilterImplementationAnyWithCheckPerRoute) { } TEST_F(PerFilterConfigsTest, OptionalDefaultFilterImplementationAnyWithCheckPerRoute) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + const std::string yaml = R"EOF( virtual_hosts: - name: bar @@ -10369,6 +10379,11 @@ TEST_F(PerFilterConfigsTest, PerVirtualHostWithUnknownFilter) { } TEST_F(PerFilterConfigsTest, PerVirtualHostWithOptionalUnknownFilter) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + const std::string yaml = R"EOF( virtual_hosts: - name: bar @@ -10406,7 +10421,12 @@ TEST_F(PerFilterConfigsTest, PerRouteWithUnknownFilter) { "'google.protobuf.BoolValue'"); } -TEST_F(PerFilterConfigsTest, PerRouteWithOptionalUnknownFilter) { +TEST_F(PerFilterConfigsTest, PerRouteWithHcmOptionalUnknownFilterLegacy) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + const std::string yaml = R"EOF( virtual_hosts: - name: bar @@ -10425,6 +10445,121 @@ TEST_F(PerFilterConfigsTest, PerRouteWithOptionalUnknownFilter) { checkNoPerFilterConfig(yaml, "filter.unknown", optional_http_filters); } +TEST_F(PerFilterConfigsTest, PerRouteWithHcmOptionalUnknownFilter) { + const std::string yaml = R"EOF( +virtual_hosts: + - name: bar + domains: ["*"] + routes: + - match: { prefix: "/" } + route: { cluster: baz } + typed_per_filter_config: + filter.unknown: + "@type": type.googleapis.com/google.protobuf.BoolValue +)EOF"; + + factory_context_.cluster_manager_.initializeClusters({"baz"}, {}); + OptionalHttpFilters optional_http_filters; + optional_http_filters.insert("filter.unknown"); + + EXPECT_THROW_WITH_MESSAGE( + TestConfigImpl(parseRouteConfigurationFromYaml(yaml), factory_context_, true, + optional_http_filters), + EnvoyException, + "Didn't find a registered implementation for 'filter.unknown' with type URL: " + "'google.protobuf.BoolValue'"); +} + +TEST_F(PerFilterConfigsTest, OptionalDefaultFilterImplementationAny) { + const std::string yaml = R"EOF( +typed_per_filter_config: + test.default.filter: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true + config: + "@type": type.googleapis.com/google.protobuf.Struct + value: + seconds: 123 +virtual_hosts: + - name: bar + domains: ["*"] + routes: + - match: { prefix: "/" } + route: { cluster: baz } + typed_per_filter_config: + test.default.filter: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true + config: + "@type": type.googleapis.com/google.protobuf.Struct + value: + seconds: 123 + typed_per_filter_config: + test.default.filter: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true + config: + "@type": type.googleapis.com/google.protobuf.Struct + value: + seconds: 123 +)EOF"; + + factory_context_.cluster_manager_.initializeClusters({"baz"}, {}); + checkNoPerFilterConfig(yaml, "filter.unknown"); +} + +TEST_F(PerFilterConfigsTest, OptionalUnknownFilter) { + const std::string yaml = R"EOF( +typed_per_filter_config: + filter.unknown: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true + config: + "@type": type.googleapis.com/google.protobuf.BoolValue +virtual_hosts: + - name: bar + domains: ["*"] + routes: + - match: { prefix: "/" } + route: { cluster: baz } + typed_per_filter_config: + filter.unknown: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true + config: + "@type": type.googleapis.com/google.protobuf.BoolValue + typed_per_filter_config: + filter.unknown: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true + config: + "@type": type.googleapis.com/google.protobuf.BoolValue +)EOF"; + + factory_context_.cluster_manager_.initializeClusters({"baz"}, {}); + checkNoPerFilterConfig(yaml, "filter.unknown"); +} + +TEST_F(PerFilterConfigsTest, FilterConfigWithoutConfig) { + const std::string yaml = R"EOF( +virtual_hosts: + - name: bar + domains: ["*"] + routes: + - match: { prefix: "/" } + route: { cluster: baz } + typed_per_filter_config: + filter.unknown: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true +)EOF"; + + EXPECT_THROW_WITH_MESSAGE( + TestConfigImpl(parseRouteConfigurationFromYaml(yaml), factory_context_, false), + EnvoyException, + "Empty route/virtual host per filter configuration for filter.unknown filter"); +} + TEST_F(PerFilterConfigsTest, RouteLocalTypedConfig) { const std::string yaml = R"EOF( typed_per_filter_config: diff --git a/test/common/router/rds_impl_test.cc b/test/common/router/rds_impl_test.cc index 881e43983cc7..981094f1b32d 100644 --- a/test/common/router/rds_impl_test.cc +++ b/test/common/router/rds_impl_test.cc @@ -26,6 +26,7 @@ #include "test/test_common/printers.h" #include "test/test_common/simulated_time_system.h" #include "test/test_common/utility.h" +#include "test/test_common/test_runtime.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -180,7 +181,12 @@ stat_prefix: foo "'google.protobuf.Struct'"); } -TEST_F(RdsImplTest, RdsAndStaticWithOptionalUnknownFilterPerVirtualHostConfig) { +TEST_F(RdsImplTest, RdsAndStaticWithHcmOptionalUnknownFilterPerVirtualHostConfig) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + const std::string config_yaml = R"EOF( route_config: virtual_hosts: @@ -205,6 +211,34 @@ stat_prefix: foo "foo.", *route_config_provider_manager_); } +TEST_F(RdsImplTest, RdsAndStaticWithOptionalUnknownFilterPerVirtualHostConfig) { + const std::string config_yaml = R"EOF( +route_config: + virtual_hosts: + - name: bar + domains: ["*"] + routes: + - match: { prefix: "/" } + typed_per_filter_config: + filter.unknown: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + is_optional: true + config: + "@type": type.googleapis.com/google.protobuf.Struct + value: + seconds: 123 +codec_type: auto +stat_prefix: foo +http_filters: +- name: filter.unknown + is_optional: true + )EOF"; + + RouteConfigProviderUtil::create(parseHttpConnectionManagerFromYaml(config_yaml), + server_factory_context_, validation_visitor_, outer_init_manager_, + "foo.", *route_config_provider_manager_); +} + TEST_F(RdsImplTest, DestroyDuringInitialize) { InSequence s; setup(); @@ -358,7 +392,12 @@ TEST_F(RdsImplTest, UnknownFacotryForPerVirtualHostTypedConfig) { } // validate the optional unknown factory will be ignored for per virtualhost typed config. -TEST_F(RdsImplTest, OptionalUnknownFacotryForPerVirtualHostTypedConfig) { +TEST_F(RdsImplTest, HcmOptionalUnknownFacotryForPerVirtualHostTypedConfig) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + InSequence s; const std::string config_yaml = R"EOF( rds: @@ -421,6 +460,74 @@ stat_prefix: foo rds_callbacks_->onConfigUpdate(decoded_resources.refvec_, response1.version_info()); } +// Validate the optional unknown factory will be ignored for per virtualhost typed config. +TEST_F(RdsImplTest, OptionalUnknownFacotryForPerVirtualHostTypedConfig) { + InSequence s; + const std::string config_yaml = R"EOF( +rds: + config_source: + api_config_source: + api_type: REST + cluster_names: + - foo_cluster + refresh_delay: 1s + route_config_name: foo_route_config +codec_type: auto +stat_prefix: foo +http_filters: +- name: filter.unknown + is_optional: true + )EOF"; + + setup(config_yaml); + + const std::string response1_json = R"EOF( +{ + "version_info": "1", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "foo_route_config", + "virtual_hosts": [ + { + "name": "integration", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/foo" + }, + "route": { + "cluster_header": ":authority" + } + } + ], + "typed_per_filter_config": { + "filter.unknown": { + "@type": "type.googleapis.com/envoy.config.route.v3.FilterConfig", + "is_optional": true, + "config": { + "@type": "type.googleapis.com/google.protobuf.Struct" + } + } + } + } + ] + } + ] +} +)EOF"; + auto response1 = + TestUtility::parseYaml(response1_json); + const auto decoded_resources = + TestUtility::decodeResources(response1); + + EXPECT_CALL(init_watcher_, ready()); + rds_callbacks_->onConfigUpdate(decoded_resources.refvec_, response1.version_info()); +} + // validate there will be exception throw when unknown factory found for per route typed config. TEST_F(RdsImplTest, UnknownFacotryForPerRouteTypedConfig) { InSequence s; @@ -476,6 +583,11 @@ TEST_F(RdsImplTest, UnknownFacotryForPerRouteTypedConfig) { // validate the optional unknown factory will be ignored for per route typed config. TEST_F(RdsImplTest, OptionalUnknownFacotryForPerRouteTypedConfig) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + InSequence s; const std::string config_yaml = R"EOF( rds: diff --git a/test/common/router/scoped_rds_test.cc b/test/common/router/scoped_rds_test.cc index d4b8b16f0b5d..f392bdd26d60 100644 --- a/test/common/router/scoped_rds_test.cc +++ b/test/common/router/scoped_rds_test.cc @@ -24,6 +24,7 @@ #include "test/mocks/router/mocks.h" #include "test/mocks/server/instance.h" #include "test/test_common/simulated_time_system.h" +#include "test/test_common/test_runtime.h" #include "test/test_common/utility.h" #include "absl/strings/string_view.h" @@ -570,6 +571,11 @@ route_configuration_name: foo_routes // Test ignoring the optional unknown factory in the per-virtualhost typed config. TEST_F(ScopedRdsTest, OptionalUnknownFactoryForPerVirtualHostTypedConfig) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"}}); + OptionalHttpFilters optional_http_filters; optional_http_filters.insert("filter.unknown"); setup(optional_http_filters); diff --git a/test/integration/http_typed_per_filter_config_test.cc b/test/integration/http_typed_per_filter_config_test.cc index 43b82354dbd1..d6a07c91b89f 100644 --- a/test/integration/http_typed_per_filter_config_test.cc +++ b/test/integration/http_typed_per_filter_config_test.cc @@ -1,3 +1,5 @@ +#include "envoy/config/route/v3/route_components.pb.h" + #include "test/integration/filters/set_response_code_filter_config.pb.h" #include "test/integration/http_integration.h" @@ -47,7 +49,11 @@ TEST_F(HTTPTypedPerFilterConfigTest, RejectUnknownHttpFilterInTypedPerFilterConf "'google.protobuf.Struct'"); } -TEST_F(HTTPTypedPerFilterConfigTest, IgnoreUnknownOptionalHttpFilterInTypedPerFilterConfig) { +TEST_F(HTTPTypedPerFilterConfigTest, HcmIgnoreUnknownOptionalHttpFilterInTypedPerFilterConfig) { + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"); + config_helper_.addConfigModifier( [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& hcm) { @@ -65,5 +71,27 @@ TEST_F(HTTPTypedPerFilterConfigTest, IgnoreUnknownOptionalHttpFilterInTypedPerFi initialize(); } +TEST_F(HTTPTypedPerFilterConfigTest, IgnoreUnknownOptionalHttpFilterInTypedPerFilterConfig) { + config_helper_.addConfigModifier( + [&](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& + hcm) { + auto* virtual_host = hcm.mutable_route_config()->mutable_virtual_hosts(0); + auto* config = virtual_host->mutable_typed_per_filter_config(); + + envoy::config::route::v3::FilterConfig filter_config; + filter_config.set_is_optional(true); + filter_config.mutable_config()->PackFrom(Envoy::ProtobufWkt::Struct()); + (*config)["filter.unknown"].PackFrom(filter_config); + + auto* filter = hcm.mutable_http_filters()->Add(); + filter->set_name("filter.unknown"); + filter->set_is_optional(true); + // keep router the last + auto size = hcm.http_filters_size(); + hcm.mutable_http_filters()->SwapElements(size - 2, size - 1); + }); + initialize(); +} + } // namespace } // namespace Envoy diff --git a/test/integration/scoped_rds_integration_test.cc b/test/integration/scoped_rds_integration_test.cc index 4b5aedffa47e..118725693f2b 100644 --- a/test/integration/scoped_rds_integration_test.cc +++ b/test/integration/scoped_rds_integration_test.cc @@ -465,6 +465,10 @@ route_configuration_name: {} sendRdsResponse(fmt::format(route_config_tmpl, "foo_route", "cluster_0"), "1"); }; + // TODO(wbpcode): This test should be removed once the deprecated flag is removed. + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.ignore_optional_option_from_hcm_for_route_config", "false"); + config_helper_.addConfigModifier( [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& http_connection_manager) { From 58ec492086e290c2a94b818206c86bce8201f3c0 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Thu, 1 Jun 2023 16:08:19 +0800 Subject: [PATCH 147/228] fix problematic link (#27673) Signed-off-by: cui fliter --- api/envoy/extensions/transport_sockets/s2a/v3/s2a.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/transport_sockets/s2a/v3/s2a.proto b/api/envoy/extensions/transport_sockets/s2a/v3/s2a.proto index a8042c0417f0..03326c43e4db 100644 --- a/api/envoy/extensions/transport_sockets/s2a/v3/s2a.proto +++ b/api/envoy/extensions/transport_sockets/s2a/v3/s2a.proto @@ -14,7 +14,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#not-implemented-hide:] // Configuration for S2A transport socket. This allows Envoy clients to // configure how to offload mTLS handshakes to the S2A service. -// https://github.com/google/s2a-core#readme +// https://github.com/google/s2a-go#readme message S2AConfiguration { // The address of the S2A. This can be an IP address or a hostname, // followed by a port number. From 9406ed05cc7442b6c7ae8f8bfaf66e9514d7a7b7 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 1 Jun 2023 09:16:26 +0100 Subject: [PATCH 148/228] ci: Shift downstream sync azp -> gh (#27294) Signed-off-by: Ryan Northey --- .azure-pipelines/stage/sync.yml | 95 -------------------------------- .azure-pipelines/stages.yml | 15 ----- .github/workflows/envoy-sync.yml | 29 ++++++++++ ci/api_mirror.sh | 44 --------------- ci/filter_example_mirror.sh | 37 ------------- ci/go_mirror.sh | 12 ---- 6 files changed, 29 insertions(+), 203 deletions(-) delete mode 100644 .azure-pipelines/stage/sync.yml create mode 100644 .github/workflows/envoy-sync.yml delete mode 100755 ci/api_mirror.sh delete mode 100755 ci/filter_example_mirror.sh delete mode 100755 ci/go_mirror.sh diff --git a/.azure-pipelines/stage/sync.yml b/.azure-pipelines/stage/sync.yml deleted file mode 100644 index 39eb91180336..000000000000 --- a/.azure-pipelines/stage/sync.yml +++ /dev/null @@ -1,95 +0,0 @@ - -parameters: -- name: authGCP - type: string - default: "" -- name: authSSHKeyPassphrase - type: string - default: "" -- name: authSSHDataPlaneApiKey - type: string - default: "" -- name: authSSHDataPlaneApiKeyPublic - type: string - default: "" -- name: authSSHGoControlPlaneKey - type: string - default: "" -- name: authSSHGoControlPlaneKeyPublic - type: string - default: "" -- name: authSSHFilterExampleKey - type: string - default: "" -- name: authSSHFilterExampleKeyPublic - type: string - default: "" - - -jobs: -- job: filter_example - dependsOn: [] - pool: - vmImage: "ubuntu-20.04" - steps: - - checkout: self - fetchDepth: 0 - fetchTags: true - - task: InstallSSHKey@0 - inputs: - hostName: $(authGithubSSHKeyPublic) - sshPublicKey: "${{ parameters.authSSHFilterExampleKeyPublic }}" - sshPassphrase: "${{ parameters.authSSHKeyPassphrase }}" - sshKeySecureFile: "${{ parameters.authSSHFilterExampleKey }}" - - bash: ci/filter_example_mirror.sh - displayName: "Sync envoy-filter-example" - workingDirectory: $(Build.SourcesDirectory) - env: - AZP_BRANCH: $(Build.SourceBranch) - -- job: data_plane_api - dependsOn: [] - pool: - vmImage: "ubuntu-20.04" - steps: - - checkout: self - fetchDepth: 0 - fetchTags: true - - task: InstallSSHKey@0 - inputs: - hostName: $(authGithubSSHKeyPublic) - sshPublicKey: "${{ parameters.authSSHDataPlaneApiKeyPublic }}" - sshPassphrase: "${{ parameters.authSSHKeyPassphrase }}" - sshKeySecureFile: "${{ parameters.authSSHDataPlaneApiKey }}" - - bash: ci/api_mirror.sh - displayName: "Sync data-plane-api" - workingDirectory: $(Build.SourcesDirectory) - env: - AZP_BRANCH: $(Build.SourceBranch) - -- job: go_control_plane - dependsOn: [] - pool: - vmImage: "ubuntu-20.04" - steps: - - checkout: self - fetchDepth: 0 - fetchTags: true - - task: InstallSSHKey@0 - inputs: - hostName: $(authGithubSSHKeyPublic) - sshPublicKey: "${{ parameters.authSSHGoControlPlaneKeyPublic }}" - sshPassphrase: "${{ parameters.authSSHKeyPassphrase }}" - sshKeySecureFile: "${{ parameters.authSSHGoControlPlaneKey }}" - - bash: | - cp -a ~/.ssh $(Build.StagingDirectory)/ - ci/run_envoy_docker.sh 'ci/go_mirror.sh' - displayName: "Sync go-control-plane" - workingDirectory: $(Build.SourcesDirectory) - env: - ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory) - # TODO: make into parameters - BAZEL_REMOTE_CACHE: grpcs://remotebuildexecution.googleapis.com - BAZEL_REMOTE_INSTANCE: projects/envoy-ci/instances/default_instance - GCP_SERVICE_ACCOUNT_KEY: ${{ parameters.authGCP }} - AZP_BRANCH: $(Build.SourceBranch) diff --git a/.azure-pipelines/stages.yml b/.azure-pipelines/stages.yml index caab5bae0fad..de69153bfbf7 100644 --- a/.azure-pipelines/stages.yml +++ b/.azure-pipelines/stages.yml @@ -75,21 +75,6 @@ stages: bucketGCP: $(GcsArtifactBucket) checkDeps: variables['CHECK_DEPS'] -- stage: sync - condition: and(succeeded(), eq(variables['PostSubmit'], true), ne(variables['NoSync'], true)) - dependsOn: [] - jobs: - - template: stage/sync.yml - parameters: - authGCP: $(GcpServiceAccountKey) - authSSHDataPlaneApiKeyPublic: $(DataPlaneApiPublicKey) - authSSHDataPlaneApiKey: $(DataPlaneApiPrivateKey) - authSSHGoControlPlaneKeyPublic: $(GoControlPlanePublicKey) - authSSHGoControlPlaneKey: $(GoControlPlanePrivateKey) - authSSHFilterExampleKeyPublic: $(FilterExamplePublicKey) - authSSHFilterExampleKey: $(FilterExamplePrivateKey) - authSSHKeyPassphrase: $(SshDeployKeyPassphrase) - - stage: linux_x64 displayName: Linux x64 dependsOn: ${{ parameters.buildStageDeps }} diff --git a/.github/workflows/envoy-sync.yml b/.github/workflows/envoy-sync.yml new file mode 100644 index 000000000000..da65ccc55984 --- /dev/null +++ b/.github/workflows/envoy-sync.yml @@ -0,0 +1,29 @@ +name: 'Sync downstream' + +on: + push: + branches: + - main + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +jobs: + sync: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + downstream: + - go-control-plane + - envoy-filter-example + - data-plane-api + steps: + - uses: envoyproxy/toolshed/gh-actions/dispatch@1f1feae1e372dde41ecc6830028989bb6037c480 + with: + repository: "envoyproxy/${{ matrix.downstream }}" + ref: main + key: "${{ secrets.ENVOY_CI_SYNC_APP_KEY }}" + workflow: envoy-sync.yaml + app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} diff --git a/ci/api_mirror.sh b/ci/api_mirror.sh deleted file mode 100755 index 8a3022b72431..000000000000 --- a/ci/api_mirror.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -set -e - -CHECKOUT_DIR=../data-plane-api -MAIN_BRANCH="refs/heads/main" -API_MAIN_BRANCH="main" - -if [[ "${AZP_BRANCH}" == "${MAIN_BRANCH}" ]]; then - echo "Cloning..." - git clone git@github.com:envoyproxy/data-plane-api "$CHECKOUT_DIR" -b "${API_MAIN_BRANCH}" - - git -C "$CHECKOUT_DIR" config user.name "data-plane-api(Azure Pipelines)" - git -C "$CHECKOUT_DIR" config user.email data-plane-api@users.noreply.github.com - - # Determine last envoyproxy/envoy SHA in envoyproxy/data-plane-api - MIRROR_MSG="Mirrored from https://github.com/envoyproxy/envoy" - LAST_ENVOY_SHA=$(git -C "$CHECKOUT_DIR" log --grep="$MIRROR_MSG" -n 1 | grep "$MIRROR_MSG" | \ - tail -n 1 | sed -e "s#.*$MIRROR_MSG @ ##") - - echo "Last mirrored envoyproxy/envoy SHA is $LAST_ENVOY_SHA" - - # Compute SHA sequence to replay in envoyproxy/data-plane-api - SHAS=$(git rev-list --reverse "$LAST_ENVOY_SHA"..HEAD api/) - - # For each SHA, hard reset, rsync api/ and generate commit in - # envoyproxy/data-plane-api - API_WORKING_DIR="../envoy-api-mirror" - git worktree add "$API_WORKING_DIR" - for sha in $SHAS - do - git -C "$API_WORKING_DIR" reset --hard "$sha" - COMMIT_MSG=$(git -C "$API_WORKING_DIR" log --format=%B -n 1) - QUALIFIED_COMMIT_MSG=$(echo -e "$COMMIT_MSG\n\n$MIRROR_MSG @ $sha") - rsync -acv --delete --exclude "ci/" --exclude ".*" --exclude LICENSE \ - "$API_WORKING_DIR"/api/ "$CHECKOUT_DIR"/ - git -C "$CHECKOUT_DIR" add . - git -C "$CHECKOUT_DIR" commit -m "$QUALIFIED_COMMIT_MSG" - done - - echo "Pushing..." - git -C "$CHECKOUT_DIR" push origin "${API_MAIN_BRANCH}" - echo "Done" -fi diff --git a/ci/filter_example_mirror.sh b/ci/filter_example_mirror.sh deleted file mode 100755 index ed26317c49a2..000000000000 --- a/ci/filter_example_mirror.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -set -e - -ENVOY_SRCDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../" && pwd) -CHECKOUT_DIR=../envoy-filter-example -MAIN_BRANCH="refs/heads/main" -FILTER_EXAMPLE_MAIN_BRANCH="main" - -if [[ "${AZP_BRANCH}" == "${MAIN_BRANCH}" ]]; then - echo "Cloning..." - git clone git@github.com:envoyproxy/envoy-filter-example "$CHECKOUT_DIR" -b "${FILTER_EXAMPLE_MAIN_BRANCH}" - - git -C "$CHECKOUT_DIR" config user.name "envoy-filter-example(Azure Pipelines)" - git -C "$CHECKOUT_DIR" config user.email envoy-filter-example@users.noreply.github.com - - echo "Updating Submodule..." - # Update submodule to latest Envoy SHA - ENVOY_SHA=$(git rev-parse HEAD) - CURRENT_SHA="$(git -C "$CHECKOUT_DIR" ls-files -s envoy | cut -d' ' -f2)" - - if [[ "$CURRENT_SHA" == "$ENVOY_SHA" ]]; then - echo "Submodule already up to date (${ENVOY_SHA})" - exit 0 - fi - - git -C "$CHECKOUT_DIR" submodule update --init - git -C "$CHECKOUT_DIR/envoy" checkout "$ENVOY_SHA" - - echo "Updating Workspace file." - sed -e "s|{ENVOY_SRCDIR}|envoy|" "${ENVOY_SRCDIR}"/ci/WORKSPACE.filter.example > "${CHECKOUT_DIR}"/WORKSPACE - - echo "Committing, and Pushing..." - git -C "$CHECKOUT_DIR" commit -a -m "Update Envoy submodule to $ENVOY_SHA" - git -C "$CHECKOUT_DIR" push origin "${FILTER_EXAMPLE_MAIN_BRANCH}" - echo "Done" -fi diff --git a/ci/go_mirror.sh b/ci/go_mirror.sh deleted file mode 100755 index 6e69c68a0a93..000000000000 --- a/ci/go_mirror.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -e - -MAIN_BRANCH="refs/heads/main" - -# shellcheck source=ci/setup_cache.sh -. "$(dirname "$0")"/setup_cache.sh - -if [[ "${AZP_BRANCH}" == "${MAIN_BRANCH}" ]]; then - BAZEL_BUILD_OPTION_LIST="${BAZEL_BUILD_EXTRA_OPTIONS}" tools/api/generate_go_protobuf.py --sync -fi From 62da62f6f8503a9f37b978ba2cef5adff9723c9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 09:27:53 +0100 Subject: [PATCH 149/228] build(deps): bump actions/dependency-review-action from 3.0.4 to 3.0.6 (#27741) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 3.0.4 to 3.0.6. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/f46c48ed6d4f1227fb2d9ea62bf6bcbed315589e...1360a344ccb0ab6e9475edef90ad2f46bf8003b1) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/depsreview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/depsreview.yml b/.github/workflows/depsreview.yml index 007b2e497174..542888585103 100644 --- a/.github/workflows/depsreview.yml +++ b/.github/workflows/depsreview.yml @@ -13,4 +13,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@v3 - name: 'Dependency Review' - uses: actions/dependency-review-action@f46c48ed6d4f1227fb2d9ea62bf6bcbed315589e + uses: actions/dependency-review-action@1360a344ccb0ab6e9475edef90ad2f46bf8003b1 From ae5758f28c4fe4e3e9935b0d1480393fb4cc1782 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 09:43:31 +0100 Subject: [PATCH 150/228] build(deps): bump jaegertracing/all-in-one from `114816a` to `1cb8093` in /examples/shared/jaeger (#27745) build(deps): bump jaegertracing/all-in-one in /examples/shared/jaeger Bumps jaegertracing/all-in-one from `114816a` to `1cb8093`. --- updated-dependencies: - dependency-name: jaegertracing/all-in-one dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/jaeger/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/jaeger/Dockerfile b/examples/shared/jaeger/Dockerfile index 57dfe7cb60a4..b9fcb0029145 100644 --- a/examples/shared/jaeger/Dockerfile +++ b/examples/shared/jaeger/Dockerfile @@ -1,4 +1,4 @@ -FROM jaegertracing/all-in-one@sha256:114816a5808fddda2bdcf85f335d306b279b2cebb1e48d9d1d0f0e9ab53beeb9 +FROM jaegertracing/all-in-one@sha256:1cb80937ebe12ed06267d2f773623d33a4610df9ef59d82e92c15613f31772ed HEALTHCHECK \ --interval=1s \ --timeout=1s \ From bdaebba6b3e77701b487761813272cc3ecd3625e Mon Sep 17 00:00:00 2001 From: John Bucy Date: Wed, 31 May 2023 23:07:21 -1000 Subject: [PATCH 151/228] Fix examples/cache (#27743) examples/cache: fix reference to aiohttp exception Signed-off-by: John Bucy --- examples/cache/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cache/service.py b/examples/cache/service.py index aff199544db3..37e18a370959 100644 --- a/examples/cache/service.py +++ b/examples/cache/service.py @@ -63,7 +63,7 @@ async def get(request): stored_response = yaml.safe_load(open('/etc/responses.yaml', 'r')).get(response_id) if stored_response is None: - raise aiohttp.web.HTTPNotFound(reason="No response found with the given id") + raise web.HTTPNotFound(reason="No response found with the given id") request_date = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") response = web.Response( From b39d6a09a1af8af96c6c9a9ec283fa581f33dd66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:13:45 +0100 Subject: [PATCH 152/228] build(deps): bump openzipkin/zipkin from `2d797c2` to `46ee38f` in /examples/zipkin (#27746) build(deps): bump openzipkin/zipkin in /examples/zipkin Bumps openzipkin/zipkin from `2d797c2` to `46ee38f`. --- updated-dependencies: - dependency-name: openzipkin/zipkin dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/zipkin/Dockerfile-zipkin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/zipkin/Dockerfile-zipkin b/examples/zipkin/Dockerfile-zipkin index c09f6bb90525..4bf28ce777b1 100644 --- a/examples/zipkin/Dockerfile-zipkin +++ b/examples/zipkin/Dockerfile-zipkin @@ -1 +1 @@ -FROM openzipkin/zipkin:latest@sha256:2d797c2da4aa98aee166eef82852cfb3cf09c1c3c3e48905be3564ce7e6acfc4 +FROM openzipkin/zipkin:latest@sha256:46ee38f01382e72de617f704441fd935390c6eeb762e88869530e661f1339765 From d69008bf49b9eb4b4327d4cb4bc8f74dbcef93a8 Mon Sep 17 00:00:00 2001 From: "Dr. Andre Vehreschild" <101638173+vehre-x41@users.noreply.github.com> Date: Thu, 1 Jun 2023 14:09:45 +0200 Subject: [PATCH 153/228] [fuzz] Look at the correct class name for cut off. (#27729) Signed-off-by: Andre Vehreschild --- test/fuzz/validated_input_generator.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/fuzz/validated_input_generator.cc b/test/fuzz/validated_input_generator.cc index db9e4f3700c7..6970b111afcb 100644 --- a/test/fuzz/validated_input_generator.cc +++ b/test/fuzz/validated_input_generator.cc @@ -427,13 +427,12 @@ void ValidatedInputGenerator::onEnterMessage(Protobuf::Message& msg, !reflection->HasOneof(msg, descriptor->oneof_decl(oneof_index)))) { // No required member in one of set, so create one. for (int index = 0; index < oneof_desc->field_count(); ++index) { - const std::string parents_class_name = parents.back()->GetDescriptor()->full_name(); + const std::string class_name = descriptor->full_name(); // Treat matchers special, because in their oneof they reference themselves, which may // create long chains. Prefer the first alternative, which does not reference itself. // Nevertheless do it randomly to allow for some nesting. - if ((parents_class_name == "xds.type.matcher.v3.Matcher.MatcherList.Predicate" || - parents_class_name == - "xds.type.matcher.v3.Matcher.MatcherList.Predicate.SinglePredicate") && + if ((class_name == "xds.type.matcher.v3.Matcher.MatcherList.Predicate" || + class_name == "xds.type.matcher.v3.Matcher.MatcherList.Predicate.SinglePredicate") && (random_() % 200) > 0) { onField(msg, *oneof_desc->field(0), parents, true, max_depth_exceeded); } else { From c43460d62489948a36a6eb36b5c6dc018e96902f Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Thu, 1 Jun 2023 20:38:40 +0800 Subject: [PATCH 154/228] warn about `GODEBUG=cgocheck=0` env variable in golang plugin example docs. (#27744) Signed-off-by: doujiang24 --- .../root/configuration/http/cluster_specifier/golang.rst | 2 +- .../configuration/http/http_filters/golang_filter.rst | 2 +- docs/root/start/sandboxes/golang.rst | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/root/configuration/http/cluster_specifier/golang.rst b/docs/root/configuration/http/cluster_specifier/golang.rst index 6b1938c5559d..efe9e1e984ff 100644 --- a/docs/root/configuration/http/cluster_specifier/golang.rst +++ b/docs/root/configuration/http/cluster_specifier/golang.rst @@ -9,7 +9,7 @@ and makes it easier to extend Envoy. Go cluster specifier plugins can be recompiled independently of Envoy. .. warning:: - The Envoy Golang cluster specifier is designed to be run with the `GODEBUG=cgocheck=0` environment variable set. + The Envoy Golang cluster specifier is designed to be run with the ``GODEBUG=cgocheck=0`` environment variable set. This disables the cgo pointer check. diff --git a/docs/root/configuration/http/http_filters/golang_filter.rst b/docs/root/configuration/http/http_filters/golang_filter.rst index e4e7aec82e1e..9a1106d8bfcd 100644 --- a/docs/root/configuration/http/http_filters/golang_filter.rst +++ b/docs/root/configuration/http/http_filters/golang_filter.rst @@ -13,7 +13,7 @@ See the `Envoy's Golang extension proposal documentation for more details on the filter's implementation. .. warning:: - The Envoy Golang filter is designed to be run with the `GODEBUG=cgocheck=0` environment variable set. + The Envoy Golang filter is designed to be run with the ``GODEBUG=cgocheck=0`` environment variable set. This disables the cgo pointer check. diff --git a/docs/root/start/sandboxes/golang.rst b/docs/root/start/sandboxes/golang.rst index 50bc2c8e878e..d81adedf48ea 100644 --- a/docs/root/start/sandboxes/golang.rst +++ b/docs/root/start/sandboxes/golang.rst @@ -40,6 +40,15 @@ Step 2: Start all of our containers Start all the containers. +.. warning:: + The Envoy Golang filter is designed to be run with the ``GODEBUG=cgocheck=0`` environment variable set. + + This disables the cgo pointer check. + + Failure to set this environment variable will cause Envoy to crash! + + Here, we have set this environment variable in :repo:`Dockerfile ` + .. code-block:: console $ docker compose pull From 487cedbc8bdccff80d497be95ac58a71b5244b64 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 1 Jun 2023 14:45:53 +0100 Subject: [PATCH 155/228] deps: Bump `proxy_wasm_cpp_host` -> 5d76116 (+ related deps) (#27718) * deps: Bump `com_github_wamr` -> 1.2.2 * deps: Bump `proxy_wasm_cpp_host` -> 5d76116 * deps: Bump `com_github_wasmtime` -> 9.0.3 Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 6ea53a224d09..1deaabc0ec69 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -930,11 +930,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Webassembly Micro Runtime", project_desc = "A standalone runtime with a small footprint for WebAssembly", project_url = "https://github.com/bytecodealliance/wasm-micro-runtime", - version = "WAMR-1.1.2", - sha256 = "976b928f420040a77e793051e4d742208adf157370b9ad0f5535e126adb31eb0", + version = "WAMR-1.2.2", + sha256 = "d328fc1e19c54cfdb4248b861de54b62977b9b85c0a40eaaeb9cd9b628c0c788", strip_prefix = "wasm-micro-runtime-{version}", urls = ["https://github.com/bytecodealliance/wasm-micro-runtime/archive/{version}.tar.gz"], - release_date = "2022-12-16", + release_date = "2023-05-16", use_category = ["dataplane_ext"], extensions = ["envoy.wasm.runtime.wamr"], cpe = "N/A", @@ -958,11 +958,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "wasmtime", project_desc = "A standalone runtime for WebAssembly", project_url = "https://github.com/bytecodealliance/wasmtime", - version = "6.0.1", - sha256 = "7ed6359faa385c40fc77e324301e5c70c7fdaeeca8a5ab58e25b1f75035b2cd6", + version = "9.0.3", + sha256 = "917da461249b11a3176a39573723f78c627259576d0ca10b00d6e7f7fa047081", strip_prefix = "wasmtime-{version}", urls = ["https://github.com/bytecodealliance/wasmtime/archive/v{version}.tar.gz"], - release_date = "2023-03-08", + release_date = "2023-05-31", use_category = ["dataplane_ext"], extensions = ["envoy.wasm.runtime.wasmtime"], cpe = "cpe:2.3:a:bytecodealliance:wasmtime:*", @@ -1271,8 +1271,8 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "WebAssembly for Proxies (C++ host implementation)", project_desc = "WebAssembly for Proxies (C++ host implementation)", project_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-host", - version = "8aa8053609d893e25287551295bd9cd7dd4c3dcc", - sha256 = "e588c077705ed2c5aa77edd19151cec8c75525ec5d0973bcb8b45a7a27109dd9", + version = "5d76116c449d6892b298b7ae79a84ef1cf5752bf", + sha256 = "a5825a1a5bbd5b0178c6189b227d5cf4370ac713a883b41f6a54edd768a03cb7", strip_prefix = "proxy-wasm-cpp-host-{version}", urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-host/archive/{version}.tar.gz"], use_category = ["dataplane_ext"], @@ -1288,7 +1288,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( "envoy.wasm.runtime.wavm", "envoy.wasm.runtime.wasmtime", ], - release_date = "2023-03-20", + release_date = "2023-06-01", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-host/blob/{version}/LICENSE", From 94223d8d6e075ce254bb79ac76321788e160e9e6 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 1 Jun 2023 09:59:14 -0400 Subject: [PATCH 156/228] xds: moving xds only files into the relevant extension directory. (#27703) move gRPC files Signed-off-by: Alyssa Wilk --- contrib/config/test/BUILD | 4 +- .../kv_store_xds_delegate_integration_test.cc | 2 +- .../config/test/kv_store_xds_delegate_test.cc | 2 +- envoy/config/BUILD | 1 - source/common/config/BUILD | 86 +++---------------- .../extensions/config_subscription/grpc/BUILD | 76 ++++++++++++++-- .../config_subscription/grpc/grpc_mux_impl.cc | 2 +- .../config_subscription/grpc/grpc_mux_impl.h | 2 +- .../config_subscription/grpc}/grpc_stream.h | 0 .../grpc/new_delta_subscription_state.h | 4 +- .../grpc/new_grpc_mux_impl.h | 6 +- .../grpc/old_delta_subscription_state.h | 4 +- .../grpc}/pausable_ack_queue.cc | 2 +- .../grpc}/pausable_ack_queue.h | 2 +- .../config_subscription/grpc}/update_ack.h | 0 .../config_subscription/grpc}/watch_map.cc | 2 +- .../config_subscription/grpc}/watch_map.h | 0 .../config_subscription/grpc/xds_mux/BUILD | 10 +-- .../grpc/xds_mux/grpc_mux_impl.h | 6 +- .../grpc/xds_mux/sotw_subscription_state.cc | 2 +- .../grpc/xds_mux/subscription_state.h | 2 +- .../grpc}/xds_source_id.cc | 2 +- .../config_subscription/grpc}/xds_source_id.h | 0 test/common/config/BUILD | 46 ---------- .../extensions/config_subscription/grpc/BUILD | 46 ++++++++++ .../grpc}/grpc_stream_test.cc | 2 +- .../grpc}/pausable_ack_queue_test.cc | 2 +- .../grpc}/watch_map_test.cc | 2 +- .../grpc}/xds_source_id_test.cc | 2 +- test/per_file_coverage.sh | 2 +- 30 files changed, 159 insertions(+), 160 deletions(-) rename source/{common/config => extensions/config_subscription/grpc}/grpc_stream.h (100%) rename source/{common/config => extensions/config_subscription/grpc}/pausable_ack_queue.cc (95%) rename source/{common/config => extensions/config_subscription/grpc}/pausable_ack_queue.h (94%) rename source/{common/config => extensions/config_subscription/grpc}/update_ack.h (100%) rename source/{common/config => extensions/config_subscription/grpc}/watch_map.cc (99%) rename source/{common/config => extensions/config_subscription/grpc}/watch_map.h (100%) rename source/{common/config => extensions/config_subscription/grpc}/xds_source_id.cc (90%) rename source/{common/config => extensions/config_subscription/grpc}/xds_source_id.h (100%) rename test/{common/config => extensions/config_subscription/grpc}/grpc_stream_test.cc (99%) rename test/{common/config => extensions/config_subscription/grpc}/pausable_ack_queue_test.cc (97%) rename test/{common/config => extensions/config_subscription/grpc}/watch_map_test.cc (99%) rename test/{common/config => extensions/config_subscription/grpc}/xds_source_id_test.cc (92%) diff --git a/contrib/config/test/BUILD b/contrib/config/test/BUILD index adcfd31ef533..36a4dc4e4464 100644 --- a/contrib/config/test/BUILD +++ b/contrib/config/test/BUILD @@ -16,7 +16,7 @@ envoy_cc_test( ], deps = [ "//contrib/config/source:kv_store_xds_delegate", - "//source/common/config:xds_source_id_lib", + "//source/extensions/config_subscription/grpc:xds_source_id_lib", "//source/extensions/key_value/file_based:config_lib", "//test/mocks/api:api_mocks", "//test/mocks/event:event_mocks", @@ -43,7 +43,7 @@ envoy_cc_test( ":invalid_proto_kv_store_config_proto_cc_proto", "//contrib/config/source:kv_store_xds_delegate", "//envoy/common:key_value_store_interface", - "//source/common/config:xds_source_id_lib", + "//source/extensions/config_subscription/grpc:xds_source_id_lib", "//source/extensions/key_value/file_based:config_lib", "//test/common/grpc:grpc_client_integration_lib", "//test/integration:http_integration_lib", diff --git a/contrib/config/test/kv_store_xds_delegate_integration_test.cc b/contrib/config/test/kv_store_xds_delegate_integration_test.cc index 18a8836293b6..ebdfb279833a 100644 --- a/contrib/config/test/kv_store_xds_delegate_integration_test.cc +++ b/contrib/config/test/kv_store_xds_delegate_integration_test.cc @@ -6,7 +6,7 @@ #include "envoy/service/runtime/v3/rtds.pb.h" #include "envoy/service/secret/v3/sds.pb.h" -#include "source/common/config/xds_source_id.h" +#include "source/extensions/config_subscription/grpc/xds_source_id.h" #include "test/common/grpc/grpc_client_integration.h" #include "test/integration/http_integration.h" diff --git a/contrib/config/test/kv_store_xds_delegate_test.cc b/contrib/config/test/kv_store_xds_delegate_test.cc index 89747e100008..d69a5ad507f9 100644 --- a/contrib/config/test/kv_store_xds_delegate_test.cc +++ b/contrib/config/test/kv_store_xds_delegate_test.cc @@ -6,7 +6,7 @@ #include "envoy/service/runtime/v3/rtds.pb.h" #include "envoy/service/runtime/v3/rtds.pb.validate.h" -#include "source/common/config/xds_source_id.h" +#include "source/extensions/config_subscription/grpc/xds_source_id.h" #include "test/common/stats/stat_test_utility.h" #include "test/mocks/api/mocks.h" diff --git a/envoy/config/BUILD b/envoy/config/BUILD index 23fd71a5c19a..a660c39c59c7 100644 --- a/envoy/config/BUILD +++ b/envoy/config/BUILD @@ -135,7 +135,6 @@ envoy_cc_library( ":subscription_interface", ":typed_config_interface", "//envoy/protobuf:message_validator_interface", - "//source/common/config:update_ack_lib", "//source/common/protobuf", "@com_google_googleapis//google/rpc:status_cc_proto", ], diff --git a/source/common/config/BUILD b/source/common/config/BUILD index f7a25c71a45e..8f527194970c 100644 --- a/source/common/config/BUILD +++ b/source/common/config/BUILD @@ -85,23 +85,6 @@ envoy_cc_library( ], ) -envoy_cc_library( - name = "grpc_stream_lib", - hdrs = ["grpc_stream.h"], - deps = [ - ":utility_lib", - "//envoy/config:grpc_mux_interface", - "//envoy/config:subscription_interface", - "//envoy/grpc:async_client_interface", - "//envoy/upstream:cluster_manager_interface", - "//source/common/common:backoff_lib", - "//source/common/common:minimal_logger_lib", - "//source/common/common:token_bucket_impl_lib", - "//source/common/grpc:async_client_lib", - "//source/common/protobuf", - ], -) - envoy_cc_library( name = "null_grpc_mux_lib", hdrs = ["null_grpc_mux_impl.h"], @@ -137,16 +120,6 @@ envoy_cc_library( ], ) -envoy_cc_library( - name = "pausable_ack_queue_lib", - srcs = ["pausable_ack_queue.cc"], - hdrs = ["pausable_ack_queue.h"], - deps = [ - ":update_ack_lib", - "//source/common/common:assert_lib", - ], -) - envoy_cc_library( name = "protobuf_link_hacks", hdrs = ["protobuf_link_hacks.h"], @@ -224,18 +197,6 @@ envoy_cc_library( ], ) -envoy_cc_library( - name = "xds_context_params_lib", - srcs = ["xds_context_params.cc"], - hdrs = ["xds_context_params.h"], - deps = [ - "//source/common/common:macros", - "//source/common/protobuf:utility_lib", - "@com_github_cncf_udpa//xds/core/v3:pkg_cc_proto", - "@envoy_api//envoy/config/core/v3:pkg_cc_proto", - ], -) - envoy_cc_library( name = "xds_resource_lib", srcs = ["xds_resource.cc"], @@ -246,21 +207,6 @@ envoy_cc_library( ], ) -envoy_cc_library( - name = "xds_source_id_lib", - srcs = ["xds_source_id.cc"], - hdrs = ["xds_source_id.h"], - deps = [ - "//envoy/config:xds_resources_delegate_interface", - ], -) - -envoy_cc_library( - name = "update_ack_lib", - hdrs = ["update_ack.h"], - deps = ["@com_google_googleapis//google/rpc:status_cc_proto"], -) - envoy_cc_library( name = "utility_lib", srcs = ["utility.cc"], @@ -296,26 +242,6 @@ envoy_cc_library( ], ) -envoy_cc_library( - name = "watch_map_lib", - srcs = ["watch_map.cc"], - hdrs = ["watch_map.h"], - deps = [ - ":decoded_resource_lib", - ":utility_lib", - ":xds_resource_lib", - "//envoy/config:custom_config_validators_interface", - "//envoy/config:subscription_interface", - "//envoy/config:xds_config_tracker_interface", - "//source/common/common:assert_lib", - "//source/common/common:cleanup_lib", - "//source/common/common:minimal_logger_lib", - "//source/common/common:utility_lib", - "//source/common/protobuf", - "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", - ], -) - envoy_cc_library( name = "subscription_base_interface", hdrs = ["subscription_base.h"], @@ -351,6 +277,18 @@ envoy_cc_library( ], ) +envoy_cc_library( + name = "xds_context_params_lib", + srcs = ["xds_context_params.cc"], + hdrs = ["xds_context_params.h"], + deps = [ + "//source/common/common:macros", + "//source/common/protobuf:utility_lib", + "@com_github_cncf_udpa//xds/core/v3:pkg_cc_proto", + "@envoy_api//envoy/config/core/v3:pkg_cc_proto", + ], +) + envoy_cc_library( name = "well_known_names", srcs = ["well_known_names.cc"], diff --git a/source/extensions/config_subscription/grpc/BUILD b/source/extensions/config_subscription/grpc/BUILD index 9736956f4938..09f73cbc92e4 100644 --- a/source/extensions/config_subscription/grpc/BUILD +++ b/source/extensions/config_subscription/grpc/BUILD @@ -14,6 +14,8 @@ envoy_cc_library( srcs = ["grpc_mux_impl.cc"], hdrs = ["grpc_mux_impl.h"], deps = [ + ":grpc_stream_lib", + ":xds_source_id_lib", "//envoy/config:custom_config_validators_interface", "//envoy/config:grpc_mux_interface", "//envoy/config:subscription_interface", @@ -25,12 +27,10 @@ envoy_cc_library( "//source/common/common:utility_lib", "//source/common/config:api_version_lib", "//source/common/config:decoded_resource_lib", - "//source/common/config:grpc_stream_lib", "//source/common/config:ttl_lib", "//source/common/config:utility_lib", "//source/common/config:xds_context_params_lib", "//source/common/config:xds_resource_lib", - "//source/common/config:xds_source_id_lib", "//source/common/memory:utils_lib", "//source/common/protobuf", "@com_google_absl//absl/container:btree", @@ -44,13 +44,13 @@ envoy_cc_library( hdrs = ["new_grpc_mux_impl.h"], deps = [ ":delta_subscription_state_lib", + ":grpc_stream_lib", + ":pausable_ack_queue_lib", + ":watch_map_lib", "//envoy/config:custom_config_validators_interface", "//envoy/config:xds_config_tracker_interface", "//envoy/event:dispatcher_interface", "//envoy/grpc:async_client_interface", - "//source/common/config:grpc_stream_lib", - "//source/common/config:pausable_ack_queue_lib", - "//source/common/config:watch_map_lib", "//source/common/config:xds_context_params_lib", "//source/common/config:xds_resource_lib", "//source/common/memory:utils_lib", @@ -138,6 +138,8 @@ envoy_cc_library( "old_delta_subscription_state.h", ], deps = [ + ":pausable_ack_queue_lib", + ":watch_map_lib", "//envoy/config:subscription_interface", "//envoy/event:dispatcher_interface", "//source/common/common:assert_lib", @@ -145,12 +147,72 @@ envoy_cc_library( "//source/common/common:minimal_logger_lib", "//source/common/common:token_bucket_impl_lib", "//source/common/config:api_version_lib", - "//source/common/config:pausable_ack_queue_lib", "//source/common/config:ttl_lib", "//source/common/config:utility_lib", - "//source/common/config:watch_map_lib", "//source/common/grpc:common_lib", "//source/common/protobuf", "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", ], ) + +envoy_cc_library( + name = "grpc_stream_lib", + hdrs = ["grpc_stream.h"], + deps = [ + "//envoy/config:grpc_mux_interface", + "//envoy/config:subscription_interface", + "//envoy/grpc:async_client_interface", + "//envoy/upstream:cluster_manager_interface", + "//source/common/common:backoff_lib", + "//source/common/common:minimal_logger_lib", + "//source/common/common:token_bucket_impl_lib", + "//source/common/config:utility_lib", + "//source/common/grpc:async_client_lib", + "//source/common/protobuf", + ], +) + +envoy_cc_library( + name = "pausable_ack_queue_lib", + srcs = ["pausable_ack_queue.cc"], + hdrs = ["pausable_ack_queue.h"], + deps = [ + ":update_ack_lib", + "//source/common/common:assert_lib", + ], +) + +envoy_cc_library( + name = "xds_source_id_lib", + srcs = ["xds_source_id.cc"], + hdrs = ["xds_source_id.h"], + deps = [ + "//envoy/config:xds_resources_delegate_interface", + ], +) + +envoy_cc_library( + name = "update_ack_lib", + hdrs = ["update_ack.h"], + deps = ["@com_google_googleapis//google/rpc:status_cc_proto"], +) + +envoy_cc_library( + name = "watch_map_lib", + srcs = ["watch_map.cc"], + hdrs = ["watch_map.h"], + deps = [ + "//envoy/config:custom_config_validators_interface", + "//envoy/config:subscription_interface", + "//envoy/config:xds_config_tracker_interface", + "//source/common/common:assert_lib", + "//source/common/common:cleanup_lib", + "//source/common/common:minimal_logger_lib", + "//source/common/common:utility_lib", + "//source/common/config:decoded_resource_lib", + "//source/common/config:utility_lib", + "//source/common/config:xds_resource_lib", + "//source/common/protobuf", + "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc index 3dce1268b18d..c5ba997b6f5b 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc @@ -4,9 +4,9 @@ #include "source/common/config/decoded_resource_impl.h" #include "source/common/config/utility.h" -#include "source/common/config/xds_source_id.h" #include "source/common/memory/utils.h" #include "source/common/protobuf/protobuf.h" +#include "source/extensions/config_subscription/grpc/xds_source_id.h" #include "absl/container/btree_map.h" #include "absl/container/node_hash_set.h" diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.h b/source/extensions/config_subscription/grpc/grpc_mux_impl.h index 280a37af6e87..83ac9c558c7e 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.h @@ -20,11 +20,11 @@ #include "source/common/common/logger.h" #include "source/common/common/utility.h" #include "source/common/config/api_version.h" -#include "source/common/config/grpc_stream.h" #include "source/common/config/ttl.h" #include "source/common/config/utility.h" #include "source/common/config/xds_context_params.h" #include "source/common/config/xds_resource.h" +#include "source/extensions/config_subscription/grpc/grpc_stream.h" #include "absl/container/node_hash_map.h" #include "xds/core/v3/resource_name.pb.h" diff --git a/source/common/config/grpc_stream.h b/source/extensions/config_subscription/grpc/grpc_stream.h similarity index 100% rename from source/common/config/grpc_stream.h rename to source/extensions/config_subscription/grpc/grpc_stream.h diff --git a/source/extensions/config_subscription/grpc/new_delta_subscription_state.h b/source/extensions/config_subscription/grpc/new_delta_subscription_state.h index dae05387428f..03d949bac1b8 100644 --- a/source/extensions/config_subscription/grpc/new_delta_subscription_state.h +++ b/source/extensions/config_subscription/grpc/new_delta_subscription_state.h @@ -10,9 +10,9 @@ #include "source/common/common/assert.h" #include "source/common/common/logger.h" #include "source/common/config/api_version.h" -#include "source/common/config/pausable_ack_queue.h" #include "source/common/config/ttl.h" -#include "source/common/config/watch_map.h" +#include "source/extensions/config_subscription/grpc/pausable_ack_queue.h" +#include "source/extensions/config_subscription/grpc/watch_map.h" #include "absl/container/node_hash_map.h" diff --git a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h index fd694c542102..39a27eeed84b 100644 --- a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.h @@ -11,12 +11,12 @@ #include "source/common/common/logger.h" #include "source/common/config/api_version.h" -#include "source/common/config/grpc_stream.h" -#include "source/common/config/pausable_ack_queue.h" -#include "source/common/config/watch_map.h" #include "source/common/grpc/common.h" #include "source/common/runtime/runtime_features.h" #include "source/extensions/config_subscription/grpc/delta_subscription_state.h" +#include "source/extensions/config_subscription/grpc/grpc_stream.h" +#include "source/extensions/config_subscription/grpc/pausable_ack_queue.h" +#include "source/extensions/config_subscription/grpc/watch_map.h" namespace Envoy { namespace Config { diff --git a/source/extensions/config_subscription/grpc/old_delta_subscription_state.h b/source/extensions/config_subscription/grpc/old_delta_subscription_state.h index f1efcb554445..d5997c953bd9 100644 --- a/source/extensions/config_subscription/grpc/old_delta_subscription_state.h +++ b/source/extensions/config_subscription/grpc/old_delta_subscription_state.h @@ -10,9 +10,9 @@ #include "source/common/common/assert.h" #include "source/common/common/logger.h" #include "source/common/config/api_version.h" -#include "source/common/config/pausable_ack_queue.h" #include "source/common/config/ttl.h" -#include "source/common/config/watch_map.h" +#include "source/extensions/config_subscription/grpc/pausable_ack_queue.h" +#include "source/extensions/config_subscription/grpc/watch_map.h" #include "absl/container/node_hash_map.h" diff --git a/source/common/config/pausable_ack_queue.cc b/source/extensions/config_subscription/grpc/pausable_ack_queue.cc similarity index 95% rename from source/common/config/pausable_ack_queue.cc rename to source/extensions/config_subscription/grpc/pausable_ack_queue.cc index 6208fd909fb4..fca69a07851c 100644 --- a/source/common/config/pausable_ack_queue.cc +++ b/source/extensions/config_subscription/grpc/pausable_ack_queue.cc @@ -1,4 +1,4 @@ -#include "source/common/config/pausable_ack_queue.h" +#include "source/extensions/config_subscription/grpc/pausable_ack_queue.h" #include diff --git a/source/common/config/pausable_ack_queue.h b/source/extensions/config_subscription/grpc/pausable_ack_queue.h similarity index 94% rename from source/common/config/pausable_ack_queue.h rename to source/extensions/config_subscription/grpc/pausable_ack_queue.h index 07af25fa9bfd..a3140b7831ad 100644 --- a/source/common/config/pausable_ack_queue.h +++ b/source/extensions/config_subscription/grpc/pausable_ack_queue.h @@ -2,7 +2,7 @@ #include -#include "source/common/config/update_ack.h" +#include "source/extensions/config_subscription/grpc/update_ack.h" #include "absl/container/flat_hash_map.h" diff --git a/source/common/config/update_ack.h b/source/extensions/config_subscription/grpc/update_ack.h similarity index 100% rename from source/common/config/update_ack.h rename to source/extensions/config_subscription/grpc/update_ack.h diff --git a/source/common/config/watch_map.cc b/source/extensions/config_subscription/grpc/watch_map.cc similarity index 99% rename from source/common/config/watch_map.cc rename to source/extensions/config_subscription/grpc/watch_map.cc index 803bc729d210..b9a1907fd3d3 100644 --- a/source/common/config/watch_map.cc +++ b/source/extensions/config_subscription/grpc/watch_map.cc @@ -1,4 +1,4 @@ -#include "source/common/config/watch_map.h" +#include "source/extensions/config_subscription/grpc/watch_map.h" #include "envoy/service/discovery/v3/discovery.pb.h" diff --git a/source/common/config/watch_map.h b/source/extensions/config_subscription/grpc/watch_map.h similarity index 100% rename from source/common/config/watch_map.h rename to source/extensions/config_subscription/grpc/watch_map.h diff --git a/source/extensions/config_subscription/grpc/xds_mux/BUILD b/source/extensions/config_subscription/grpc/xds_mux/BUILD index 9dd3a7318c7b..50cba69c40a6 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/BUILD +++ b/source/extensions/config_subscription/grpc/xds_mux/BUILD @@ -32,9 +32,9 @@ envoy_cc_library( "//source/common/config:api_version_lib", "//source/common/config:decoded_resource_lib", "//source/common/config:utility_lib", - "//source/common/config:xds_source_id_lib", "//source/common/grpc:common_lib", "//source/common/protobuf", + "//source/extensions/config_subscription/grpc:xds_source_id_lib", "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", ], ) @@ -50,8 +50,8 @@ envoy_cc_library( "//envoy/local_info:local_info_interface", "//source/common/common:minimal_logger_lib", "//source/common/config:ttl_lib", - "//source/common/config:update_ack_lib", "//source/common/config:utility_lib", + "//source/extensions/config_subscription/grpc:update_ack_lib", "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", ], ) @@ -65,12 +65,12 @@ envoy_cc_extension( ":sotw_subscription_state_lib", "//envoy/event:dispatcher_interface", "//envoy/grpc:async_client_interface", - "//source/common/config:grpc_stream_lib", - "//source/common/config:pausable_ack_queue_lib", - "//source/common/config:watch_map_lib", "//source/common/config:xds_context_params_lib", "//source/common/config:xds_resource_lib", "//source/common/memory:utils_lib", + "//source/extensions/config_subscription/grpc:grpc_stream_lib", + "//source/extensions/config_subscription/grpc:pausable_ack_queue_lib", + "//source/extensions/config_subscription/grpc:watch_map_lib", "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h index e5434f9eaaeb..7669ca73cffd 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.h @@ -20,10 +20,10 @@ #include "source/common/common/logger.h" #include "source/common/common/utility.h" #include "source/common/config/api_version.h" -#include "source/common/config/grpc_stream.h" -#include "source/common/config/pausable_ack_queue.h" -#include "source/common/config/watch_map.h" #include "source/common/grpc/common.h" +#include "source/extensions/config_subscription/grpc/grpc_stream.h" +#include "source/extensions/config_subscription/grpc/pausable_ack_queue.h" +#include "source/extensions/config_subscription/grpc/watch_map.h" #include "source/extensions/config_subscription/grpc/xds_mux/delta_subscription_state.h" #include "source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.h" diff --git a/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc b/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc index e1a887663ffa..18bafc1a8015 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc +++ b/source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.cc @@ -1,7 +1,7 @@ #include "source/extensions/config_subscription/grpc/xds_mux/sotw_subscription_state.h" #include "source/common/config/utility.h" -#include "source/common/config/xds_source_id.h" +#include "source/extensions/config_subscription/grpc/xds_source_id.h" namespace Envoy { namespace Config { diff --git a/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h b/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h index 41223d0829d4..3c7ec8d0c542 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h +++ b/source/extensions/config_subscription/grpc/xds_mux/subscription_state.h @@ -11,9 +11,9 @@ #include "envoy/service/discovery/v3/discovery.pb.h" #include "source/common/config/ttl.h" -#include "source/common/config/update_ack.h" #include "source/common/config/utility.h" #include "source/common/protobuf/protobuf.h" +#include "source/extensions/config_subscription/grpc/update_ack.h" #include "absl/strings/string_view.h" diff --git a/source/common/config/xds_source_id.cc b/source/extensions/config_subscription/grpc/xds_source_id.cc similarity index 90% rename from source/common/config/xds_source_id.cc rename to source/extensions/config_subscription/grpc/xds_source_id.cc index 090f1d4bff1e..8dcd7da287f3 100644 --- a/source/common/config/xds_source_id.cc +++ b/source/extensions/config_subscription/grpc/xds_source_id.cc @@ -1,4 +1,4 @@ -#include "source/common/config/xds_source_id.h" +#include "source/extensions/config_subscription/grpc/xds_source_id.h" #include "absl/strings/str_cat.h" diff --git a/source/common/config/xds_source_id.h b/source/extensions/config_subscription/grpc/xds_source_id.h similarity index 100% rename from source/common/config/xds_source_id.h rename to source/extensions/config_subscription/grpc/xds_source_id.h diff --git a/test/common/config/BUILD b/test/common/config/BUILD index 60f8f952f964..dd5035c98579 100644 --- a/test/common/config/BUILD +++ b/test/common/config/BUILD @@ -31,22 +31,6 @@ envoy_cc_test( ], ) -envoy_cc_test( - name = "grpc_stream_test", - srcs = ["grpc_stream_test.cc"], - deps = [ - "//source/common/config:grpc_stream_lib", - "//test/common/stats:stat_test_utility_lib", - "//test/mocks:common_lib", - "//test/mocks/config:config_mocks", - "//test/mocks/event:event_mocks", - "//test/mocks/grpc:grpc_mocks", - "//test/test_common:logging_lib", - "//test/test_common:simulated_time_system_lib", - "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", - ], -) - envoy_cc_test( name = "grpc_subscription_impl_test", srcs = ["grpc_subscription_impl_test.cc"], @@ -112,14 +96,6 @@ envoy_cc_test( ], ) -envoy_cc_test( - name = "pausable_ack_queue_test", - srcs = ["pausable_ack_queue_test.cc"], - deps = [ - "//source/common/config:pausable_ack_queue_lib", - ], -) - envoy_cc_test( name = "metadata_test", srcs = ["metadata_test.cc"], @@ -182,20 +158,6 @@ envoy_cc_test( ], ) -envoy_cc_test( - name = "watch_map_test", - srcs = ["watch_map_test.cc"], - deps = [ - "//envoy/config:xds_config_tracker_interface", - "//source/common/config:watch_map_lib", - "//test/mocks/config:config_mocks", - "//test/mocks/config:custom_config_validators_mocks", - "//test/test_common:utility_lib", - "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto", - "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", - ], -) - envoy_proto_library( name = "dummy_config_proto", srcs = ["dummy_config.proto"], @@ -289,11 +251,3 @@ envoy_cc_test( "//test/test_common:test_runtime_lib", ], ) - -envoy_cc_test( - name = "xds_source_id_test", - srcs = ["xds_source_id_test.cc"], - deps = [ - "//source/common/config:xds_source_id_lib", - ], -) diff --git a/test/extensions/config_subscription/grpc/BUILD b/test/extensions/config_subscription/grpc/BUILD index a6ee6147e4f4..b352ca281b13 100644 --- a/test/extensions/config_subscription/grpc/BUILD +++ b/test/extensions/config_subscription/grpc/BUILD @@ -195,3 +195,49 @@ envoy_cc_test( "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", ], ) + +envoy_cc_test( + name = "grpc_stream_test", + srcs = ["grpc_stream_test.cc"], + deps = [ + "//source/extensions/config_subscription/grpc:grpc_stream_lib", + "//test/common/stats:stat_test_utility_lib", + "//test/mocks:common_lib", + "//test/mocks/config:config_mocks", + "//test/mocks/event:event_mocks", + "//test/mocks/grpc:grpc_mocks", + "//test/test_common:logging_lib", + "//test/test_common:simulated_time_system_lib", + "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", + ], +) + +envoy_cc_test( + name = "pausable_ack_queue_test", + srcs = ["pausable_ack_queue_test.cc"], + deps = [ + "//source/extensions/config_subscription/grpc:pausable_ack_queue_lib", + ], +) + +envoy_cc_test( + name = "watch_map_test", + srcs = ["watch_map_test.cc"], + deps = [ + "//envoy/config:xds_config_tracker_interface", + "//source/extensions/config_subscription/grpc:watch_map_lib", + "//test/mocks/config:config_mocks", + "//test/mocks/config:custom_config_validators_mocks", + "//test/test_common:utility_lib", + "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto", + "@envoy_api//envoy/service/discovery/v3:pkg_cc_proto", + ], +) + +envoy_cc_test( + name = "xds_source_id_test", + srcs = ["xds_source_id_test.cc"], + deps = [ + "//source/extensions/config_subscription/grpc:xds_source_id_lib", + ], +) diff --git a/test/common/config/grpc_stream_test.cc b/test/extensions/config_subscription/grpc/grpc_stream_test.cc similarity index 99% rename from test/common/config/grpc_stream_test.cc rename to test/extensions/config_subscription/grpc/grpc_stream_test.cc index 259d2619cecd..6d594c2ff2f6 100644 --- a/test/common/config/grpc_stream_test.cc +++ b/test/extensions/config_subscription/grpc/grpc_stream_test.cc @@ -1,7 +1,7 @@ #include "envoy/service/discovery/v3/discovery.pb.h" -#include "source/common/config/grpc_stream.h" #include "source/common/protobuf/protobuf.h" +#include "source/extensions/config_subscription/grpc/grpc_stream.h" #include "test/common/stats/stat_test_utility.h" #include "test/mocks/common.h" diff --git a/test/common/config/pausable_ack_queue_test.cc b/test/extensions/config_subscription/grpc/pausable_ack_queue_test.cc similarity index 97% rename from test/common/config/pausable_ack_queue_test.cc rename to test/extensions/config_subscription/grpc/pausable_ack_queue_test.cc index f984193bf837..e52e3a32b414 100644 --- a/test/common/config/pausable_ack_queue_test.cc +++ b/test/extensions/config_subscription/grpc/pausable_ack_queue_test.cc @@ -1,4 +1,4 @@ -#include "source/common/config/pausable_ack_queue.h" +#include "source/extensions/config_subscription/grpc/pausable_ack_queue.h" #include "gtest/gtest.h" diff --git a/test/common/config/watch_map_test.cc b/test/extensions/config_subscription/grpc/watch_map_test.cc similarity index 99% rename from test/common/config/watch_map_test.cc rename to test/extensions/config_subscription/grpc/watch_map_test.cc index 76cfe3176836..dcdbe9a418ee 100644 --- a/test/common/config/watch_map_test.cc +++ b/test/extensions/config_subscription/grpc/watch_map_test.cc @@ -6,7 +6,7 @@ #include "envoy/service/discovery/v3/discovery.pb.h" #include "envoy/stats/scope.h" -#include "source/common/config/watch_map.h" +#include "source/extensions/config_subscription/grpc/watch_map.h" #include "test/mocks/config/custom_config_validators.h" #include "test/mocks/config/mocks.h" diff --git a/test/common/config/xds_source_id_test.cc b/test/extensions/config_subscription/grpc/xds_source_id_test.cc similarity index 92% rename from test/common/config/xds_source_id_test.cc rename to test/extensions/config_subscription/grpc/xds_source_id_test.cc index c138d56cd3b1..c3ad0a37bf7c 100644 --- a/test/common/config/xds_source_id_test.cc +++ b/test/extensions/config_subscription/grpc/xds_source_id_test.cc @@ -1,4 +1,4 @@ -#include "source/common/config/xds_source_id.h" +#include "source/extensions/config_subscription/grpc/xds_source_id.h" #include "gtest/gtest.h" diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index e26c99615b49..76f798634a85 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -7,7 +7,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/api:82.6" "source/common/api/posix:81.3" "source/common/common/posix:92.7" -"source/common/config:95.6" +"source/common/config:94.8" "source/common/crypto:88.1" "source/common/event:95.1" # Emulated edge events guards don't report LCOV "source/common/filesystem/posix:96.2" # FileReadToEndNotReadable fails in some env; createPath can't test all failure branches. From d732f9a5a58ca412d5dc13835c8f06897cfb1c5f Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 1 Jun 2023 13:38:30 -0400 Subject: [PATCH 157/228] router: cleaning up 1xx coalescing now done in codec filter (#27736) Signed-off-by: Alyssa Wilk --- source/common/router/router.cc | 12 +------- source/common/router/router.h | 8 ++--- test/common/router/router_test.cc | 50 ------------------------------- 3 files changed, 4 insertions(+), 66 deletions(-) diff --git a/source/common/router/router.cc b/source/common/router/router.cc index b03ea8b89a5a..6e50cd72c999 100644 --- a/source/common/router/router.cc +++ b/source/common/router/router.cc @@ -1397,17 +1397,7 @@ void Filter::onUpstream1xxHeaders(Http::ResponseHeaderMapPtr&& headers, // the complexity until someone asks for it. retry_state_.reset(); - // We coalesce 1xx headers here, to prevent encoder filters and HCM from having to worry - // about this. This is done in the router filter, rather than UpstreamRequest, since we want to - // potentially coalesce across retries and multiple upstream requests in the future, even though - // we currently don't support retry after 1xx. - // It's plausible that this functionality might need to move to HCM in the future for internal - // redirects, but we would need to maintain the "only call encode1xxHeaders() once" - // invariant. - if (!downstream_1xx_headers_encoded_) { - downstream_1xx_headers_encoded_ = true; - callbacks_->encode1xxHeaders(std::move(headers)); - } + callbacks_->encode1xxHeaders(std::move(headers)); } void Filter::resetAll() { diff --git a/source/common/router/router.h b/source/common/router/router.h index 3245b1452147..c3c3b61c8180 100644 --- a/source/common/router/router.h +++ b/source/common/router/router.h @@ -380,10 +380,9 @@ class Filter : Logger::Loggable, public: Filter(FilterConfig& config, FilterStats& stats) : config_(config), stats_(stats), grpc_request_(false), exclude_http_code_stats_(false), - downstream_1xx_headers_encoded_(false), downstream_response_started_(false), - downstream_end_stream_(false), is_retry_(false), request_buffer_overflowed_(false), - streaming_shadows_( - Runtime::runtimeFeatureEnabled("envoy.reloadable_features.streaming_shadow")) {} + downstream_response_started_(false), downstream_end_stream_(false), is_retry_(false), + request_buffer_overflowed_(false), streaming_shadows_(Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.streaming_shadow")) {} ~Filter() override; @@ -672,7 +671,6 @@ class Filter : Logger::Loggable, FilterUtility::HedgingParams hedging_params_; bool grpc_request_ : 1; bool exclude_http_code_stats_ : 1; - bool downstream_1xx_headers_encoded_ : 1; bool downstream_response_started_ : 1; bool downstream_end_stream_ : 1; bool is_retry_ : 1; diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc index de30e05444be..82f7711cb50c 100644 --- a/test/common/router/router_test.cc +++ b/test/common/router/router_test.cc @@ -3504,56 +3504,6 @@ TEST_F(RouterTest, RetryUpstreamResetResponseStarted) { callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); } -// The router filter is responsible for not propagating 100-continue headers after the initial 100. -// TODO(alyssawilk) remove coalescing with old code deprecation. -TEST_F(RouterTest, Coalesce1xxHeaders) { - // Setup. - NiceMock encoder1; - Http::ResponseDecoder* response_decoder = nullptr; - expectNewStreamWithImmediateEncoder(encoder1, &response_decoder, Http::Protocol::Http10); - - expectResponseTimerCreate(); - - Http::TestRequestHeaderMapImpl headers; - HttpTestUtility::addDefaultHeaders(headers); - router_->decodeHeaders(headers, true); - EXPECT_EQ(1U, - callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); - - // Initial 100-continue, this is processed normally. - EXPECT_CALL(callbacks_, encode1xxHeaders_(_)); - { - Http::ResponseHeaderMapPtr continue_headers( - new Http::TestResponseHeaderMapImpl{{":status", "100"}}); - // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) - response_decoder->decode1xxHeaders(std::move(continue_headers)); - } - EXPECT_EQ( - 1U, - cm_.thread_local_cluster_.cluster_.info_->stats_store_.counter("upstream_rq_100").value()); - - // No encode1xxHeaders() invocation for the second 100-continue (but we continue to track - // stats from upstream). - EXPECT_CALL(callbacks_, encode1xxHeaders_(_)).Times(0); - { - Http::ResponseHeaderMapPtr continue_headers( - new Http::TestResponseHeaderMapImpl{{":status", "100"}}); - // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) - response_decoder->decode1xxHeaders(std::move(continue_headers)); - } - // With the filter manager coalescing, the router only sees 1 100. - EXPECT_EQ( - 1U, - cm_.thread_local_cluster_.cluster_.info_->stats_store_.counter("upstream_rq_100").value()); - - // Reset stream and cleanup. - EXPECT_CALL(cm_.thread_local_cluster_.conn_pool_.host_->outlier_detector_, - putResult(Upstream::Outlier::Result::LocalOriginConnectFailed, _)); - encoder1.stream_.resetStream(Http::StreamResetReason::RemoteReset); - EXPECT_EQ(1U, - callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value()); -} - TEST_F(RouterTest, RetryUpstreamReset1xxResponseStarted) { NiceMock encoder1; Http::ResponseDecoder* response_decoder = nullptr; From 5fefd9d4f78d169e3cb71f4e2c53a1b5d575334b Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 1 Jun 2023 20:48:43 +0100 Subject: [PATCH 158/228] changelog: Add `wasmtime`, `c-ares` CVE updates (#27753) Signed-off-by: Ryan Northey --- changelogs/current.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index c6eff7753bf3..aff04bd00c7d 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -140,6 +140,18 @@ bug_fixes: This was fixed now by marking the cookie as httpOnly. This behavioral change can be temporarily reverted by setting runtime guard ``envoy.reloadable_features.oauth_make_token_cookie_httponly`` to false. +- area: dependency + change: | + update Wasmtime and related deps -> 9.0.3 to resolve + `CVE-2023-30624 `_. +- area: dependency + change: | + update C-ares -> 1.91.1 to resolve: + + - `CVE-2023-31130 `_. + - `CVE-2023-31147 `_. + - `CVE-2023-31124 `_. + - `CVE-2023-32067 `_. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` From 517d2dba98ba7691d1642caf2ef4dd42a6daf029 Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Thu, 1 Jun 2023 23:11:24 -0400 Subject: [PATCH 159/228] docs: Add info about xDS cluster ordering in the Bootstrap (#27706) Clarification for a workaround to #27702. Signed-off-by: Ali Beyad --- docs/root/api-docs/xds_protocol.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/root/api-docs/xds_protocol.rst b/docs/root/api-docs/xds_protocol.rst index 0ba5abb942ed..a9c36ef1f4f6 100644 --- a/docs/root/api-docs/xds_protocol.rst +++ b/docs/root/api-docs/xds_protocol.rst @@ -252,6 +252,14 @@ how to contact the ADS server, which will be used whenever a :ref:`ConfigSource management server) contains an :ref:`AggregatedConfigSource ` message. +A current limitation in Envoy is that any xDS :ref:`Cluster ` resources +should be specified first in the `static_resources` field of the Bootstrap configuration prior to any static +:ref:`Cluster ` resources that depend on the xDS cluster. Failure to do +so will result in slower Envoy initialization (see the `GitHub issue `_ +for details). As an example, if a cluster depends on an xDS :ref:`Cluster ` +for SDS to configure the secrets on a transport socket, the xDS :ref:`Cluster ` +should be specified first in the `static_resources` field, before the cluster with the transport socket secret is specified. + In a gRPC client that uses xDS, only ADS is supported, and the bootstrap file contains the name of the ADS server, which will be used for all resources. The :ref:`ConfigSource ` messages in the :ref:`Listener ` and From 4942648504249567f41691ca8fe3258ad1acd3f6 Mon Sep 17 00:00:00 2001 From: code Date: Fri, 2 Jun 2023 16:37:07 +0800 Subject: [PATCH 160/228] generic proxy: fix flaky integration test (#27763) Signed-off-by: wbpcode --- .../generic_proxy/filters/network/test/integration_test.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/generic_proxy/filters/network/test/integration_test.cc b/contrib/generic_proxy/filters/network/test/integration_test.cc index 53c948f247da..d68f2d3b154e 100644 --- a/contrib/generic_proxy/filters/network/test/integration_test.cc +++ b/contrib/generic_proxy/filters/network/test/integration_test.cc @@ -410,8 +410,12 @@ TEST_P(IntegrationTest, MultipleRequests) { request_2.protocol_ = "fake_fake_fake"; request_2.data_ = {{"version", "v1"}, {"stream_id", "2"}}; - // Send the second request with the same stream id and expect the connection to be closed. + // Reset request encoder callback. + request_encoder_callback_ = std::make_shared(); + + // Send the second request with the different stream id and expect the connection to be alive. sendRequestForTest(request_2); + waitForUpstreamRequestForTest(request_encoder_callback_->request_bytes_, nullptr); FakeStreamCodecFactory::FakeResponse response_2; response_2.protocol_ = "fake_fake_fake"; From 08b7a8922702b49c0f2191ee58a48a4850206a35 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 2 Jun 2023 15:37:04 +0300 Subject: [PATCH 161/228] sds: Add support to hot-reload CRL files (#27751) * sds: Add support to hot-reload CRL files Signed-off-by: Tero Saarni --- .../transport_sockets/tls/v3/common.proto | 5 +++++ changelogs/current.yaml | 6 ++++++ source/common/secret/sds_api.cc | 16 +++++++++++----- source/common/secret/sds_api.h | 3 +++ test/common/secret/sds_api_test.cc | 16 ++++++++++++++-- 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/api/envoy/extensions/transport_sockets/tls/v3/common.proto b/api/envoy/extensions/transport_sockets/tls/v3/common.proto index 4780858efa36..66c8c7978def 100644 --- a/api/envoy/extensions/transport_sockets/tls/v3/common.proto +++ b/api/envoy/extensions/transport_sockets/tls/v3/common.proto @@ -505,6 +505,11 @@ message CertificateValidationContext { // from that chain. This default behavior can be altered by setting // :ref:`only_verify_leaf_cert_crl ` to // true. + // + // If ``crl`` is a filesystem path, a watch will be added to the parent + // directory for any file moves to support rotation. This currently only + // applies to dynamic secrets, when the ``CertificateValidationContext`` is + // delivered via SDS. config.core.v3.DataSource crl = 7; // If specified, Envoy will not reject expired certificates. diff --git a/changelogs/current.yaml b/changelogs/current.yaml index aff04bd00c7d..7fc60f892d9a 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -292,6 +292,12 @@ new_features: change: | added CEL(Common Expression Language) matcher support :ref:`CEL data input ` and :ref:`CEL input matcher `. +- area: tls + change: | + Added support for hot-reloading CRL file when the file changes on disk. + This works with dynamic secrets when + :ref:`CertificateValidationContext ` + is delivered via SDS. deprecated: - area: access_log diff --git a/source/common/secret/sds_api.cc b/source/common/secret/sds_api.cc index 253391f44940..e20ca282f22e 100644 --- a/source/common/secret/sds_api.cc +++ b/source/common/secret/sds_api.cc @@ -195,11 +195,17 @@ std::vector TlsCertificateSdsApi::getDataSourceFilenames() { std::vector CertificateValidationContextSdsApi::getDataSourceFilenames() { std::vector files; - if (sds_certificate_validation_context_secrets_ && - sds_certificate_validation_context_secrets_->has_trusted_ca() && - sds_certificate_validation_context_secrets_->trusted_ca().specifier_case() == - envoy::config::core::v3::DataSource::SpecifierCase::kFilename) { - files.push_back(sds_certificate_validation_context_secrets_->trusted_ca().filename()); + if (sds_certificate_validation_context_secrets_) { + if (sds_certificate_validation_context_secrets_->has_trusted_ca() && + sds_certificate_validation_context_secrets_->trusted_ca().specifier_case() == + envoy::config::core::v3::DataSource::SpecifierCase::kFilename) { + files.push_back(sds_certificate_validation_context_secrets_->trusted_ca().filename()); + } + if (sds_certificate_validation_context_secrets_->has_crl() && + sds_certificate_validation_context_secrets_->crl().specifier_case() == + envoy::config::core::v3::DataSource::SpecifierCase::kFilename) { + files.push_back(sds_certificate_validation_context_secrets_->crl().filename()); + } } return files; } diff --git a/source/common/secret/sds_api.h b/source/common/secret/sds_api.h index edc5db1e0ad8..2c5a08bc5281 100644 --- a/source/common/secret/sds_api.h +++ b/source/common/secret/sds_api.h @@ -284,6 +284,9 @@ class CertificateValidationContextSdsApi : public SdsApi, // We replace path based secrets with inlined secrets on update. resolveDataSource(files, *resolved_certificate_validation_context_secrets_->mutable_trusted_ca()); + if (sds_certificate_validation_context_secrets_->has_crl()) { + resolveDataSource(files, *resolved_certificate_validation_context_secrets_->mutable_crl()); + } } void diff --git a/test/common/secret/sds_api_test.cc b/test/common/secret/sds_api_test.cc index de86349a0783..6cb640f23464 100644 --- a/test/common/secret/sds_api_test.cc +++ b/test/common/secret/sds_api_test.cc @@ -293,6 +293,7 @@ class CertificateValidationContextSdsRotationApiTest : public testing::TestWithP } void onConfigUpdate(const std::string& trusted_ca_path, const std::string& trusted_ca_value, + const std::string& crl_path, const std::string& crl_value, const std::string& watch_path) { const std::string yaml = fmt::format( R"EOF( @@ -300,17 +301,24 @@ class CertificateValidationContextSdsRotationApiTest : public testing::TestWithP validation_context: trusted_ca: filename: "{}" + crl: + filename: "{}" allow_expired_certificate: true )EOF", - trusted_ca_path); + trusted_ca_path, crl_path); envoy::extensions::transport_sockets::tls::v3::Secret typed_secret; TestUtility::loadFromYaml(yaml, typed_secret); const auto decoded_resources = TestUtility::decodeResources({typed_secret}); auto* watcher = new Filesystem::MockWatcher(); EXPECT_CALL(filesystem_, fileReadToEnd(trusted_ca_path)).WillOnce(Return(trusted_ca_value)); + EXPECT_CALL(filesystem_, fileReadToEnd(crl_path)).WillOnce(Return(crl_value)); EXPECT_CALL(secret_callback_, onAddOrUpdateSecret()); EXPECT_CALL(mock_dispatcher_, createFilesystemWatcher_()).WillOnce(Return(watcher)); + EXPECT_CALL(*watcher, addWatch(watch_path, Filesystem::Watcher::Events::MovedTo, _)) + .WillOnce(Invoke([this](absl::string_view, uint32_t, Filesystem::Watcher::OnChangedCb cb) { + watch_cbs_.push_back(cb); + })); EXPECT_CALL(*watcher, addWatch(watch_path, Filesystem::Watcher::Events::MovedTo, _)) .WillOnce(Invoke([this](absl::string_view, uint32_t, Filesystem::Watcher::OnChangedCb cb) { watch_cbs_.push_back(cb); @@ -417,15 +425,19 @@ TEST_P(TlsCertificateSdsRotationApiTest, FailedRotation) { // Basic rotation of CertificateValidationContext. TEST_P(CertificateValidationContextSdsRotationApiTest, CertificateValidationContext) { InSequence s; - onConfigUpdate("/foo/bar/ca.pem", "a", "/foo/bar/"); + onConfigUpdate("/foo/bar/ca.pem", "a", "/foo/bar/crl.pem", "b", "/foo/bar/"); EXPECT_CALL(filesystem_, fileReadToEnd("/foo/bar/ca.pem")).WillOnce(Return("c")); + EXPECT_CALL(filesystem_, fileReadToEnd("/foo/bar/crl.pem")).WillOnce(Return("d")); EXPECT_CALL(filesystem_, fileReadToEnd("/foo/bar/ca.pem")).WillOnce(Return("c")); + EXPECT_CALL(filesystem_, fileReadToEnd("/foo/bar/crl.pem")).WillOnce(Return("d")); + EXPECT_CALL(secret_callback_, onAddOrUpdateSecret()); watch_cbs_[0](Filesystem::Watcher::Events::MovedTo); const auto& secret = *sds_api_->secret(); EXPECT_EQ("c", secret.trusted_ca().inline_bytes()); + EXPECT_EQ("d", secret.crl().inline_bytes()); } // Hash consistency verification prevents races. From d29dcb1ce058edcfcd80737c0a097f776b6759fa Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 2 Jun 2023 18:53:52 +0100 Subject: [PATCH 162/228] ci: Replace python go proto script with ci target (#27675) Signed-off-by: Ryan Northey --- ci/build_setup.sh | 6 ++ ci/do_ci.sh | 55 ++++++++-- tools/api/generate_go_protobuf.py | 161 +----------------------------- 3 files changed, 55 insertions(+), 167 deletions(-) diff --git a/ci/build_setup.sh b/ci/build_setup.sh index 9ad3a8dd0577..f0de186abd60 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -7,6 +7,10 @@ set -e +if [[ -n "$NO_BUILD_SETUP" ]]; then + exit +fi + export PPROF_PATH=/thirdparty_build/bin/pprof [ -z "${NUM_CPUS}" ] && NUM_CPUS=$(grep -c ^processor /proc/cpuinfo) @@ -196,3 +200,5 @@ if [[ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "true" ]]; then else echo "Skip setting up Envoy Filter Example." fi + +export NO_BUILD_SETUP=1 diff --git a/ci/do_ci.sh b/ci/do_ci.sh index b0f178293f05..2d7b61298396 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -8,17 +8,15 @@ set -e # TODO(phlax): Clarify and/or integrate SRCDIR and ENVOY_SRCDIR export SRCDIR="${SRCDIR:-$PWD}" export ENVOY_SRCDIR="${ENVOY_SRCDIR:-$PWD}" -NO_BUILD_SETUP="${NO_BUILD_SETUP:-}" -if [[ -z "$NO_BUILD_SETUP" ]]; then - # shellcheck source=ci/setup_cache.sh - . "$(dirname "$0")"/setup_cache.sh - # shellcheck source=ci/build_setup.sh - . "$(dirname "$0")"/build_setup.sh +# shellcheck source=ci/setup_cache.sh +. "$(dirname "$0")"/setup_cache.sh +# shellcheck source=ci/build_setup.sh +. "$(dirname "$0")"/build_setup.sh + +echo "building using ${NUM_CPUS} CPUs" +echo "building for ${ENVOY_BUILD_ARCH}" - echo "building using ${NUM_CPUS} CPUs" - echo "building for ${ENVOY_BUILD_ARCH}" -fi cd "${SRCDIR}" if [[ "${ENVOY_BUILD_ARCH}" == "x86_64" ]]; then @@ -202,8 +200,6 @@ case $CI_TARGET in //tools/protoprint:protoprint_test echo "Validating API structure..." "${ENVOY_SRCDIR}"/tools/api/validate_structure.py - echo "Validate Golang protobuf generation..." - "${ENVOY_SRCDIR}"/tools/api/generate_go_protobuf.py echo "Testing API..." bazel_with_collection \ test "${BAZEL_BUILD_OPTIONS[@]}" \ @@ -215,6 +211,43 @@ case $CI_TARGET in echo "Building API..." bazel build "${BAZEL_BUILD_OPTIONS[@]}" \ -c fastbuild @envoy_api//envoy/... + if [[ -n "$ENVOY_API_ONLY" ]]; then + exit 0 + fi + ;& + + api.go) + if [[ -z "$NO_BUILD_SETUP" ]]; then + setup_clang_toolchain + fi + GO_IMPORT_BASE="github.com/envoyproxy/go-control-plane" + GO_TARGETS=(@envoy_api//...) + read -r -a GO_PROTOS <<< "$(bazel query "${BAZEL_GLOBAL_OPTIONS[@]}" "kind('go_proto_library', ${GO_TARGETS[*]})" | tr '\n' ' ')" + echo "${GO_PROTOS[@]}" | grep -q envoy_api || echo "No go proto targets found" + bazel build "${BAZEL_BUILD_OPTIONS[@]}" \ + --experimental_proto_descriptor_sets_include_source_info \ + --remote_download_outputs=all \ + "${GO_PROTOS[@]}" + rm -rf build_go + mkdir -p build_go + echo "Copying go protos -> build_go" + BAZEL_BIN="$(bazel info "${BAZEL_BUILD_OPTIONS[@]}" bazel-bin)" + for GO_PROTO in "${GO_PROTOS[@]}"; do + # strip @envoy_api// + RULE_DIR="$(echo "${GO_PROTO:12}" | cut -d: -f1)" + PROTO="$(echo "${GO_PROTO:12}" | cut -d: -f2)" + INPUT_DIR="${BAZEL_BIN}/external/envoy_api/${RULE_DIR}/${PROTO}_/${GO_IMPORT_BASE}/${RULE_DIR}" + OUTPUT_DIR="build_go/${RULE_DIR}" + mkdir -p "$OUTPUT_DIR" + if [[ ! -e "$INPUT_DIR" ]]; then + echo "Unable to find input ${INPUT_DIR}" >&2 + exit 1 + fi + # echo "Copying go files ${INPUT_DIR} -> ${OUTPUT_DIR}" + while read -r GO_FILE; do + cp -a "$GO_FILE" "$OUTPUT_DIR" + done <<< "$(find "$INPUT_DIR" -name "*.go")" + done ;; api_compat) diff --git a/tools/api/generate_go_protobuf.py b/tools/api/generate_go_protobuf.py index 2fc3728f56b5..af3a85b29129 100755 --- a/tools/api/generate_go_protobuf.py +++ b/tools/api/generate_go_protobuf.py @@ -1,164 +1,13 @@ #!/usr/bin/env python3 -from subprocess import check_output, STDOUT, CalledProcessError -import argparse -import glob -import os -import shlex -import shutil import sys -import re -# Needed for CI to pass down bazel options. -BAZEL_BUILD_OPTIONS = shlex.split(os.environ.get('BAZEL_BUILD_OPTION_LIST', '')) -BAZEL_GLOBAL_OPTIONS = shlex.split(os.environ.get('BAZEL_GLOBAL_OPTION_LIST', '')) -BAZEL_STARTUP_OPTIONS = shlex.split(os.environ.get('BAZEL_STARTUP_OPTION_LIST', '')) -TARGETS = '@envoy_api//...' -IMPORT_BASE = 'github.com/envoyproxy/go-control-plane' -REPO_BASE = 'go-control-plane' -BRANCH = 'main' -MIRROR_MSG = 'Mirrored from envoyproxy/envoy @ ' -USER_NAME = 'go-control-plane(Azure Pipelines)' -USER_EMAIL = 'go-control-plane@users.noreply.github.com' - - -def generate_protobufs(targets, output, api_repo): - bazel_bin = check_output( - ['bazel', *BAZEL_STARTUP_OPTIONS, 'info', *BAZEL_BUILD_OPTIONS, - 'bazel-bin']).decode().strip() - go_protos = check_output([ - 'bazel', - *BAZEL_STARTUP_OPTIONS, - 'query', - *BAZEL_GLOBAL_OPTIONS, - 'kind("go_proto_library", %s)' % targets, - ]).split() - - # Each rule has the form @envoy_api//foo/bar:baz_go_proto. - # First build all the rules to ensure we have the output files. - # We preserve source info so comments are retained on generated code. - try: - check_output([ - 'bazel', *BAZEL_STARTUP_OPTIONS, 'build', '-c', 'fastbuild', - '--experimental_proto_descriptor_sets_include_source_info' - ] + BAZEL_BUILD_OPTIONS + go_protos, - stderr=STDOUT) - except CalledProcessError as e: - print(e.output) - raise e - - for rule in go_protos: - # Example rule: - # @envoy_api//envoy/config/bootstrap/v2:pkg_go_proto - # - # Example generated directory: - # bazel-bin/external/envoy_api/envoy/config/bootstrap/v2/linux_amd64_stripped/pkg_go_proto%/github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2/ - # - # Example output directory: - # go_out/envoy/config/bootstrap/v2 - rule_dir, proto = rule.decode().rsplit('//', 1)[1].rsplit(':', 1) - - prefix = '' if not api_repo else os.path.join('external', api_repo) - input_dir = os.path.join(bazel_bin, prefix, rule_dir, proto + '_', IMPORT_BASE, rule_dir) - input_files = glob.glob(os.path.join(input_dir, '*.go')) - output_dir = os.path.join(output, rule_dir) - - # Ensure the output directory exists - os.makedirs(output_dir, 0o755, exist_ok=True) - for generated_file in input_files: - shutil.copy(generated_file, output_dir) - print('Go artifacts placed into: ' + output) - - -def git(repo, *args): - cmd = ['git'] - if repo: - cmd = cmd + ['-C', repo] - for arg in args: - cmd = cmd + [arg] - return check_output(cmd).decode() - - -def clone_go_protobufs(repo): - # Create a local clone of go-control-plane - git(None, 'clone', 'git@github.com:envoyproxy/go-control-plane', repo, '-b', BRANCH) - - -def find_last_sync_sha(repo): - # Determine last envoyproxy/envoy SHA in envoyproxy/go-control-plane - last_commit = git(repo, 'log', '--grep=' + MIRROR_MSG, '-n', '1', '--format=%B').strip() - # Initial SHA from which the APIs start syncing. Prior to that it was done manually. - if last_commit == "": - return 'e7f0b7176efdc65f96eb1697b829d1e6187f4502' - m = re.search(MIRROR_MSG + '(\w+)', last_commit) - return m.group(1) - - -def updated_since_sha(repo, last_sha): - # Determine if there are changes to API since last SHA - return git(None, 'rev-list', '%s..HEAD' % last_sha).split() - - -def write_revision_info(repo, sha): - # Put a file in the generated code root containing the latest mirrored SHA - dst = os.path.join(repo, 'envoy', 'COMMIT') - with open(dst, 'w') as fh: - fh.write(sha) - - -def sync_go_protobufs(output, repo): - for folder in ['envoy', 'contrib']: - # Sync generated content against repo and return true if there is a commit necessary - dst = os.path.join(repo, folder) - # Remove subtree in repo - git(repo, 'rm', '-r', '--ignore-unmatch', folder) - # Copy subtree from output to repo - shutil.copytree(os.path.join(output, folder), dst) - git(repo, 'add', folder) - - -def publish_go_protobufs(repo, sha): - # Publish generated files with the last SHA changes to API - git(repo, 'config', 'user.name', USER_NAME) - git(repo, 'config', 'user.email', USER_EMAIL) - git(repo, 'add', 'envoy') - git(repo, 'add', 'contrib') - git(repo, 'commit', '--allow-empty', '-s', '-m', MIRROR_MSG + sha) - git(repo, 'push', 'origin', BRANCH) - - -def updated(repo): - return len([ - f for f in git(repo, 'diff', 'HEAD', '--name-only').splitlines() if f != 'envoy/COMMIT' - ]) > 0 +def main(): + # TODO(phlax): remove this 12/23 + sys.stderr.write("This script has been removed, please use `ci/do_ci.sh api.go` instead\n") + sys.exit(1) if __name__ == "__main__": - parser = argparse.ArgumentParser( - description='Generate Go protobuf files and sync with go-control-plane') - parser.add_argument('--sync', action='store_true') - parser.add_argument('--output_base', default='build_go') - parser.add_argument('--targets', default=TARGETS) - parser.add_argument('--api_repo', default="envoy_api") - args = parser.parse_args() - - workspace = check_output( - ['bazel', *BAZEL_STARTUP_OPTIONS, 'info', *BAZEL_BUILD_OPTIONS, - 'workspace']).decode().strip() - output = os.path.join(workspace, args.output_base) - generate_protobufs(args.targets, output, args.api_repo) - if not args.sync: - print('Skipping sync with go-control-plane') - sys.exit() - - repo = os.path.join(workspace, REPO_BASE) - clone_go_protobufs(repo) - sync_go_protobufs(output, repo) - last_sha = find_last_sync_sha(repo) - changes = updated_since_sha(repo, last_sha) - if updated(repo): - print('Changes detected: %s' % changes) - new_sha = changes[0] - write_revision_info(repo, new_sha) - publish_go_protobufs(repo, new_sha) + main() From d0fd0258e52de718ef29b52699fe0fb82b29fafc Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:05:04 -0400 Subject: [PATCH 163/228] Fuzzer: Fix ext_proc fuzz bug (#27639) * ext_proc should not open an additional stream if we've completed processing. Signed-off-by: Yanjun Xiang --- .../filters/http/ext_proc/ext_proc.cc | 8 ++- ...h-232906f11069ff930e29c13c1a3ae5a2c3202c57 | 70 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-232906f11069ff930e29c13c1a3ae5a2c3202c57 diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 7661048511ac..0ef4f84c8274 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -118,7 +118,13 @@ void Filter::setEncoderFilterCallbacks(Http::StreamEncoderFilterCallbacks& callb } Filter::StreamOpenState Filter::openStream() { - ENVOY_BUG(!processing_complete_, "openStream should not have been called"); + // External processing is completed. This means there is no need to send any further + // message to the server for processing. Just return IgnoreError so the filter + // will return FilterHeadersStatus::Continue. + if (processing_complete_) { + ENVOY_LOG(debug, "External processing is completed when trying to open the gRPC stream"); + return StreamOpenState::IgnoreError; + } if (!stream_) { ENVOY_LOG(debug, "Opening gRPC stream to external processor"); stream_ = client_->start(*this, grpc_service_, decoder_callbacks_->streamInfo()); diff --git a/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-232906f11069ff930e29c13c1a3ae5a2c3202c57 b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-232906f11069ff930e29c13c1a3ae5a2c3202c57 new file mode 100644 index 000000000000..9bfa96c62f75 --- /dev/null +++ b/test/extensions/filters/http/ext_proc/unit_test_fuzz/ext_proc_corpus/crash-232906f11069ff930e29c13c1a3ae5a2c3202c57 @@ -0,0 +1,70 @@ +config { + grpc_service { + google_grpc { + target_uri: "test_uri" + channel_credentials { + ssl_credentials { + private_key { + inline_string: "/" + } + } + } + stat_prefix: "test_uri" + credentials_factory_name: "test_uri" + config { + } + } + initial_metadata { + key: "test_uri" + } + } + failure_mode_allow: true + processing_mode { + response_header_mode: SKIP + } + request_attributes: "(" + response_attributes: "test_uri" + response_attributes: "9\000\000\000\000\000\000\000" + stat_prefix: "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000." +} +request { + headers { + headers { + key: "(" + } + headers { + key: "test_uri" + } + } + http_body { + data: "\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\360\270\270\270\350\270\270" + } +} +response { + request_headers { + response { + header_mutation { + remove_headers: "f" + remove_headers: "f" + } + } + } + dynamic_metadata { + fields { + key: "" + value { + } + } + fields { + key: "" + value { + } + } + } + mode_override { + request_header_mode: SKIP + request_body_mode: BUFFERED + response_body_mode: BUFFERED + request_trailer_mode: SEND + } +} From e20ba06ff3719862212780d413b2405de8f06460 Mon Sep 17 00:00:00 2001 From: botengyao Date: Fri, 2 Jun 2023 15:12:00 -0400 Subject: [PATCH 164/228] nit: setOverrideConfigForTests comment clean up (#27770) comment clean up Signed-off-by: Boteng Yao --- mobile/test/common/integration/test_engine_builder.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/test/common/integration/test_engine_builder.h b/mobile/test/common/integration/test_engine_builder.h index 1c969046249d..7fb6d6be3e0a 100644 --- a/mobile/test/common/integration/test_engine_builder.h +++ b/mobile/test/common/integration/test_engine_builder.h @@ -7,8 +7,8 @@ namespace Envoy { // A wrapper class around EngineBuilder, specifically for mobile tests. // // Mobile tests often supply their own configuration for convenience, instead of using the -// EngineBuilder APIs. This wrapper class builds an Envoy Mobile Engine with the ability to -// access setOverrideConfigForTests(), which is a protected method inside EngineBuilder. +// EngineBuilder APIs. This wrapper class can build an Envoy Mobile Engine through createEngine +// with a customized bootstrap configuration. class TestEngineBuilder : public Platform::EngineBuilder { public: virtual ~TestEngineBuilder() {} From ae44069e7185531fdcb92d776eb9f62d1721ff6d Mon Sep 17 00:00:00 2001 From: danzh Date: Fri, 2 Jun 2023 15:36:19 -0400 Subject: [PATCH 165/228] deprecate runtime guard `envoy.reloadable_features.tls_async_cert_validation` (#27656) Risk Level: low Testing: existing tests Docs Changes: release note Release Notes: removed_config_or_runtime Platform Specific Features: N/A Fixes #26908 Signed-off-by: Dan Zhang --- changelogs/current.yaml | 3 + .../platform_bridge_cert_validator.h | 8 - .../common/quic/envoy_quic_proof_verifier.cc | 68 +---- .../common/quic/envoy_quic_proof_verifier.h | 7 - source/common/runtime/runtime_features.cc | 1 - .../tls/cert_validator/cert_validator.h | 12 - .../tls/cert_validator/default_validator.cc | 31 --- .../tls/cert_validator/default_validator.h | 4 - .../cert_validator/spiffe/spiffe_validator.cc | 17 -- .../cert_validator/spiffe/spiffe_validator.h | 3 - .../transport_sockets/tls/context_impl.cc | 77 +----- .../transport_sockets/tls/context_impl.h | 6 - .../transport_sockets/tls/ssl_handshaker.cc | 1 - .../quic/envoy_quic_proof_verifier_test.cc | 71 ++---- .../cert_validator/default_validator_test.cc | 26 +- .../spiffe/spiffe_validator_test.cc | 239 ++++++------------ .../tls/cert_validator/timed_cert_validator.h | 7 - .../tls/integration/ssl_integration_test.cc | 12 - .../transport_sockets/tls/ssl_socket_test.cc | 83 ++---- .../integration/quic_http_integration_test.cc | 12 - 20 files changed, 165 insertions(+), 523 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 7fc60f892d9a..932d78b1e19f 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -179,6 +179,9 @@ removed_config_or_runtime: - area: header_formatters change: | removed runtime key ``envoy.reloadable_features.unified_header_formatter`` and legacy code paths. +- area: tls + change: | + remove runtime key ``envoy.reloadable_features.tls_async_cert_validation`` and legacy code paths. - area: config change: | removed runtime key ``envoy.reloadable_features.delta_xds_subscription_state_tracking_fix`` and legacy code paths. diff --git a/mobile/library/common/extensions/cert_validator/platform_bridge/platform_bridge_cert_validator.h b/mobile/library/common/extensions/cert_validator/platform_bridge/platform_bridge_cert_validator.h index c2912c77799b..db190635e03e 100644 --- a/mobile/library/common/extensions/cert_validator/platform_bridge/platform_bridge_cert_validator.h +++ b/mobile/library/common/extensions/cert_validator/platform_bridge/platform_bridge_cert_validator.h @@ -37,14 +37,6 @@ class PlatformBridgeCertValidator : public CertValidator, Logger::Loggable daysUntilFirstCertExpires() const override { return absl::nullopt; } Envoy::Ssl::CertificateDetailsPtr getCaCertInformation() const override { return nullptr; } // Return empty string diff --git a/source/common/quic/envoy_quic_proof_verifier.cc b/source/common/quic/envoy_quic_proof_verifier.cc index 0f2404e90132..b971b0a5ced1 100644 --- a/source/common/quic/envoy_quic_proof_verifier.cc +++ b/source/common/quic/envoy_quic_proof_verifier.cc @@ -43,16 +43,14 @@ class QuicValidateResultCallback : public Ssl::ValidateResultCallback { void onCertValidationResult(bool succeeded, Ssl::ClientValidationStatus /*detailed_status*/, const std::string& error_details, uint8_t /*tls_alert*/) override { + std::string error; if (!succeeded) { - std::unique_ptr details = std::make_unique(false); - quic_callback_->Run(succeeded, error_details, &details); - return; + error = error_details; + } else { + std::unique_ptr cert_view = + quic::CertificateView::ParseSingleCertificate(leaf_cert_); + succeeded = verifyLeafCertMatchesHostname(*cert_view, hostname_, &error); } - std::string error; - - std::unique_ptr cert_view = - quic::CertificateView::ParseSingleCertificate(leaf_cert_); - succeeded = verifyLeafCertMatchesHostname(*cert_view, hostname_, &error); std::unique_ptr details = std::make_unique(succeeded); quic_callback_->Run(succeeded, error, &details); @@ -69,8 +67,8 @@ class QuicValidateResultCallback : public Ssl::ValidateResultCallback { } // namespace quic::QuicAsyncStatus EnvoyQuicProofVerifier::VerifyCertChain( - const std::string& hostname, const uint16_t port, const std::vector& certs, - const std::string& ocsp_response, const std::string& cert_sct, + const std::string& hostname, const uint16_t /*port*/, const std::vector& certs, + const std::string& /*ocsp_response*/, const std::string& /*cert_sct*/, const quic::ProofVerifyContext* context, std::string* error_details, std::unique_ptr* details, uint8_t* out_alert, std::unique_ptr callback) { @@ -83,16 +81,6 @@ quic::QuicAsyncStatus EnvoyQuicProofVerifier::VerifyCertChain( } ENVOY_BUG(!verify_context->isServer(), "Client certificates are not supported in QUIC yet."); - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - if (doVerifyCertChain(hostname, port, certs, ocsp_response, cert_sct, context, error_details, - out_alert, std::move(callback))) { - *details = std::make_unique(true); - return quic::QUIC_SUCCESS; - } - *details = std::make_unique(false); - return quic::QUIC_FAILURE; - } - bssl::UniquePtr cert_chain(sk_X509_new_null()); for (const auto& cert_str : certs) { bssl::UniquePtr cert = parseDERCertificate(cert_str, error_details); @@ -143,45 +131,5 @@ quic::QuicAsyncStatus EnvoyQuicProofVerifier::VerifyCertChain( return quic::QUIC_FAILURE; } -bool EnvoyQuicProofVerifier::doVerifyCertChain( - const std::string& hostname, const uint16_t /*port*/, const std::vector& certs, - const std::string& /*ocsp_response*/, const std::string& /*cert_sct*/, - const quic::ProofVerifyContext* /*context*/, std::string* error_details, uint8_t* /*out_alert*/, - std::unique_ptr /*callback*/) { - bssl::UniquePtr intermediates(sk_X509_new_null()); - bssl::UniquePtr leaf; - for (size_t i = 0; i < certs.size(); i++) { - bssl::UniquePtr cert = parseDERCertificate(certs[i], error_details); - if (!cert) { - return false; - } - if (i == 0) { - leaf = std::move(cert); - } else { - sk_X509_push(intermediates.get(), cert.release()); - } - } - std::unique_ptr cert_view = - quic::CertificateView::ParseSingleCertificate(certs[0]); - ASSERT(cert_view != nullptr); - int sign_alg = deduceSignatureAlgorithmFromPublicKey(cert_view->public_key(), error_details); - if (sign_alg == 0) { - return false; - } - // We down cast rather than add verifyCertChain to Envoy::Ssl::Context because - // verifyCertChain uses a bunch of SSL-specific structs which we want to keep - // out of the interface definition. - bool success = static_cast(context_.get()) - ->verifyCertChain(*leaf, *intermediates, *error_details); - if (!success) { - return false; - } - if (verifyLeafCertMatchesHostname(*cert_view, hostname, error_details)) { - return true; - } - *error_details = absl::StrCat("Leaf certificate doesn't match hostname: ", hostname); - return false; -} - } // namespace Quic } // namespace Envoy diff --git a/source/common/quic/envoy_quic_proof_verifier.h b/source/common/quic/envoy_quic_proof_verifier.h index 50a3b9e66a44..fc03fbca15d0 100644 --- a/source/common/quic/envoy_quic_proof_verifier.h +++ b/source/common/quic/envoy_quic_proof_verifier.h @@ -54,13 +54,6 @@ class EnvoyQuicProofVerifier : public EnvoyQuicProofVerifierBase { std::unique_ptr callback) override; private: - // TODO(danzh) remove when deprecating envoy.reloadable_features.tls_async_cert_validation. - bool doVerifyCertChain(const std::string& hostname, const uint16_t port, - const std::vector& certs, const std::string& ocsp_response, - const std::string& cert_sct, const quic::ProofVerifyContext* context, - std::string* error_details, uint8_t* out_alert, - std::unique_ptr callback); - Envoy::Ssl::ClientContextSharedPtr context_; }; diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index f0e2429dccce..c7ce0d53bc49 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -73,7 +73,6 @@ RUNTIME_GUARD(envoy_reloadable_features_tcp_pool_idle_timeout); RUNTIME_GUARD(envoy_reloadable_features_test_feature_true); RUNTIME_GUARD(envoy_reloadable_features_thrift_allow_negative_field_ids); RUNTIME_GUARD(envoy_reloadable_features_thrift_connection_draining); -RUNTIME_GUARD(envoy_reloadable_features_tls_async_cert_validation); RUNTIME_GUARD(envoy_reloadable_features_uhv_allow_malformed_url_encoding); RUNTIME_GUARD(envoy_reloadable_features_uhv_preserve_url_encoded_case); RUNTIME_GUARD(envoy_reloadable_features_uhv_translate_backslash_to_slash); diff --git a/source/extensions/transport_sockets/tls/cert_validator/cert_validator.h b/source/extensions/transport_sockets/tls/cert_validator/cert_validator.h index 0034cc7dff02..99e6945923fd 100644 --- a/source/extensions/transport_sockets/tls/cert_validator/cert_validator.h +++ b/source/extensions/transport_sockets/tls/cert_validator/cert_validator.h @@ -58,18 +58,6 @@ class CertValidator { */ virtual void addClientValidationContext(SSL_CTX* context, bool require_client_cert) PURE; - /** - * Called by verifyCallback to do the actual cert chain verification. - * - * @param store_ctx the store context - * @param ssl_extended_info the info for storing the validation status - * @param leaf_cert the peer certificate to verify - * @return 1 to indicate verification success and 0 to indicate verification failure. - */ - virtual int doSynchronousVerifyCertChain( - X509_STORE_CTX* store_ctx, Ssl::SslExtendedSocketInfo* ssl_extended_info, X509& leaf_cert, - const Network::TransportSocketOptions* transport_socket_options) PURE; - /** * Called by customVerifyCallback to do the actual cert chain verification which could be * asynchronous. If the verification is asynchronous, Pending will be returned. After the diff --git a/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc b/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc index 74ff6984d9a4..c618b2531583 100644 --- a/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc +++ b/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc @@ -194,37 +194,6 @@ int DefaultCertValidator::initializeSslContexts(std::vector contexts, return verify_mode; } -int DefaultCertValidator::doSynchronousVerifyCertChain( - X509_STORE_CTX* store_ctx, Ssl::SslExtendedSocketInfo* ssl_extended_info, X509& leaf_cert, - const Network::TransportSocketOptions* transport_socket_options) { - if (verify_trusted_ca_) { - int ret = X509_verify_cert(store_ctx); - if (ssl_extended_info) { - ssl_extended_info->setCertificateValidationStatus( - ret == 1 ? Envoy::Ssl::ClientValidationStatus::Validated - : Envoy::Ssl::ClientValidationStatus::Failed); - } - - if (ret <= 0) { - stats_.fail_verify_error_.inc(); - ENVOY_LOG(debug, "{}", Utility::getX509VerificationErrorInfo(store_ctx)); - return allow_untrusted_certificate_ ? 1 : ret; - } - } - Envoy::Ssl::ClientValidationStatus detailed_status = - Envoy::Ssl::ClientValidationStatus::NotValidated; - bool success = verifyCertAndUpdateStatus(&leaf_cert, transport_socket_options, detailed_status, - nullptr, nullptr); - if (ssl_extended_info) { - ssl_extended_info->setCertificateValidationStatus(detailed_status); - } - if (!success) { - X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_APPLICATION_VERIFICATION); - return 0; - } - return 1; -} - bool DefaultCertValidator::verifyCertAndUpdateStatus( X509* leaf_cert, const Network::TransportSocketOptions* transport_socket_options, Envoy::Ssl::ClientValidationStatus& detailed_status, std::string* error_details, diff --git a/source/extensions/transport_sockets/tls/cert_validator/default_validator.h b/source/extensions/transport_sockets/tls/cert_validator/default_validator.h index 06ad4b7f887e..704af90c1053 100644 --- a/source/extensions/transport_sockets/tls/cert_validator/default_validator.h +++ b/source/extensions/transport_sockets/tls/cert_validator/default_validator.h @@ -42,10 +42,6 @@ class DefaultCertValidator : public CertValidator, Logger::Loggable, bool) { return SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } -int SPIFFEValidator::doSynchronousVerifyCertChain(X509_STORE_CTX* store_ctx, - Ssl::SslExtendedSocketInfo* ssl_extended_info, - X509& leaf_cert, - const Network::TransportSocketOptions*) { - STACK_OF(X509)* cert_chain = X509_STORE_CTX_get0_untrusted(store_ctx); - X509_VERIFY_PARAM* verify_param = X509_STORE_CTX_get0_param(store_ctx); - std::string error_details; - bool verified = - verifyCertChainUsingTrustBundleStore(leaf_cert, cert_chain, verify_param, error_details); - if (ssl_extended_info) { - ssl_extended_info->setCertificateValidationStatus( - verified ? Envoy::Ssl::ClientValidationStatus::Validated - : Envoy::Ssl::ClientValidationStatus::Failed); - } - return verified ? 1 : 0; -} - bool SPIFFEValidator::verifyCertChainUsingTrustBundleStore(X509& leaf_cert, STACK_OF(X509)* cert_chain, X509_VERIFY_PARAM* verify_param, diff --git a/source/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator.h b/source/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator.h index d252620d2e02..3850fa5533be 100644 --- a/source/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator.h +++ b/source/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator.h @@ -41,9 +41,6 @@ class SPIFFEValidator : public CertValidator { // Tls::CertValidator void addClientValidationContext(SSL_CTX* context, bool require_client_cert) override; - int doSynchronousVerifyCertChain( - X509_STORE_CTX* store_ctx, Ssl::SslExtendedSocketInfo* ssl_extended_info, X509& leaf_cert, - const Network::TransportSocketOptions* transport_socket_options) override; ValidationResults doVerifyCertChain(STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, diff --git a/source/extensions/transport_sockets/tls/context_impl.cc b/source/extensions/transport_sockets/tls/context_impl.cc index ea8dff81ea39..13389b0c8a17 100644 --- a/source/extensions/transport_sockets/tls/context_impl.cc +++ b/source/extensions/transport_sockets/tls/context_impl.cc @@ -172,22 +172,17 @@ ContextImpl::ContextImpl(Stats::Scope& scope, const Envoy::Ssl::ContextConfig& c if (!capabilities_.verifies_peer_certificates) { for (auto ctx : ssl_contexts) { if (verify_mode != SSL_VERIFY_NONE) { - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - // TODO(danzh) Envoy's use of SSL_VERIFY_NONE does not quite match the actual semantics as - // a client. As a client, SSL_VERIFY_NONE means to verify the certificate (which will fail - // without trust anchors), save the result in the session ticket, but otherwise continue - // with the handshake. But Envoy actually wants it to accept all certificates. The - // disadvantage of using SSL_VERIFY_NONE is that it records the verify_result, which Envoy - // never queries but gets saved in session tickets, and tries to find an anchor that isn't - // there. And also it differs from server side behavior of SSL_VERIFY_NONE which won't - // even request client certs. So, instead, we should configure a callback to skip - // validation and always supply the callback to boring SSL. - SSL_CTX_set_custom_verify(ctx, verify_mode, customVerifyCallback); - SSL_CTX_set_reverify_on_resume(ctx, /*reverify_on_resume_enabled)=*/1); - } else { - SSL_CTX_set_verify(ctx, verify_mode, nullptr); - SSL_CTX_set_cert_verify_callback(ctx, verifyCallback, this); - } + // TODO(danzh) Envoy's use of SSL_VERIFY_NONE does not quite match the actual semantics as + // a client. As a client, SSL_VERIFY_NONE means to verify the certificate (which will fail + // without trust anchors), save the result in the session ticket, but otherwise continue + // with the handshake. But Envoy actually wants it to accept all certificates. The + // disadvantage of using SSL_VERIFY_NONE is that it records the verify_result, which Envoy + // never queries but gets saved in session tickets, and tries to find an anchor that isn't + // there. And also it differs from server side behavior of SSL_VERIFY_NONE which won't + // even request client certs. So, instead, we should configure a callback to skip + // validation and always supply the callback to boring SSL. + SSL_CTX_set_custom_verify(ctx, verify_mode, customVerifyCallback); + SSL_CTX_set_reverify_on_resume(ctx, /*reverify_on_resume_enabled)=*/1); } } } @@ -467,23 +462,6 @@ ContextImpl::newSsl(const Network::TransportSocketOptionsConstSharedPtr& options return ssl_con; } -int ContextImpl::verifyCallback(X509_STORE_CTX* store_ctx, void* arg) { - ContextImpl* impl = reinterpret_cast(arg); - SSL* ssl = reinterpret_cast( - X509_STORE_CTX_get_ex_data(store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); - auto cert = bssl::UniquePtr(SSL_get_peer_certificate(ssl)); - auto transport_socket_options_shared_ptr_ptr = - static_cast(SSL_get_app_data(ssl)); - ASSERT(transport_socket_options_shared_ptr_ptr); - const Network::TransportSocketOptions* transport_socket_options = - (*transport_socket_options_shared_ptr_ptr).get(); - return impl->cert_validator_->doSynchronousVerifyCertChain( - store_ctx, - reinterpret_cast( - SSL_get_ex_data(ssl, ContextImpl::sslExtendedSocketInfoIndex())), - *cert, transport_socket_options); -} - enum ssl_verify_result_t ContextImpl::customVerifyCallback(SSL* ssl, uint8_t* out_alert) { auto* extended_socket_info = reinterpret_cast( SSL_get_ex_data(ssl, ContextImpl::sslExtendedSocketInfoIndex())); @@ -525,7 +503,6 @@ enum ssl_verify_result_t ContextImpl::customVerifyCallback(SSL* ssl, uint8_t* ou ValidationResults ContextImpl::customVerifyCertChain( Envoy::Ssl::SslExtendedSocketInfo* extended_socket_info, const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, SSL* ssl) { - ASSERT(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")); ASSERT(extended_socket_info); STACK_OF(X509)* cert_chain = SSL_get_peer_full_cert_chain(ssl); if (cert_chain == nullptr) { @@ -1373,42 +1350,10 @@ bool TlsContext::isCipherEnabled(uint16_t cipher_id, uint16_t client_version) { return false; } -bool ContextImpl::verifyCertChain(X509& leaf_cert, STACK_OF(X509)& intermediates, - std::string& error_details) { - bssl::UniquePtr ctx(X509_STORE_CTX_new()); - - ASSERT(!tls_contexts_.empty()); - // It doesn't matter which SSL context is used, because they share the same - // cert validation config. - const SSL_CTX* ssl_ctx = tls_contexts_[0].ssl_ctx_.get(); - X509_STORE* store = SSL_CTX_get_cert_store(ssl_ctx); - if (!X509_STORE_CTX_init(ctx.get(), store, &leaf_cert, &intermediates)) { - error_details = "Failed to verify certificate chain: X509_STORE_CTX_init"; - return false; - } - // Currently this method is only used to verify server certs, so hard-code "ssl_server" for now. - if (!X509_STORE_CTX_set_default(ctx.get(), "ssl_server") || - !X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(ctx.get()), - SSL_CTX_get0_param(const_cast(ssl_ctx)))) { - error_details = - "Failed to verify certificate chain: fail to setup X509_STORE_CTX or its param."; - return false; - } - - int res = cert_validator_->doSynchronousVerifyCertChain(ctx.get(), nullptr, leaf_cert, nullptr); - // If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the error details. - if (res <= 0 && SSL_CTX_get_verify_mode(ssl_ctx) != SSL_VERIFY_NONE) { - error_details = Utility::getX509VerificationErrorInfo(ctx.get()); - return false; - } - return true; -} - ValidationResults ContextImpl::customVerifyCertChainForQuic( STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server, const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, const CertValidator::ExtraValidationContext& validation_context, const std::string& host_name) { - ASSERT(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")); ASSERT(!tls_contexts_.empty()); // It doesn't matter which SSL context is used, because they share the same cert validation // config. diff --git a/source/extensions/transport_sockets/tls/context_impl.h b/source/extensions/transport_sockets/tls/context_impl.h index 45c2a08e7ee7..c786f3738662 100644 --- a/source/extensions/transport_sockets/tls/context_impl.h +++ b/source/extensions/transport_sockets/tls/context_impl.h @@ -91,9 +91,6 @@ class ContextImpl : public virtual Envoy::Ssl::Context, std::vector getPrivateKeyMethodProviders(); - // TODO(danzh) remove when deprecate envoy.reloadable_features.tls_async_cert_validation - bool verifyCertChain(X509& leaf_cert, STACK_OF(X509)& intermediates, std::string& error_details); - // Validate cert asynchronously for a QUIC connection. ValidationResults customVerifyCertChainForQuic( STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, bool is_server, @@ -115,9 +112,6 @@ class ContextImpl : public virtual Envoy::Ssl::Context, */ static int sslContextIndex(); - // A SSL_CTX_set_cert_verify_callback for custom cert validation. - static int verifyCallback(X509_STORE_CTX* store_ctx, void* arg); - // A SSL_CTX_set_custom_verify callback for asynchronous cert validation. static enum ssl_verify_result_t customVerifyCallback(SSL* ssl, uint8_t* out_alert); diff --git a/source/extensions/transport_sockets/tls/ssl_handshaker.cc b/source/extensions/transport_sockets/tls/ssl_handshaker.cc index 3528f5f5f1df..2a0ad63dcc4e 100644 --- a/source/extensions/transport_sockets/tls/ssl_handshaker.cc +++ b/source/extensions/transport_sockets/tls/ssl_handshaker.cc @@ -48,7 +48,6 @@ void SslExtendedSocketInfoImpl::onCertificateValidationCompleted(bool succeeded) cert_validation_result_ = succeeded ? Ssl::ValidateStatus::Successful : Ssl::ValidateStatus::Failed; if (cert_validate_result_callback_.has_value()) { - ASSERT(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")); // This is an async cert validation. cert_validate_result_callback_.reset(); // Resume handshake. diff --git a/test/common/quic/envoy_quic_proof_verifier_test.cc b/test/common/quic/envoy_quic_proof_verifier_test.cc index 93d1d025403e..04957d0e2905 100644 --- a/test/common/quic/envoy_quic_proof_verifier_test.cc +++ b/test/common/quic/envoy_quic_proof_verifier_test.cc @@ -31,8 +31,7 @@ class MockProofVerifierCallback : public quic::ProofVerifierCallback { MOCK_METHOD(void, Run, (bool, const std::string&, std::unique_ptr*)); }; -class EnvoyQuicProofVerifierTest : public ::testing::Test, - public testing::WithParamInterface { +class EnvoyQuicProofVerifierTest : public testing::Test { public: EnvoyQuicProofVerifierTest() : root_ca_cert_(cert_chain_.substr(cert_chain_.rfind("-----BEGIN CERTIFICATE-----"))), @@ -41,8 +40,6 @@ class EnvoyQuicProofVerifierTest : public ::testing::Test, std::vector chain = quic::CertificateView::LoadPemFromStream(&pem_stream); return chain[0]; }()) { - Runtime::maybeSetRuntimeGuard("envoy.reloadable_features.tls_async_cert_validation", - GetParam()); ON_CALL(client_context_config_, cipherSuites) .WillByDefault(ReturnRef( Extensions::TransportSockets::Tls::ClientContextConfigImpl::DEFAULT_CIPHER_SUITES)); @@ -111,9 +108,7 @@ class EnvoyQuicProofVerifierTest : public ::testing::Test, NiceMock verify_context_; }; -INSTANTIATE_TEST_SUITE_P(EnvoyQuicProofVerifierTests, EnvoyQuicProofVerifierTest, testing::Bool()); - -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainSuccess) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainSuccess) { configCertVerificationDetails(true); std::unique_ptr cert_view = quic::CertificateView::ParseSingleCertificate(leaf_cert_); @@ -132,10 +127,7 @@ TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainSuccess) { EXPECT_TRUE(cloned->isValid()); } -TEST_P(EnvoyQuicProofVerifierTest, AsyncVerifyCertChainSuccess) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } +TEST_F(EnvoyQuicProofVerifierTest, AsyncVerifyCertChainSuccess) { custom_validator_config_ = envoy::config::core::v3::TypedExtensionConfig(); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" @@ -171,7 +163,7 @@ name: "envoy.tls.cert_validator.timed_cert_validator" verify_timer->invokeCallback(); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureFromSsl) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainFailureFromSsl) { configCertVerificationDetails(false); std::unique_ptr cert_view = quic::CertificateView::ParseSingleCertificate(leaf_cert_); @@ -184,26 +176,20 @@ TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureFromSsl) { {leaf_cert_}, ocsp_response, cert_sct, &verify_context_, &error_details, &verify_details, nullptr, nullptr)) << error_details; - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - EXPECT_EQ("verify cert failed: X509_verify_cert: certificate verification error at depth 1: " - "certificate has expired", - error_details); - } else { - EXPECT_EQ("X509_verify_cert: certificate verification error at depth 1: " - "certificate has expired", - error_details); - } + EXPECT_EQ("verify cert failed: X509_verify_cert: certificate verification error at depth 1: " + "certificate has expired", + error_details); EXPECT_NE(verify_details, nullptr); EXPECT_FALSE(static_cast(*verify_details).isValid()); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidCA) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidCA) { root_ca_cert_ = "invalid root CA"; EXPECT_THROW_WITH_REGEX(configCertVerificationDetails(true), EnvoyException, "Failed to load trusted CA certificates from"); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidLeafCert) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidLeafCert) { configCertVerificationDetails(true); const std::string ocsp_response; const std::string cert_sct; @@ -217,7 +203,7 @@ TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidLeafCert) { EXPECT_EQ("d2i_X509: fail to parse DER", error_details); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureLeafCertWithGarbage) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainFailureLeafCertWithGarbage) { configCertVerificationDetails(true); std::unique_ptr cert_view = quic::CertificateView::ParseSingleCertificate(leaf_cert_); @@ -235,7 +221,7 @@ TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureLeafCertWithGarbage) { EXPECT_EQ("There is trailing garbage in DER.", error_details); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidHost) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidHost) { configCertVerificationDetails(true); const std::string ocsp_response; const std::string cert_sct; @@ -249,11 +235,7 @@ TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureInvalidHost) { EXPECT_EQ("Leaf certificate doesn't match hostname: unknown.org", error_details); } -TEST_P(EnvoyQuicProofVerifierTest, AsyncVerifyCertChainFailureInvalidHost) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - +TEST_F(EnvoyQuicProofVerifierTest, AsyncVerifyCertChainFailureInvalidHost) { custom_validator_config_ = envoy::config::core::v3::TypedExtensionConfig(); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" @@ -288,7 +270,7 @@ name: "envoy.tls.cert_validator.timed_cert_validator" verify_timer->invokeCallback(); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureUnsupportedECKey) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainFailureUnsupportedECKey) { configCertVerificationDetails(true); const std::string ocsp_response; const std::string cert_sct; @@ -323,7 +305,7 @@ VdGXMAjeXhnOnPvmDi5hUz/uvI+Pg6cNmUoCRwSCnK/DazhA EXPECT_EQ("Invalid leaf cert, only P-256 ECDSA certificates are supported", error_details); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyCertChainFailureNonServerAuthEKU) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyCertChainFailureNonServerAuthEKU) { // Override the CA cert with cert copied from test/config/integration/certs/cacert.pem. root_ca_cert_ = R"(-----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIUdCu/mLip3X/We37vh3BA9u/nxakwDQYJKoZIhvcNAQEL @@ -391,24 +373,13 @@ ZCFbredVxDBZuoVsfrKPSQa407Jj1Q== verifier_->VerifyCertChain("lyft.com", 54321, chain, ocsp_response, cert_sct, &verify_context_, &error_details, &verify_details, nullptr, nullptr)); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - EXPECT_EQ("verify cert failed: X509_verify_cert: certificate verification error at depth 0: " - "unsupported certificate " - "purpose", - error_details); - } else { - EXPECT_EQ("X509_verify_cert: certificate verification error at depth 0: " - "unsupported certificate " - "purpose", - error_details); - } + EXPECT_EQ("verify cert failed: X509_verify_cert: certificate verification error at depth 0: " + "unsupported certificate " + "purpose", + error_details); } -TEST_P(EnvoyQuicProofVerifierTest, VerifySubjectAltNameListOverrideFailure) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - +TEST_F(EnvoyQuicProofVerifierTest, VerifySubjectAltNameListOverrideFailure) { transport_socket_options_.reset(new Network::TransportSocketOptionsImpl("", {"non-example.com"})); configCertVerificationDetails(true); std::unique_ptr cert_view = @@ -427,14 +398,14 @@ TEST_P(EnvoyQuicProofVerifierTest, VerifySubjectAltNameListOverrideFailure) { EXPECT_FALSE(static_cast(*verify_details).isValid()); } -TEST_P(EnvoyQuicProofVerifierTest, VerifyProof) { +TEST_F(EnvoyQuicProofVerifierTest, VerifyProof) { configCertVerificationDetails(true); EXPECT_DEATH(verifier_->VerifyProof("", 0, "", quic::QUIC_VERSION_IETF_RFC_V1, "", {}, "", "", nullptr, nullptr, nullptr, {}), "not implemented"); } -TEST_P(EnvoyQuicProofVerifierTest, CreateDefaultContext) { +TEST_F(EnvoyQuicProofVerifierTest, CreateDefaultContext) { configCertVerificationDetails(true); EXPECT_EQ(nullptr, verifier_->CreateDefaultContext()); } diff --git a/test/extensions/transport_sockets/tls/cert_validator/default_validator_test.cc b/test/extensions/transport_sockets/tls/cert_validator/default_validator_test.cc index 12bc395a3109..2920617947c3 100644 --- a/test/extensions/transport_sockets/tls/cert_validator/default_validator_test.cc +++ b/test/extensions/transport_sockets/tls/cert_validator/default_validator_test.cc @@ -180,12 +180,6 @@ TEST(DefaultCertValidatorTest, TestCertificateVerificationWithNoValidationContex nullptr), Envoy::Ssl::ClientValidationStatus::NotValidated); bssl::UniquePtr cert(X509_new()); - bssl::UniquePtr store_ctx(X509_STORE_CTX_new()); - EXPECT_EQ(default_validator->doSynchronousVerifyCertChain(/*store_ctx=*/store_ctx.get(), - /*ssl_extended_info=*/nullptr, - /*leaf_cert=*/*cert, - /*transport_socket_options=*/nullptr), - 0); SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); bssl::UniquePtr cert_chain(sk_X509_new_null()); ASSERT_TRUE(bssl::PushToStack(cert_chain.get(), std::move(cert))); @@ -291,7 +285,9 @@ TEST(DefaultCertValidatorTest, WithVerifyDepth) { class MockCertificateValidationContextConfig : public Ssl::CertificateValidationContextConfig { public: - MockCertificateValidationContextConfig() { + MockCertificateValidationContextConfig() : MockCertificateValidationContextConfig("") {} + + explicit MockCertificateValidationContextConfig(const std::string& s) : s_(s) { auto matcher = envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher(); matcher.set_san_type( static_cast( @@ -340,6 +336,22 @@ TEST(DefaultCertValidatorTest, TestUnexpectedSanMatcherType) { "Failed to create string SAN matcher of type.*"); } +TEST(DefaultCertValidatorTest, TestInitializeSslContextFailure) { + auto mock_context_config = std::make_unique( + "-----BEGIN CERTIFICATE-----\nincomplete payload"); + EXPECT_CALL(*mock_context_config.get(), trustChainVerification()) + .WillRepeatedly(testing::Return(envoy::extensions::transport_sockets::tls::v3:: + CertificateValidationContext::ACCEPT_UNTRUSTED)); + + Stats::TestUtil::TestStore store; + auto ssl_stats = generateSslStats(*store.rootScope()); + auto validator = std::make_unique(mock_context_config.get(), ssl_stats, + Event::GlobalTimeSystem().timeSystem()); + auto ctx = std::vector(); + EXPECT_THROW_WITH_REGEX(validator->initializeSslContexts(ctx, false), EnvoyException, + "Failed to load trusted CA certificates from.*"); +} + } // namespace Tls } // namespace TransportSockets } // namespace Extensions diff --git a/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc index 9f67f7978654..c6a06acab352 100644 --- a/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc +++ b/test/extensions/transport_sockets/tls/cert_validator/spiffe/spiffe_validator_test.cc @@ -36,12 +36,9 @@ using X509StoreContextPtr = CSmartPtr; using X509Ptr = CSmartPtr; using SSLContextPtr = CSmartPtr; -class TestSPIFFEValidator : public ::testing::Test, public testing::WithParamInterface { +class TestSPIFFEValidator : public testing::Test { public: - TestSPIFFEValidator() : stats_(generateSslStats(*store_.rootScope())) { - Runtime::maybeSetRuntimeGuard("envoy.reloadable_features.tls_async_cert_validation", - GetParam()); - } + TestSPIFFEValidator() : stats_(generateSslStats(*store_.rootScope())) {} void initialize(std::string yaml, TimeSource& time_source) { envoy::config::core::v3::TypedExtensionConfig typed_conf; TestUtility::loadFromYaml(yaml, typed_conf); @@ -102,9 +99,7 @@ class TestSPIFFEValidator : public ::testing::Test, public testing::WithParamInt SPIFFEValidatorPtr validator_; }; -INSTANTIATE_TEST_SUITE_P(TestSPIFFEValidators, TestSPIFFEValidator, testing::Bool()); - -TEST_P(TestSPIFFEValidator, InvalidCA) { +TEST_F(TestSPIFFEValidator, InvalidCA) { // Invalid trust bundle. EXPECT_THROW_WITH_MESSAGE(initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe @@ -119,7 +114,7 @@ name: envoy.tls.cert_validator.spiffe } // Multiple trust bundles are given for the same trust domain. -TEST_P(TestSPIFFEValidator, Constructor) { +TEST_F(TestSPIFFEValidator, Constructor) { EXPECT_THROW_WITH_MESSAGE(initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe typed_config: @@ -204,13 +199,13 @@ TEST(SPIFFEValidator, TestCertificatePrecheck) { EXPECT_TRUE(SPIFFEValidator::certificatePrecheck(cert.get())); } -TEST_P(TestSPIFFEValidator, TestInitializeSslContexts) { +TEST_F(TestSPIFFEValidator, TestInitializeSslContexts) { initialize(); EXPECT_EQ(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, validator().initializeSslContexts({}, false)); } -TEST_P(TestSPIFFEValidator, TestGetTrustBundleStore) { +TEST_F(TestSPIFFEValidator, TestGetTrustBundleStore) { initialize(); // No SAN @@ -236,7 +231,7 @@ TEST_P(TestSPIFFEValidator, TestGetTrustBundleStore) { EXPECT_TRUE(validator().getTrustBundleStore(cert.get())); } -TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainWithEmptyChain) { +TEST_F(TestSPIFFEValidator, TestDoVerifyCertChainWithEmptyChain) { initialize(); TestSslExtendedSocketInfo info; SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); @@ -249,30 +244,24 @@ TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainWithEmptyChain) { EXPECT_EQ(1, stats().fail_verify_error_.value()); } -TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainPrecheckFailure) { +TEST_F(TestSPIFFEValidator, TestDoVerifyCertChainPrecheckFailure) { initialize(); bssl::UniquePtr cert = readCertFromFile(TestEnvironment::substitute( // basicConstraints: CA:True "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ca_cert.pem")); TestSslExtendedSocketInfo info; - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); - bssl::UniquePtr cert_chain(sk_X509_new_null()); - sk_X509_push(cert_chain.get(), cert.release()); - ValidationResults results = validator().doVerifyCertChain( - *cert_chain, info.createValidateResultCallback(), - /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, ""); - EXPECT_EQ(ValidationResults::ValidationStatus::Failed, results.status); - EXPECT_EQ(Envoy::Ssl::ClientValidationStatus::Failed, results.detailed_status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_FALSE(validator().doSynchronousVerifyCertChain(store_ctx.get(), &info, *cert, nullptr)); - EXPECT_EQ(info.certificateValidationStatus(), Envoy::Ssl::ClientValidationStatus::Failed); - } + SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); + bssl::UniquePtr cert_chain(sk_X509_new_null()); + sk_X509_push(cert_chain.get(), cert.release()); + ValidationResults results = + validator().doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), + /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, ""); + EXPECT_EQ(ValidationResults::ValidationStatus::Failed, results.status); + EXPECT_EQ(Envoy::Ssl::ClientValidationStatus::Failed, results.detailed_status); EXPECT_EQ(1, stats().fail_verify_error_.value()); } -TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainSingleTrustDomain) { +TEST_F(TestSPIFFEValidator, TestDoVerifyCertChainSingleTrustDomain) { initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe typed_config: @@ -286,10 +275,10 @@ name: envoy.tls.cert_validator.spiffe X509StorePtr store = X509_STORE_new(); SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); TestSslExtendedSocketInfo info; - // Trust domain matches so should be accepted. - auto cert = readCertFromFile(TestEnvironment::substitute( - "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { + { + // Trust domain matches so should be accepted. + auto cert = readCertFromFile(TestEnvironment::substitute( + "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_cert.pem")); bssl::UniquePtr cert_chain(sk_X509_new_null()); sk_X509_push(cert_chain.get(), cert.release()); EXPECT_EQ(ValidationResults::ValidationStatus::Successful, @@ -297,16 +286,12 @@ name: envoy.tls.cert_validator.spiffe .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_TRUE(validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); } - // Different trust domain so should be rejected. - cert = readCertFromFile(TestEnvironment::substitute( - "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/spiffe_san_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { + { + // Different trust domain so should be rejected. + auto cert = readCertFromFile(TestEnvironment::substitute( + "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/spiffe_san_cert.pem")); bssl::UniquePtr cert_chain(sk_X509_new_null()); sk_X509_push(cert_chain.get(), cert.release()); EXPECT_EQ(ValidationResults::ValidationStatus::Failed, @@ -314,17 +299,11 @@ name: envoy.tls.cert_validator.spiffe .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_FALSE( - validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); } - - // Does not have san. - cert = readCertFromFile(TestEnvironment::substitute( - "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/extensions_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { + { + // Does not have san. + auto cert = readCertFromFile(TestEnvironment::substitute( + "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/extensions_cert.pem")); bssl::UniquePtr cert_chain(sk_X509_new_null()); sk_X509_push(cert_chain.get(), cert.release()); EXPECT_EQ(ValidationResults::ValidationStatus::Failed, @@ -332,17 +311,12 @@ name: envoy.tls.cert_validator.spiffe .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_FALSE( - validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); } EXPECT_EQ(2, stats().fail_verify_error_.value()); } -TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainMultipleTrustDomain) { +TEST_F(TestSPIFFEValidator, TestDoVerifyCertChainMultipleTrustDomain) { initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe typed_config: @@ -360,10 +334,10 @@ name: envoy.tls.cert_validator.spiffe SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); TestSslExtendedSocketInfo info; - // Trust domain matches so should be accepted. - auto cert = readCertFromFile(TestEnvironment::substitute( - "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { + { + // Trust domain matches so should be accepted. + auto cert = readCertFromFile(TestEnvironment::substitute( + "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_cert.pem")); bssl::UniquePtr cert_chain(sk_X509_new_null()); sk_X509_push(cert_chain.get(), cert.release()); EXPECT_EQ(ValidationResults::ValidationStatus::Successful, @@ -371,15 +345,11 @@ name: envoy.tls.cert_validator.spiffe .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_TRUE(validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); } - cert = readCertFromFile(TestEnvironment::substitute( - "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/spiffe_san_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { + { + auto cert = readCertFromFile(TestEnvironment::substitute( + "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/spiffe_san_cert.pem")); bssl::UniquePtr cert_chain(sk_X509_new_null()); sk_X509_push(cert_chain.get(), cert.release()); EXPECT_EQ(ValidationResults::ValidationStatus::Successful, @@ -387,17 +357,13 @@ name: envoy.tls.cert_validator.spiffe .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_TRUE(validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); } - // Trust domain matches but it has expired. - cert = readCertFromFile(TestEnvironment::substitute( - "{{ test_rundir " - "}}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { + { + // Trust domain matches but it has expired. + auto cert = readCertFromFile(TestEnvironment::substitute( + "{{ test_rundir " + "}}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem")); bssl::UniquePtr cert_chain(sk_X509_new_null()); sk_X509_push(cert_chain.get(), cert.release()); EXPECT_EQ(ValidationResults::ValidationStatus::Failed, @@ -405,17 +371,12 @@ name: envoy.tls.cert_validator.spiffe .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_FALSE( - validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); } - // Does not have san. - cert = readCertFromFile(TestEnvironment::substitute( - "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/extensions_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { + { + // Does not have san. + auto cert = readCertFromFile(TestEnvironment::substitute( + "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/extensions_cert.pem")); bssl::UniquePtr cert_chain(sk_X509_new_null()); sk_X509_push(cert_chain.get(), cert.release()); EXPECT_EQ(ValidationResults::ValidationStatus::Failed, @@ -423,17 +384,12 @@ name: envoy.tls.cert_validator.spiffe .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_FALSE( - validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); } EXPECT_EQ(2, stats().fail_verify_error_.value()); } -TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainMultipleTrustDomainAllowExpired) { +TEST_F(TestSPIFFEValidator, TestDoVerifyCertChainMultipleTrustDomainAllowExpired) { setAllowExpiredCertificate(true); initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe @@ -453,24 +409,18 @@ name: envoy.tls.cert_validator.spiffe auto cert = readCertFromFile(TestEnvironment::substitute( "{{ test_rundir " "}}/test/extensions/transport_sockets/tls/test_data/expired_spiffe_san_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - bssl::UniquePtr cert_chain(sk_X509_new_null()); - sk_X509_push(cert_chain.get(), cert.release()); - EXPECT_EQ(ValidationResults::ValidationStatus::Successful, - validator() - .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), - /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") - .status); - } else { - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); - EXPECT_TRUE(validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); - } + bssl::UniquePtr cert_chain(sk_X509_new_null()); + sk_X509_push(cert_chain.get(), cert.release()); + EXPECT_EQ(ValidationResults::ValidationStatus::Successful, + validator() + .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), + /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") + .status); EXPECT_EQ(0, stats().fail_verify_error_.value()); } -TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainSANMatching) { +TEST_F(TestSPIFFEValidator, TestDoVerifyCertChainSANMatching) { const auto config = TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe typed_config: @@ -489,9 +439,7 @@ name: envoy.tls.cert_validator.spiffe X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), nullptr)); bssl::UniquePtr cert_chain(sk_X509_new_null()); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - sk_X509_push(cert_chain.get(), cert.release()); - } + sk_X509_push(cert_chain.get(), cert.release()); TestSslExtendedSocketInfo info; info.setCertificateValidationStatus(Envoy::Ssl::ClientValidationStatus::NotValidated); { @@ -499,39 +447,28 @@ name: envoy.tls.cert_validator.spiffe matcher.set_prefix("spiffe://lyft.com/"); setSanMatchers({matcher}); initialize(config); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - ValidationResults results = validator().doVerifyCertChain( - *cert_chain, info.createValidateResultCallback(), - /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, ""); - EXPECT_EQ(ValidationResults::ValidationStatus::Successful, results.status); - EXPECT_EQ(Envoy::Ssl::ClientValidationStatus::Validated, results.detailed_status); - } else { - EXPECT_TRUE(validator().doSynchronousVerifyCertChain(store_ctx.get(), &info, *cert, nullptr)); - EXPECT_EQ(info.certificateValidationStatus(), Envoy::Ssl::ClientValidationStatus::Validated); - } + ValidationResults results = validator().doVerifyCertChain( + *cert_chain, info.createValidateResultCallback(), + /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, ""); + EXPECT_EQ(ValidationResults::ValidationStatus::Successful, results.status); + EXPECT_EQ(Envoy::Ssl::ClientValidationStatus::Validated, results.detailed_status); } { envoy::type::matcher::v3::StringMatcher matcher; matcher.set_prefix("spiffe://example.com/"); setSanMatchers({matcher}); initialize(config); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - ValidationResults results = validator().doVerifyCertChain( - *cert_chain, info.createValidateResultCallback(), - /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, ""); - EXPECT_EQ(ValidationResults::ValidationStatus::Failed, results.status); - EXPECT_EQ(Envoy::Ssl::ClientValidationStatus::Failed, results.detailed_status); - } else { - EXPECT_FALSE( - validator().doSynchronousVerifyCertChain(store_ctx.get(), &info, *cert, nullptr)); - EXPECT_EQ(info.certificateValidationStatus(), Envoy::Ssl::ClientValidationStatus::Failed); - } + ValidationResults results = validator().doVerifyCertChain( + *cert_chain, info.createValidateResultCallback(), + /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, ""); + EXPECT_EQ(ValidationResults::ValidationStatus::Failed, results.status); + EXPECT_EQ(Envoy::Ssl::ClientValidationStatus::Failed, results.detailed_status); EXPECT_EQ(1, stats().fail_verify_san_.value()); stats().fail_verify_san_.reset(); } } -TEST_P(TestSPIFFEValidator, TestDoVerifyCertChainIntermediateCerts) { +TEST_F(TestSPIFFEValidator, TestDoVerifyCertChainIntermediateCerts) { initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe typed_config: @@ -551,25 +488,15 @@ name: envoy.tls.cert_validator.spiffe "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/" "intermediate_ca_cert.pem")); - if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); - bssl::UniquePtr cert_chain(sk_X509_new_null()); - sk_X509_push(cert_chain.get(), cert.release()); - sk_X509_push(cert_chain.get(), intermediate_ca_cert.release()); - EXPECT_EQ(ValidationResults::ValidationStatus::Successful, - validator() - .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), - /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") - .status); - } else { - X509StorePtr store = X509_STORE_new(); - STACK_OF(X509)* intermediates = sk_X509_new_null(); - sk_X509_push(intermediates, intermediate_ca_cert.release()); - X509StoreContextPtr store_ctx = X509_STORE_CTX_new(); - EXPECT_TRUE(X509_STORE_CTX_init(store_ctx.get(), store.get(), cert.get(), intermediates)); - EXPECT_TRUE(validator().doSynchronousVerifyCertChain(store_ctx.get(), nullptr, *cert, nullptr)); - sk_X509_pop_free(intermediates, X509_free); - } + SSLContextPtr ssl_ctx = SSL_CTX_new(TLS_method()); + bssl::UniquePtr cert_chain(sk_X509_new_null()); + sk_X509_push(cert_chain.get(), cert.release()); + sk_X509_push(cert_chain.get(), intermediate_ca_cert.release()); + EXPECT_EQ(ValidationResults::ValidationStatus::Successful, + validator() + .doVerifyCertChain(*cert_chain, info.createValidateResultCallback(), + /*transport_socket_options=*/nullptr, *ssl_ctx, {}, false, "") + .status); } void addIA5StringGenNameExt(X509* cert, int type, const std::string name) { @@ -582,7 +509,7 @@ void addIA5StringGenNameExt(X509* cert, int type, const std::string name) { EXPECT_TRUE(X509_add1_ext_i2d(cert, NID_subject_alt_name, gens.get(), 0, X509V3_ADD_DEFAULT)); } -TEST_P(TestSPIFFEValidator, TestMatchSubjectAltNameWithURISan) { +TEST_F(TestSPIFFEValidator, TestMatchSubjectAltNameWithURISan) { envoy::type::matcher::v3::StringMatcher exact_matcher, prefix_matcher, regex_matcher; exact_matcher.set_exact("spiffe://example.com/workload"); prefix_matcher.set_prefix("spiffe://envoy.com"); @@ -627,7 +554,7 @@ name: envoy.tls.cert_validator.spiffe } // SPIFFE validator ignores any SANs other than URI. -TEST_P(TestSPIFFEValidator, TestMatchSubjectAltNameWithoutURISan) { +TEST_F(TestSPIFFEValidator, TestMatchSubjectAltNameWithoutURISan) { envoy::type::matcher::v3::StringMatcher exact_matcher, prefix_matcher; exact_matcher.set_exact("spiffe://example.com/workload"); prefix_matcher.set_prefix("envoy"); @@ -659,7 +586,7 @@ name: envoy.tls.cert_validator.spiffe } } -TEST_P(TestSPIFFEValidator, TestGetCaCertInformation) { +TEST_F(TestSPIFFEValidator, TestGetCaCertInformation) { initialize(); // No cert is set so this should be nullptr. @@ -682,7 +609,7 @@ name: envoy.tls.cert_validator.spiffe EXPECT_TRUE(actual); } -TEST_P(TestSPIFFEValidator, TestDaysUntilFirstCertExpires) { +TEST_F(TestSPIFFEValidator, TestDaysUntilFirstCertExpires) { initialize(); EXPECT_EQ(std::numeric_limits::max(), validator().daysUntilFirstCertExpires().value()); @@ -707,7 +634,7 @@ name: envoy.tls.cert_validator.spiffe EXPECT_EQ(19946, validator().daysUntilFirstCertExpires().value()); } -TEST_P(TestSPIFFEValidator, TestDaysUntilFirstCertExpiresExpired) { +TEST_F(TestSPIFFEValidator, TestDaysUntilFirstCertExpiresExpired) { Event::SimulatedTimeSystem time_system; // 2033-05-18 03:33:20 UTC const time_t known_date_time = 2000000000; @@ -727,7 +654,7 @@ name: envoy.tls.cert_validator.spiffe EXPECT_EQ(absl::nullopt, validator().daysUntilFirstCertExpires()); } -TEST_P(TestSPIFFEValidator, TestAddClientValidationContext) { +TEST_F(TestSPIFFEValidator, TestAddClientValidationContext) { Event::TestRealTimeSystem time_system; initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe @@ -770,7 +697,7 @@ name: envoy.tls.cert_validator.spiffe EXPECT_TRUE(foundTestCA); } -TEST_P(TestSPIFFEValidator, TestUpdateDigestForSessionId) { +TEST_F(TestSPIFFEValidator, TestUpdateDigestForSessionId) { Event::TestRealTimeSystem time_system; initialize(TestEnvironment::substitute(R"EOF( name: envoy.tls.cert_validator.spiffe diff --git a/test/extensions/transport_sockets/tls/cert_validator/timed_cert_validator.h b/test/extensions/transport_sockets/tls/cert_validator/timed_cert_validator.h index 890a76a48c6e..72e3a721daae 100644 --- a/test/extensions/transport_sockets/tls/cert_validator/timed_cert_validator.h +++ b/test/extensions/transport_sockets/tls/cert_validator/timed_cert_validator.h @@ -20,13 +20,6 @@ class TimedCertValidator : public DefaultCertValidator { : DefaultCertValidator(config, stats, time_source), validation_time_out_ms_(validation_time_out_ms), expected_host_name_(expected_host_name) {} - int doSynchronousVerifyCertChain( - X509_STORE_CTX* /*store_ctx*/, Ssl::SslExtendedSocketInfo* /*ssl_extended_info*/, - X509& /*leaf_cert*/, - const Network::TransportSocketOptions* /*transport_socket_options*/) override { - PANIC("unimplemented"); - } - ValidationResults doVerifyCertChain(STACK_OF(X509)& cert_chain, Ssl::ValidateResultCallbackPtr callback, const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, diff --git a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc index f79a8218c223..5cf4a34ff6fb 100644 --- a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc +++ b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc @@ -382,10 +382,6 @@ TEST_P(SslIntegrationTest, RouterHeaderOnlyRequestAndResponseWithSni) { } TEST_P(SslIntegrationTest, AsyncCertValidationSucceeds) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - // Config client to use an async cert validator which defer the actual validation by 5ms. envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = new envoy::config::core::v3::TypedExtensionConfig(); @@ -416,10 +412,6 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(SslIntegrationTest, AsyncCertValidationAfterTearDown) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = new envoy::config::core::v3::TypedExtensionConfig(); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( @@ -469,10 +461,6 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(SslIntegrationTest, AsyncCertValidationAfterSslShutdown) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = new envoy::config::core::v3::TypedExtensionConfig(); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( diff --git a/test/extensions/transport_sockets/tls/ssl_socket_test.cc b/test/extensions/transport_sockets/tls/ssl_socket_test.cc index 65b366f01606..e036a7b6c1d4 100644 --- a/test/extensions/transport_sockets/tls/ssl_socket_test.cc +++ b/test/extensions/transport_sockets/tls/ssl_socket_test.cc @@ -921,25 +921,12 @@ TestUtilOptionsV2 createProtocolTestOptions( } // namespace -std::string ipCustomCertValidationTestParamsToString( - const ::testing::TestParamInfo>& params) { - return fmt::format( - "{}_{}", - TestUtility::ipTestParamsToString( - ::testing::TestParamInfo(std::get<0>(params.param), 0)), - std::get<1>(params.param) ? "with_custom_cert_validation" : "with_sync_cert_validation"); -} - -class SslSocketTest - : public SslCertsTest, - public testing::WithParamInterface> { +class SslSocketTest : public SslCertsTest, + public testing::WithParamInterface { protected: SslSocketTest() : dispatcher_(api_->allocateDispatcher("test_thread")), - stream_info_(api_->timeSource(), nullptr), version_(std::get<0>(GetParam())) { - Runtime::maybeSetRuntimeGuard("envoy.reloadable_features.tls_async_cert_validation", - std::get<1>(GetParam())); - } + stream_info_(api_->timeSource(), nullptr), version_(GetParam()) {} void testClientSessionResumption(const std::string& server_ctx_yaml, const std::string& client_ctx_yaml, bool expect_reuse, @@ -951,10 +938,9 @@ class SslSocketTest Network::Address::IpVersion version_; }; -INSTANTIATE_TEST_SUITE_P( - IpVersions, SslSocketTest, - testing::Combine(testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), testing::Bool()), - ipCustomCertValidationTestParamsToString); +INSTANTIATE_TEST_SUITE_P(IpVersions, SslSocketTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); TEST_P(SslSocketTest, ServerTransportSocketOptions) { Stats::TestUtil::TestStore server_stats_store; @@ -2093,13 +2079,9 @@ TEST_P(SslSocketTest, FailedClientCertAllowExpiredBadHashVerification) { configureServerAndExpiredClientCertificate(listener, client, server_config); TestUtilOptionsV2 test_options(listener, client, false, version_); - testUtilV2( - test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") - .setExpectedClientCertUri("spiffe://lyft.com/test-team") - .setExpectedTransportFailureReasonContains( - Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation") - ? "TLSV1.*_BAD_CERTIFICATE_HASH_VALUE" - : "SSLV3_ALERT_HANDSHAKE_FAILURE")); + testUtilV2(test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") + .setExpectedClientCertUri("spiffe://lyft.com/test-team") + .setExpectedTransportFailureReasonContains("TLSV1.*_BAD_CERTIFICATE_HASH_VALUE")); } // Allow expired certificates, but use the wrong CA so it should fail still. @@ -2651,12 +2633,8 @@ TEST_P(SslSocketTest, FailedClientCertificateSpkiVerificationWrongClientCertific "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/no_san_key.pem")); TestUtilOptionsV2 test_options(listener, client, false, version_); - testUtilV2( - test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") - .setExpectedTransportFailureReasonContains( - Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation") - ? "TLSV1.*_BAD_CERTIFICATE_HASH_VALUE" - : "SSLV3_ALERT_HANDSHAKE_FAILURE")); + testUtilV2(test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") + .setExpectedTransportFailureReasonContains("TLSV1.*_BAD_CERTIFICATE_HASH_VALUE")); // Fails even with client renegotiation. client.set_allow_renegotiation(true); @@ -2689,12 +2667,8 @@ TEST_P(SslSocketTest, FailedClientCertificateSpkiVerificationNoCAWrongClientCert "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/no_san_key.pem")); TestUtilOptionsV2 test_options(listener, client, false, version_); - testUtilV2( - test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") - .setExpectedTransportFailureReasonContains( - Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation") - ? "TLSV1.*_BAD_CERTIFICATE_HASH_VALUE" - : "SSLV3_ALERT_HANDSHAKE_FAILURE")); + testUtilV2(test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") + .setExpectedTransportFailureReasonContains("TLSV1.*_BAD_CERTIFICATE_HASH_VALUE")); // Fails even with client renegotiation. client.set_allow_renegotiation(true); @@ -2899,12 +2873,8 @@ TEST_P(SslSocketTest, FailedClientCertificateHashAndSpkiVerificationWrongClientC "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/no_san_key.pem")); TestUtilOptionsV2 test_options(listener, client, false, version_); - testUtilV2( - test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") - .setExpectedTransportFailureReasonContains( - Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation") - ? "TLSV1.*_BAD_CERTIFICATE_HASH_VALUE" - : "SSLV3_ALERT_HANDSHAKE_FAILURE")); + testUtilV2(test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") + .setExpectedTransportFailureReasonContains("TLSV1.*_BAD_CERTIFICATE_HASH_VALUE")); // Fails even with client renegotiation. client.set_allow_renegotiation(true); @@ -2938,12 +2908,8 @@ TEST_P(SslSocketTest, FailedClientCertificateHashAndSpkiVerificationNoCAWrongCli "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/no_san_key.pem")); TestUtilOptionsV2 test_options(listener, client, false, version_); - testUtilV2( - test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") - .setExpectedTransportFailureReasonContains( - Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation") - ? "TLSV1.*_BAD_CERTIFICATE_HASH_VALUE" - : "SSLV3_ALERT_HANDSHAKE_FAILURE")); + testUtilV2(test_options.setExpectedServerStats("ssl.fail_verify_cert_hash") + .setExpectedTransportFailureReasonContains("TLSV1.*_BAD_CERTIFICATE_HASH_VALUE")); // Fails even with client renegotiation. client.set_allow_renegotiation(true); @@ -5983,10 +5949,9 @@ class SslReadBufferLimitTest : public SslSocketTest { Network::Address::InstanceConstSharedPtr source_address_; }; -INSTANTIATE_TEST_SUITE_P( - IpVersions, SslReadBufferLimitTest, - testing::Combine(testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), testing::Bool()), - ipCustomCertValidationTestParamsToString); +INSTANTIATE_TEST_SUITE_P(IpVersions, SslReadBufferLimitTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); TEST_P(SslReadBufferLimitTest, NoLimit) { readBufferLimitTest(0, 256 * 1024, 256 * 1024, 1, false); @@ -6948,10 +6913,6 @@ TEST_P(SslSocketTest, Sni) { } TEST_P(SslSocketTest, AsyncCustomCertValidatorSucceeds) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - const std::string client_ctx_yaml = R"EOF( common_tls_context: tls_certificates: @@ -6995,10 +6956,6 @@ TEST_P(SslSocketTest, AsyncCustomCertValidatorSucceeds) { } TEST_P(SslSocketTest, AsyncCustomCertValidatorFails) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - const std::string server_ctx_yaml = R"EOF( common_tls_context: tls_certificates: diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index cb506c233f37..97f93cda361e 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -1066,10 +1066,6 @@ TEST_P(QuicHttpIntegrationTest, NoStreams) { } TEST_P(QuicHttpIntegrationTest, AsyncCertVerificationSucceeds) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - // Config the client to defer cert validation by 5ms. envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = new envoy::config::core::v3::TypedExtensionConfig(); @@ -1086,10 +1082,6 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(QuicHttpIntegrationTest, AsyncCertVerificationAfterDisconnect) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = new envoy::config::core::v3::TypedExtensionConfig(); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( @@ -1129,10 +1121,6 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(QuicHttpIntegrationTest, AsyncCertVerificationAfterTearDown) { - if (!Runtime::runtimeFeatureEnabled("envoy.reloadable_features.tls_async_cert_validation")) { - return; - } - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = new envoy::config::core::v3::TypedExtensionConfig(); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( From 19e0611a97a128cecd9caf4f0bee01da1b2acedb Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Fri, 2 Jun 2023 16:08:58 -0400 Subject: [PATCH 166/228] composite: add CEL matcher to allow list (#27771) Add CEL matcher to allow list Signed-off-by: tyxia --- source/extensions/filters/http/composite/config.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/extensions/filters/http/composite/config.h b/source/extensions/filters/http/composite/config.h index 0ab7203f1093..8d088994378e 100644 --- a/source/extensions/filters/http/composite/config.h +++ b/source/extensions/filters/http/composite/config.h @@ -11,6 +11,8 @@ #include "source/common/protobuf/utility.h" #include "source/extensions/filters/http/common/factory_base.h" +#include "xds/type/matcher/v3/http_inputs.pb.h" + namespace Envoy { namespace Extensions { namespace HttpFilters { @@ -35,9 +37,12 @@ class CompositeFilterFactory // This ensure that trees are only allowed to match on request headers, avoiding configurations // where the matcher requires data that will be available too late for the delegation to work // correctly. - requirements->mutable_data_input_allow_list()->add_type_url( - TypeUtil::descriptorFullNameToTypeUrl( - envoy::type::matcher::v3::HttpRequestHeaderMatchInput::descriptor()->full_name())); + auto* allow_list = requirements->mutable_data_input_allow_list(); + allow_list->add_type_url(TypeUtil::descriptorFullNameToTypeUrl( + envoy::type::matcher::v3::HttpRequestHeaderMatchInput::descriptor()->full_name())); + // CEL matcher and its input is also allowed. + allow_list->add_type_url(TypeUtil::descriptorFullNameToTypeUrl( + xds::type::matcher::v3::HttpAttributesCelMatchInput::descriptor()->full_name())); return requirements; } From 2ab9d6b7f816acbbde3cecc9357efc4f0960c9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Sat, 3 Jun 2023 04:26:12 +0800 Subject: [PATCH 167/228] golang filter: support getting log level (#27652) Signed-off-by: spacewander --- contrib/golang/filters/http/source/cgo.cc | 2 ++ .../filters/http/source/go/pkg/api/api.h | 1 + .../filters/http/source/go/pkg/api/capi.go | 1 + .../filters/http/source/go/pkg/api/filter.go | 1 + .../filters/http/source/go/pkg/api/type.go | 18 ++++++++++++++++++ .../http/source/go/pkg/http/capi_impl.go | 4 ++++ .../filters/http/source/go/pkg/http/filter.go | 4 ++++ .../filters/http/source/golang_filter.cc | 2 ++ .../golang/filters/http/source/golang_filter.h | 1 + .../http/test/golang_integration_test.cc | 3 +++ .../http/test/test_data/basic/filter.go | 1 + 11 files changed, 38 insertions(+) diff --git a/contrib/golang/filters/http/source/cgo.cc b/contrib/golang/filters/http/source/cgo.cc index 56742609932a..74adb835d778 100644 --- a/contrib/golang/filters/http/source/cgo.cc +++ b/contrib/golang/filters/http/source/cgo.cc @@ -175,6 +175,8 @@ void envoyGoFilterHttpLog(uint32_t level, void* message) { getFilterLogger().log(level, mesg); } +uint32_t envoyGoFilterHttpLogLevel() { return getFilterLogger().level(); } + CAPIStatus envoyGoFilterHttpSetDynamicMetadata(void* r, void* name, void* key, void* buf) { return envoyGoFilterHandlerWrapper( r, [name, key, buf](std::shared_ptr& filter) -> CAPIStatus { diff --git a/contrib/golang/filters/http/source/go/pkg/api/api.h b/contrib/golang/filters/http/source/go/pkg/api/api.h index 3673e458d5c8..3620ff1dc454 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/api.h +++ b/contrib/golang/filters/http/source/go/pkg/api/api.h @@ -65,6 +65,7 @@ CAPIStatus envoyGoFilterHttpGetIntegerValue(void* r, int id, void* value); CAPIStatus envoyGoFilterHttpSetDynamicMetadata(void* r, void* name, void* key, void* buf); void envoyGoFilterHttpLog(uint32_t level, void* message); +uint32_t envoyGoFilterHttpLogLevel(); void envoyGoFilterHttpFinalize(void* r, int reason); diff --git a/contrib/golang/filters/http/source/go/pkg/api/capi.go b/contrib/golang/filters/http/source/go/pkg/api/capi.go index 764cf3845431..494bf72572be 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/capi.go +++ b/contrib/golang/filters/http/source/go/pkg/api/capi.go @@ -46,6 +46,7 @@ type HttpCAPI interface { HttpSetDynamicMetadata(r unsafe.Pointer, filterName string, key string, value interface{}) HttpLog(level LogType, message string) + HttpLogLevel() LogType HttpFinalize(r unsafe.Pointer, reason int) diff --git a/contrib/golang/filters/http/source/go/pkg/api/filter.go b/contrib/golang/filters/http/source/go/pkg/api/filter.go index 1979fc2935f0..1d3973a2f525 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/filter.go +++ b/contrib/golang/filters/http/source/go/pkg/api/filter.go @@ -93,6 +93,7 @@ type FilterCallbacks interface { // RecoverPanic recover panic in defer and terminate the request by SendLocalReply with 500 status code. RecoverPanic() Log(level LogType, msg string) + LogLevel() LogType // TODO add more for filter callbacks } diff --git a/contrib/golang/filters/http/source/go/pkg/api/type.go b/contrib/golang/filters/http/source/go/pkg/api/type.go index 24156b06a144..002cfd80a28d 100644 --- a/contrib/golang/filters/http/source/go/pkg/api/type.go +++ b/contrib/golang/filters/http/source/go/pkg/api/type.go @@ -70,6 +70,24 @@ const ( Critical LogType = 5 ) +func (self LogType) String() string { + switch self { + case Trace: + return "trace" + case Debug: + return "debug" + case Info: + return "info" + case Warn: + return "warn" + case Error: + return "error" + case Critical: + return "critical" + } + return "unknown" +} + //******************* log level end *******************// // ****************** HeaderMap start ******************// diff --git a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go index f043b5671224..3df76682028e 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go +++ b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go @@ -255,6 +255,10 @@ func (c *httpCApiImpl) HttpLog(level api.LogType, message string) { C.envoyGoFilterHttpLog(C.uint32_t(level), unsafe.Pointer(&message)) } +func (c *httpCApiImpl) HttpLogLevel() api.LogType { + return api.LogType(C.envoyGoFilterHttpLogLevel()) +} + func (c *httpCApiImpl) HttpFinalize(r unsafe.Pointer, reason int) { C.envoyGoFilterHttpFinalize(r, C.int(reason)) } diff --git a/contrib/golang/filters/http/source/go/pkg/http/filter.go b/contrib/golang/filters/http/source/go/pkg/http/filter.go index 881b2825b1b7..b035ab7a5e81 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/filter.go +++ b/contrib/golang/filters/http/source/go/pkg/http/filter.go @@ -115,6 +115,10 @@ func (r *httpRequest) Log(level api.LogType, message string) { cAPI.HttpLog(level, fmt.Sprintf("[go_plugin_http][%v] %v", r.pluginName(), message)) } +func (r *httpRequest) LogLevel() api.LogType { + return cAPI.HttpLogLevel() +} + func (r *httpRequest) StreamInfo() api.StreamInfo { return &streamInfo{ request: r, diff --git a/contrib/golang/filters/http/source/golang_filter.cc b/contrib/golang/filters/http/source/golang_filter.cc index 8dfd65f14ca6..82aa29bdd97f 100644 --- a/contrib/golang/filters/http/source/golang_filter.cc +++ b/contrib/golang/filters/http/source/golang_filter.cc @@ -1255,6 +1255,8 @@ void FilterLogger::log(uint32_t level, absl::string_view message) const { PANIC_DUE_TO_CORRUPT_ENUM; } +uint32_t FilterLogger::level() const { return static_cast(ENVOY_LOGGER().level()); } + } // namespace Golang } // namespace HttpFilters } // namespace Extensions diff --git a/contrib/golang/filters/http/source/golang_filter.h b/contrib/golang/filters/http/source/golang_filter.h index af1423103c15..7d175df45ed2 100644 --- a/contrib/golang/filters/http/source/golang_filter.h +++ b/contrib/golang/filters/http/source/golang_filter.h @@ -259,6 +259,7 @@ class FilterLogger : Logger::Loggable { FilterLogger() = default; void log(uint32_t level, absl::string_view message) const; + uint32_t level() const; }; class GoStringFilterState : public StreamInfo::FilterState::Object { diff --git a/contrib/golang/filters/http/test/golang_integration_test.cc b/contrib/golang/filters/http/test/golang_integration_test.cc index efda0c3f4541..1e4908e9986e 100644 --- a/contrib/golang/filters/http/test/golang_integration_test.cc +++ b/contrib/golang/filters/http/test/golang_integration_test.cc @@ -386,6 +386,9 @@ name: golang // verify host EXPECT_EQ("test.com", getHeader(response->headers(), "test-host")); + // verify log level + EXPECT_EQ("error", getHeader(response->headers(), "test-log-level")); + // upper("goodbye") EXPECT_EQ("GOODBYE", response->body()); diff --git a/contrib/golang/filters/http/test/test_data/basic/filter.go b/contrib/golang/filters/http/test/test_data/basic/filter.go index 3d73cd9df187..b1838067c1c3 100644 --- a/contrib/golang/filters/http/test/test_data/basic/filter.go +++ b/contrib/golang/filters/http/test/test_data/basic/filter.go @@ -256,6 +256,7 @@ func (f *filter) encodeHeaders(header api.ResponseHeaderMap, endStream bool) api header.Set("test-method", f.method) header.Set("test-path", f.path) header.Set("test-host", f.host) + header.Set("test-log-level", f.callbacks.LogLevel().String()) header.Set("rsp-route-name", f.callbacks.StreamInfo().GetRouteName()) header.Set("rsp-filter-chain-name", f.callbacks.StreamInfo().FilterChainName()) header.Set("rsp-attempt-count", strconv.Itoa(int(f.callbacks.StreamInfo().AttemptCount()))) From 62dcbc89cbd9ff67343c6fe3a2bbe70909b34864 Mon Sep 17 00:00:00 2001 From: phlax Date: Sat, 3 Jun 2023 16:30:48 +0100 Subject: [PATCH 168/228] ci: Minor cleanup for build script (#27780) Signed-off-by: Ryan Northey --- ci/build_setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/build_setup.sh b/ci/build_setup.sh index f0de186abd60..f4a94398f1bf 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -8,7 +8,7 @@ set -e if [[ -n "$NO_BUILD_SETUP" ]]; then - exit + return fi export PPROF_PATH=/thirdparty_build/bin/pprof From 22af18a40f043ac46d8c9ef9b51cb50f2ce69d50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Jun 2023 17:24:25 +0100 Subject: [PATCH 169/228] build(deps): bump github/codeql-action from 2.3.5 to 2.3.6 (#27764) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.3.5 to 2.3.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0225834cc549ee0ca93cb085b92954821a145866...83f0fe6c4988d98a455712a27f0255212bba9bd4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-daily.yml | 4 ++-- .github/workflows/codeql-push.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index b81e86623169..7c069b38723f 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -33,7 +33,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0225834cc549ee0ca93cb085b92954821a145866 + uses: github/codeql-action/init@83f0fe6c4988d98a455712a27f0255212bba9bd4 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -64,4 +64,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0225834cc549ee0ca93cb085b92954821a145866 + uses: github/codeql-action/analyze@83f0fe6c4988d98a455712a27f0255212bba9bd4 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index b1ab668242b7..f303a369c068 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0225834cc549ee0ca93cb085b92954821a145866 + uses: github/codeql-action/init@83f0fe6c4988d98a455712a27f0255212bba9bd4 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -78,4 +78,4 @@ jobs: - name: Perform CodeQL Analysis if: env.BUILD_TARGETS != '' - uses: github/codeql-action/analyze@0225834cc549ee0ca93cb085b92954821a145866 + uses: github/codeql-action/analyze@83f0fe6c4988d98a455712a27f0255212bba9bd4 From 4da4a1175e6774b610f5da4e736abc43ebcda9bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Jun 2023 17:40:18 +0100 Subject: [PATCH 170/228] build(deps): bump confluentinc/cp-zookeeper from `8fb8e15` to `90631f2` in /examples/kafka (#27766) build(deps): bump confluentinc/cp-zookeeper in /examples/kafka Bumps confluentinc/cp-zookeeper from `8fb8e15` to `90631f2`. --- updated-dependencies: - dependency-name: confluentinc/cp-zookeeper dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/kafka/Dockerfile-zookeeper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/kafka/Dockerfile-zookeeper b/examples/kafka/Dockerfile-zookeeper index 1cd685cc6876..b5c8f9c05a9c 100644 --- a/examples/kafka/Dockerfile-zookeeper +++ b/examples/kafka/Dockerfile-zookeeper @@ -1 +1 @@ -FROM confluentinc/cp-zookeeper:latest@sha256:8fb8e15d702d6935d21622ac03e789ba79bcedd3fa809134556d9fed0f88f0e9 +FROM confluentinc/cp-zookeeper:latest@sha256:90631f224b4397ecfb4e824e43d93e0e42656841c6d55ef635c49df3975260ae From 7731469dbdd94e2599fd0188a7c29b35f4f0c280 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Jun 2023 18:15:59 +0100 Subject: [PATCH 171/228] build(deps): bump cryptography from 39.0.2 to 41.0.0 in /.github/actions/pr_notifier (#27781) build(deps): bump cryptography in /.github/actions/pr_notifier Bumps [cryptography](https://github.com/pyca/cryptography) from 39.0.2 to 41.0.0. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/39.0.2...41.0.0) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/pr_notifier/requirements.txt | 44 +++++++++----------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/.github/actions/pr_notifier/requirements.txt b/.github/actions/pr_notifier/requirements.txt index f241eeaa3fc0..0ffc7c83a529 100644 --- a/.github/actions/pr_notifier/requirements.txt +++ b/.github/actions/pr_notifier/requirements.txt @@ -138,30 +138,26 @@ charset-normalizer==3.1.0 \ --hash=sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df \ --hash=sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab # via requests -cryptography==39.0.2 \ - --hash=sha256:103e8f7155f3ce2ffa0049fe60169878d47a4364b277906386f8de21c9234aa1 \ - --hash=sha256:23df8ca3f24699167daf3e23e51f7ba7334d504af63a94af468f468b975b7dd7 \ - --hash=sha256:2725672bb53bb92dc7b4150d233cd4b8c59615cd8288d495eaa86db00d4e5c06 \ - --hash=sha256:30b1d1bfd00f6fc80d11300a29f1d8ab2b8d9febb6ed4a38a76880ec564fae84 \ - --hash=sha256:35d658536b0a4117c885728d1a7032bdc9a5974722ae298d6c533755a6ee3915 \ - --hash=sha256:50cadb9b2f961757e712a9737ef33d89b8190c3ea34d0fb6675e00edbe35d074 \ - --hash=sha256:5f8c682e736513db7d04349b4f6693690170f95aac449c56f97415c6980edef5 \ - --hash=sha256:6236a9610c912b129610eb1a274bdc1350b5df834d124fa84729ebeaf7da42c3 \ - --hash=sha256:788b3921d763ee35dfdb04248d0e3de11e3ca8eb22e2e48fef880c42e1f3c8f9 \ - --hash=sha256:8bc0008ef798231fac03fe7d26e82d601d15bd16f3afaad1c6113771566570f3 \ - --hash=sha256:8f35c17bd4faed2bc7797d2a66cbb4f986242ce2e30340ab832e5d99ae60e011 \ - --hash=sha256:b49a88ff802e1993b7f749b1eeb31134f03c8d5c956e3c125c75558955cda536 \ - --hash=sha256:bc0521cce2c1d541634b19f3ac661d7a64f9555135e9d8af3980965be717fd4a \ - --hash=sha256:bc5b871e977c8ee5a1bbc42fa8d19bcc08baf0c51cbf1586b0e87a2694dde42f \ - --hash=sha256:c43ac224aabcbf83a947eeb8b17eaf1547bce3767ee2d70093b461f31729a480 \ - --hash=sha256:d15809e0dbdad486f4ad0979753518f47980020b7a34e9fc56e8be4f60702fac \ - --hash=sha256:d7d84a512a59f4412ca8549b01f94be4161c94efc598bf09d027d67826beddc0 \ - --hash=sha256:e029b844c21116564b8b61216befabca4b500e6816fa9f0ba49527653cae2108 \ - --hash=sha256:e8a0772016feeb106efd28d4a328e77dc2edae84dfbac06061319fdb669ff828 \ - --hash=sha256:e944fe07b6f229f4c1a06a7ef906a19652bdd9fd54c761b0ff87e83ae7a30354 \ - --hash=sha256:eb40fe69cfc6f5cdab9a5ebd022131ba21453cf7b8a7fd3631f45bbf52bed612 \ - --hash=sha256:fa507318e427169ade4e9eccef39e9011cdc19534f55ca2f36ec3f388c1f70f3 \ - --hash=sha256:ffd394c7896ed7821a6d13b24657c6a34b6e2650bd84ae063cf11ccffa4f1a97 +cryptography==41.0.0 \ + --hash=sha256:0ddaee209d1cf1f180f1efa338a68c4621154de0afaef92b89486f5f96047c55 \ + --hash=sha256:14754bcdae909d66ff24b7b5f166d69340ccc6cb15731670435efd5719294895 \ + --hash=sha256:344c6de9f8bda3c425b3a41b319522ba3208551b70c2ae00099c205f0d9fd3be \ + --hash=sha256:34d405ea69a8b34566ba3dfb0521379b210ea5d560fafedf9f800a9a94a41928 \ + --hash=sha256:3680248309d340fda9611498a5319b0193a8dbdb73586a1acf8109d06f25b92d \ + --hash=sha256:3c5ef25d060c80d6d9f7f9892e1d41bb1c79b78ce74805b8cb4aa373cb7d5ec8 \ + --hash=sha256:4ab14d567f7bbe7f1cdff1c53d5324ed4d3fc8bd17c481b395db224fb405c237 \ + --hash=sha256:5c1f7293c31ebc72163a9a0df246f890d65f66b4a40d9ec80081969ba8c78cc9 \ + --hash=sha256:6b71f64beeea341c9b4f963b48ee3b62d62d57ba93eb120e1196b31dc1025e78 \ + --hash=sha256:7d92f0248d38faa411d17f4107fc0bce0c42cae0b0ba5415505df72d751bf62d \ + --hash=sha256:8362565b3835ceacf4dc8f3b56471a2289cf51ac80946f9087e66dc283a810e0 \ + --hash=sha256:84a165379cb9d411d58ed739e4af3396e544eac190805a54ba2e0322feb55c46 \ + --hash=sha256:88ff107f211ea696455ea8d911389f6d2b276aabf3231bf72c8853d22db755c5 \ + --hash=sha256:9f65e842cb02550fac96536edb1d17f24c0a338fd84eaf582be25926e993dde4 \ + --hash=sha256:a4fc68d1c5b951cfb72dfd54702afdbbf0fb7acdc9b7dc4301bbf2225a27714d \ + --hash=sha256:b7f2f5c525a642cecad24ee8670443ba27ac1fab81bba4cc24c7b6b41f2d0c75 \ + --hash=sha256:b846d59a8d5a9ba87e2c3d757ca019fa576793e8758174d3868aecb88d6fc8eb \ + --hash=sha256:bf8fc66012ca857d62f6a347007e166ed59c0bc150cefa49f28376ebe7d992a2 \ + --hash=sha256:f5d0bf9b252f30a31664b6f64432b4730bb7038339bd18b1fafe129cfc2be9be # via pyjwt deprecated==1.2.13 \ --hash=sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d \ From ba9a2a7b0ee700117a49f493ff72fe080c5c2b9e Mon Sep 17 00:00:00 2001 From: phlax Date: Sun, 4 Jun 2023 08:30:28 +0100 Subject: [PATCH 172/228] deps: Bump tooling updates to resolve openssl vulns (#27779) Signed-off-by: Ryan Northey --- tools/base/requirements.in | 1 + tools/base/requirements.txt | 289 ++++++++++++++++++------------------ 2 files changed, 147 insertions(+), 143 deletions(-) diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 75ee140ce992..86532c679c85 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -4,6 +4,7 @@ aiohttp>=3.8.1 cffi>=1.15.0 colorama coloredlogs +cryptography>=41.0.1 dependatool>=0.2.2 envoy.base.utils>=0.4.11 envoy.code.check>=0.5.4 diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index a901bba652a5..b60e9117dd11 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -212,9 +212,9 @@ boto==2.49.0 \ --hash=sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8 \ --hash=sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a # via gcs-oauth2-boto-plugin -cachetools==5.3.0 \ - --hash=sha256:13dfddc7b8df938c21a940dfa6557ce6e94a2f1cdfa58eb90c805721d58f2c14 \ - --hash=sha256:429e1a1e845c008ea6c85aa35d4b98b65d6a9763eeef3e37e92728a12d1de9d4 +cachetools==5.3.1 \ + --hash=sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590 \ + --hash=sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b # via google-auth certifi==2023.5.7 \ --hash=sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7 \ @@ -383,36 +383,37 @@ coloredlogs==15.0.1 \ crcmod==1.7 \ --hash=sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e # via gsutil -cryptography==40.0.2 \ - --hash=sha256:05dc219433b14046c476f6f09d7636b92a1c3e5808b9a6536adf4932b3b2c440 \ - --hash=sha256:0dcca15d3a19a66e63662dc8d30f8036b07be851a8680eda92d079868f106288 \ - --hash=sha256:142bae539ef28a1c76794cca7f49729e7c54423f615cfd9b0b1fa90ebe53244b \ - --hash=sha256:3daf9b114213f8ba460b829a02896789751626a2a4e7a43a28ee77c04b5e4958 \ - --hash=sha256:48f388d0d153350f378c7f7b41497a54ff1513c816bcbbcafe5b829e59b9ce5b \ - --hash=sha256:4df2af28d7bedc84fe45bd49bc35d710aede676e2a4cb7fc6d103a2adc8afe4d \ - --hash=sha256:4f01c9863da784558165f5d4d916093737a75203a5c5286fde60e503e4276c7a \ - --hash=sha256:7a38250f433cd41df7fcb763caa3ee9362777fdb4dc642b9a349721d2bf47404 \ - --hash=sha256:8f79b5ff5ad9d3218afb1e7e20ea74da5f76943ee5edb7f76e56ec5161ec782b \ - --hash=sha256:956ba8701b4ffe91ba59665ed170a2ebbdc6fc0e40de5f6059195d9f2b33ca0e \ - --hash=sha256:a04386fb7bc85fab9cd51b6308633a3c271e3d0d3eae917eebab2fac6219b6d2 \ - --hash=sha256:a95f4802d49faa6a674242e25bfeea6fc2acd915b5e5e29ac90a32b1139cae1c \ - --hash=sha256:adc0d980fd2760c9e5de537c28935cc32b9353baaf28e0814df417619c6c8c3b \ - --hash=sha256:aecbb1592b0188e030cb01f82d12556cf72e218280f621deed7d806afd2113f9 \ - --hash=sha256:b12794f01d4cacfbd3177b9042198f3af1c856eedd0a98f10f141385c809a14b \ - --hash=sha256:c0764e72b36a3dc065c155e5b22f93df465da9c39af65516fe04ed3c68c92636 \ - --hash=sha256:c33c0d32b8594fa647d2e01dbccc303478e16fdd7cf98652d5b3ed11aa5e5c99 \ - --hash=sha256:cbaba590180cba88cb99a5f76f90808a624f18b169b90a4abb40c1fd8c19420e \ - --hash=sha256:d5a1bd0e9e2031465761dfa920c16b0065ad77321d8a8c1f5ee331021fda65e9 +cryptography==41.0.1 \ + --hash=sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db \ + --hash=sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a \ + --hash=sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039 \ + --hash=sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c \ + --hash=sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3 \ + --hash=sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485 \ + --hash=sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c \ + --hash=sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca \ + --hash=sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5 \ + --hash=sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5 \ + --hash=sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3 \ + --hash=sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb \ + --hash=sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43 \ + --hash=sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31 \ + --hash=sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc \ + --hash=sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b \ + --hash=sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006 \ + --hash=sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a \ + --hash=sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699 # via + # -r requirements.in # pyjwt # pyopenssl dependatool==0.2.2 \ --hash=sha256:8e66850c79e37325735efa67ce06e2d5a939c0dab758f37b9bd3d09d0fb1f9a4 \ --hash=sha256:dff28853a7252d6a5d670c2519165506902c0d4746cbbdac99d2ad63ed96d82d # via -r requirements.in -deprecated==1.2.13 \ - --hash=sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d \ - --hash=sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d +deprecated==1.2.14 \ + --hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \ + --hash=sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3 # via pygithub docutils==0.19 \ --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ @@ -621,9 +622,9 @@ frozenlist==1.3.3 \ gcs-oauth2-boto-plugin==3.0 \ --hash=sha256:f4120b08b7f8d32904674c98f07d4caf4083a58343c0c0fa0016e0f0254dfe31 # via gsutil -gidgethub==5.2.1 \ - --hash=sha256:8ac9cf5314aac0f3a33f46127d4a538d0ed1a7030027eb2fc4aa3b55c66abcef \ - --hash=sha256:a533f85a57955261433c250701476304cc374037c0ab66b0e5372b4846749d5c +gidgethub==5.3.0 \ + --hash=sha256:4dd92f2252d12756b13f9dd15cde322bfb0d625b6fb5d680da1567ec74b462c0 \ + --hash=sha256:9ece7d37fbceb819b80560e7ed58f936e48a65d37ec5f56db79145156b426a25 # via # aio-api-github # envoy-dependency-check @@ -648,9 +649,9 @@ google-apitools==0.5.32 \ --hash=sha256:b78f74116558e0476e19501b5b4b2ac7c93261a69c5449c861ea95cbc853c688 \ --hash=sha256:c3763e52289f61e21c41d5531e20fbda9cc8484a088b8686fd460770db8bad13 # via gsutil -google-auth[aiohttp]==2.17.3 \ - --hash=sha256:ce311e2bc58b130fddf316df57c9b3943c2a7b4f6ec31de9663a9333e4064efc \ - --hash=sha256:f586b274d3eb7bd932ea424b1c702a30e0393a2e2bc4ca3eae8263ffd8be229f +google-auth[aiohttp]==2.19.1 \ + --hash=sha256:a9cfa88b3e16196845e64a3658eb953992129d13ac7337b064c6546f77c17183 \ + --hash=sha256:ea165e014c7cbd496558796b627c271aa8c18b4cba79dc1cc962b24c5efdfb85 # via # google-api-core # google-cloud-core @@ -781,57 +782,57 @@ jinja2==3.1.2 \ # envoy-base-utils # envoy-dependency-check # sphinx -markupsafe==2.1.2 \ - --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ - --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ - --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ - --hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \ - --hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \ - --hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \ - --hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \ - --hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \ - --hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \ - --hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \ - --hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \ - --hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \ - --hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \ - --hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \ - --hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \ - --hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \ - --hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \ - --hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \ - --hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \ - --hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \ - --hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \ - --hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \ - --hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \ - --hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \ - --hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \ - --hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \ - --hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \ - --hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \ - --hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \ - --hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \ - --hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \ - --hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \ - --hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \ - --hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \ - --hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \ - --hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \ - --hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \ - --hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \ - --hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \ - --hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \ - --hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \ - --hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \ - --hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \ - --hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \ - --hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \ - --hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \ - --hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \ - --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ - --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ - --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 +markupsafe==2.1.3 \ + --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \ + --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ + --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ + --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \ + --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \ + --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \ + --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \ + --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \ + --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \ + --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \ + --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \ + --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \ + --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \ + --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \ + --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \ + --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \ + --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \ + --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \ + --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \ + --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \ + --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \ + --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \ + --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \ + --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \ + --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \ + --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \ + --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \ + --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \ + --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \ + --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \ + --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \ + --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \ + --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \ + --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \ + --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \ + --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \ + --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \ + --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \ + --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \ + --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \ + --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \ + --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \ + --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \ + --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \ + --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \ + --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \ + --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \ + --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ + --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ + --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 # via jinja2 mccabe==0.7.0 \ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ @@ -926,53 +927,53 @@ oauth2client==4.1.3 \ # via # gcs-oauth2-boto-plugin # google-apitools -orjson==3.8.14 \ - --hash=sha256:01640ab79111dd97515cba9fab7c66cb3b0967b0892cc74756a801ff681a01b6 \ - --hash=sha256:017de5ba22e58dfa6f41914f5edb8cd052d23f171000684c26b2d2ab219db31e \ - --hash=sha256:04c70dc8ca79b0072a16d82f94b9d9dd6598a43dd753ab20039e9f7d2b14f017 \ - --hash=sha256:062829b5e20cd8648bf4c11c3a5ee7cf196fa138e573407b5312c849b0cf354d \ - --hash=sha256:087c0dc93379e8ba2d59e9f586fab8de8c137d164fccf8afd5523a2137570917 \ - --hash=sha256:09a3bf3154f40299b8bc95e9fb8da47436a59a2106fc22cae15f76d649e062da \ - --hash=sha256:0bc6b7abf27f1dc192dadad249df9b513912506dd420ce50fd18864a33789b71 \ - --hash=sha256:0bf00c42333412a9338297bf888d7428c99e281e20322070bde8c2314775508b \ - --hash=sha256:19415aaf30525a5baff0d72a089fcdd68f19a3674998263c885c3908228c1086 \ - --hash=sha256:20b7ffc7736000ea205f9143df322b03961f287b4057606291c62c842ff3c5b5 \ - --hash=sha256:27967be4c16bd09f4aeff8896d9be9cbd00fd72f5815d5980e4776f821e2f77c \ - --hash=sha256:31a2a29be559e92dcc5c278787b4166da6f0d45675b59a11c4867f5d1455ebf4 \ - --hash=sha256:33bc310da4ad2ffe8f7f1c9e89692146d9ec5aec2d1c9ef6b67f8dc5e2d63241 \ - --hash=sha256:38ca39bae7fbc050332a374062d4cdec28095540fa8bb245eada467897a3a0bb \ - --hash=sha256:3ee09bfbf1d54c127d3061f6721a1a11d2ce502b50597c3d0d2e1bd2d235b764 \ - --hash=sha256:5ea93fd3ef7be7386f2516d728c877156de1559cda09453fc7dd7b696d0439b3 \ - --hash=sha256:5fb66f0ac23e861b817c858515ac1f74d1cd9e72e3f82a5b2c9bae9f92286adc \ - --hash=sha256:6112194c11e611596eed72f46efb0e6b4812682eff3c7b48473d1146c3fa0efb \ - --hash=sha256:64b4fca0531030040e611c6037aaf05359e296877ab0a8e744c26ef9c32738b9 \ - --hash=sha256:67a7e883b6f782b106683979ccc43d89b98c28a1f4a33fe3a22e253577499bb1 \ - --hash=sha256:716a3994e039203f0a59056efa28185d4cac51b922cc5bf27ab9182cfa20e12e \ - --hash=sha256:739f9f633e1544f2a477fa3bef380f488c8dca6e2521c8dc36424b12554ee31e \ - --hash=sha256:7a7b0fead2d0115ef927fa46ad005d7a3988a77187500bf895af67b365c10d1f \ - --hash=sha256:7cb35dd3ba062c1d984d57e6477768ed7b62ed9260f31362b2d69106f9c60ebd \ - --hash=sha256:7d3d8faded5a514b80b56d0429eb38b429d7a810f8749d25dc10a0cc15b8a3c8 \ - --hash=sha256:7e2f75b7d9285e35c3d4dff9811185535ff2ea637f06b2b242cb84385f8ffe63 \ - --hash=sha256:87ba7882e146e24a7d8b4a7971c20212c2af75ead8096fc3d55330babb1015fb \ - --hash=sha256:8a896a12b38fe201a72593810abc1f4f1597e65b8c869d5fc83bbcf75d93398f \ - --hash=sha256:8b206cca6836a4c6683bcaa523ab467627b5f03902e5e1082dc59cd010e6925f \ - --hash=sha256:92374bc35b6da344a927d5a850f7db80a91c7b837de2f0ea90fc870314b1ff44 \ - --hash=sha256:9393a63cb0424515ec5e434078b3198de6ec9e057f1d33bad268683935f0a5d5 \ - --hash=sha256:9725226478d1dafe46d26f758eadecc6cf98dcbb985445e14a9c74aaed6ccfea \ - --hash=sha256:97ebb7fab5f1ae212a6501f17cb7750a6838ffc2f1cebbaa5dec1a90038ca3c6 \ - --hash=sha256:9df820e6c8c84c52ec39ea2cc9c79f7999c839c7d1481a056908dce3b90ce9f9 \ - --hash=sha256:9f5cf61b6db68f213c805c55bf0aab9b4cb75a4e9c7f5bfbd4deb3a0aef0ec53 \ - --hash=sha256:aedba48264fe87e5060c0e9c2b28909f1e60626e46dc2f77e0c8c16939e2e1f7 \ - --hash=sha256:bf6825e160e4eb0ef65ce37d8c221edcab96ff2ffba65e5da2437a60a12b3ad1 \ - --hash=sha256:ca90db8f551b8960da95b0d4cad6c0489df52ea03585b6979595be7b31a3f946 \ - --hash=sha256:d03f29b0369bb1ab55c8a67103eb3a9675daaf92f04388568034fe16be48fa5d \ - --hash=sha256:d66966fd94719beb84e8ed84833bc59c3c005d3d2d0c42f11d7552d3267c6de7 \ - --hash=sha256:de1ee13d6b6727ee1db38722695250984bae81b8fc9d05f1176c74d14b1322d9 \ - --hash=sha256:e53bc5beb612df8ddddb065f079d3fd30b5b4e73053518524423549d61177f3f \ - --hash=sha256:ebca14ae80814219ea3327e3dfa7ff618621ff335e45781fac26f5cd0b48f2b4 \ - --hash=sha256:ee0299b2dda9afce351a5e8c148ea7a886de213f955aa0288fb874fb44829c36 \ - --hash=sha256:f4ac01a3db4e6a98a8ad1bb1a3e8bfc777928939e87c04e93e0d5006df574a4b \ - --hash=sha256:f80e62afe49e6bfc706e041faa351d7520b5f86572b8e31455802251ea989613 +orjson==3.9.0 \ + --hash=sha256:04e61db09ff155846b69d07cf5aa21001f2010ea669ec3169c1fbad9c9e40cd5 \ + --hash=sha256:08cb43569198c1f5c89ecafcbfc62414f6115d894ff908d8cf8e5e24801364e6 \ + --hash=sha256:09522937479bd39d5bb32d11a5ecdf6926fda43ac2cbde21cc1a9508b4e4ea29 \ + --hash=sha256:09ee828572fadcd58bf356d2c1bad99a95c7c9c1f182b407abbc7dec1810f542 \ + --hash=sha256:0e7fe5d603ee9177ff2e45858b4fc47fea2da0688f23d9773654889d56dfbc82 \ + --hash=sha256:108c58d2c7648c991f82f9b2217c50981ad7cf6aaee3efbfaa9d807e49cd69b8 \ + --hash=sha256:128b1cd0f00a37ba64a12cceeba4e8070655d4400edd55a737513ee663c1ed5a \ + --hash=sha256:1e3bde77c1e0061eb34bae6fea44818b2198e043ee10a16ad7b160921fee26ea \ + --hash=sha256:21f6a6fdfbc13cd715c61e9fa9daeff732df6401ab7d6a2ebad0042313a40bd1 \ + --hash=sha256:2536a7f30fd4d77532769ea9285cd20c69bd2b40acf980de94bbc79b1c6fad5a \ + --hash=sha256:271b6f1018757fc6bca40ae72e6cdb6cf84584dde2d1e5eaac30e387a13d9e72 \ + --hash=sha256:2af7dff1c7ddb0c83eb5773acf6566b153f8cd32e4ba782ae9ccd6d0f324efd3 \ + --hash=sha256:3235c31d0fe674f6e3433e9ddfed212aa840c83a9b6ef5ae128950e2c808c303 \ + --hash=sha256:3a208d0bca609de3152eb8320d5093ad9c52979332f626c13500d1645c66bf8d \ + --hash=sha256:3f1193417b5a93deb41bcb8db27b61179b9b3e299b337b578c31f19159664da3 \ + --hash=sha256:44fa74b497e608a8cdca1ee37fe3533a30f17163c7e2872ab1b854900cf0dfcf \ + --hash=sha256:45df5bf6531ffda518331cc93cdcd4c84f4a4a0507d72af8fb698c7131a440a0 \ + --hash=sha256:46c9733330b75c116438f555c0b971a2388b5f502e2dd4ec3bf6bacb96f82741 \ + --hash=sha256:47d7e4a3effc0e9314bd5b06e7431f2490a5e64dcdcbbc4d60e713786fec327d \ + --hash=sha256:5afd22847b07b63f2b8fcfddd5b7a6f47c5aaa25e19b97a3d6d39508b8fd465a \ + --hash=sha256:6c50654e4870805e4b1a587c2c3c5ef2f36f3e67fc463a738339ff40d65f7db1 \ + --hash=sha256:721d47dffedb7795ffea8a06f2de7d192de7b58e085cf357a99abf0eb931f2c3 \ + --hash=sha256:748c1e8df0b0880c63d323e167ad17ab4db2e1178a40902c2fcb68cbe402d7c8 \ + --hash=sha256:7a3693fde44b2eeb80074ecbe8c504b25baf71e66c080af2a574193a5ba81960 \ + --hash=sha256:86da00836029b2a071229c8aecab998a2f316c1bc7de10ae020d7311de3a6d0d \ + --hash=sha256:88626d898c408450c57664899831cf072787898af4847fa4466607ad2a83f454 \ + --hash=sha256:8a1fcddcabe121e393f3c4a31ed6d3535214d42a4ece0f9dde2e250006d6a58d \ + --hash=sha256:949698bdddb1daff986d73e6bbe6cd68833cd80c4adc6b69fafbd46634d4672c \ + --hash=sha256:9de2129d40674007cb24164939e075b5b39fee768bf20801e08c0e3283bfb18e \ + --hash=sha256:9ee5f1ba82146a50d61fb58d310a37c0f406eda898172f9c98673b5d6f9461c3 \ + --hash=sha256:a901c432828c191332d75f358142736c433d4a192f7794123e1d30d68193de86 \ + --hash=sha256:bd89d63707ac616462832bfc5d16fa0c12483f86add2432ce55c8710c9531c03 \ + --hash=sha256:c41d1ef6ec308e9e3701764b3de889ed8c1c126eceaea881dd1027bffbed89fe \ + --hash=sha256:c4949fc1304b702197c0840882e84b86d8d5ca33c3d945cc60727bc1786c2b20 \ + --hash=sha256:c68af71b1110820c914f9df75842895b5528ff524d3286fde57097b2b5ed8f22 \ + --hash=sha256:c7b241c3229084035b38cac9b5c96b43644da829da41d9d5be0fefb96fb116e1 \ + --hash=sha256:d2fbf34667a8be48ec89d5ef479a00d4e7b3acda62d722c97377702da0c30ffd \ + --hash=sha256:d414fd0678e949779104f5b307f0f9fac861728e19d3cdde66759af77f892da0 \ + --hash=sha256:d4c2d31178e3027affd98eead033f1c406890df83a0ca2016604cc21f722a1d1 \ + --hash=sha256:d4fcf598bd5a99a94caa7ec92ce657939f12491e4753ea7e4d6c03faf5f7912e \ + --hash=sha256:e44ebe2129d43c5a48f3affa3fa59c6484ed16faf5b00486add1061a95384ab0 \ + --hash=sha256:ebe372e9f4e4f0335b7b4ebfab991b3734371e3d5b7f989ca3baa5da25185f4a \ + --hash=sha256:edd77183c154cbedaa6dac32fee9cb770b04e2a7f367a5864f444578554cc946 \ + --hash=sha256:f6476e2487c0b7387187de15e5b8f6635c29b75934f2e689ca8cad6550439f3d \ + --hash=sha256:f6ab80b60195f166a9d666b2eaf6d2c74202b6da2a1fb4b4d66b9cc0ce5c9957 \ + --hash=sha256:f6dd27c71cd6e146795f876449a8eae74f67ae1e4e244dfc1203489103eb2d94 # via # -r requirements.in # envoy-base-utils @@ -1075,9 +1076,9 @@ pynacl==1.5.0 \ --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 # via pygithub -pyopenssl==23.1.1 \ - --hash=sha256:841498b9bec61623b1b6c47ebbc02367c07d60e0e195f19790817f10cc8db0b7 \ - --hash=sha256:9e0c526404a210df9d2b18cd33364beadb0dc858a739b885677bc65e105d4a4c +pyopenssl==23.2.0 \ + --hash=sha256:24f0dc5227396b3e831f4c7f602b950a5e9833d292c8e4a2e06b709292806ae2 \ + --hash=sha256:276f931f55a452e7dea69c7173e984eb2a4407ce413c918aa34b55f82f9b8bac # via # gcs-oauth2-boto-plugin # gsutil @@ -1257,18 +1258,20 @@ trycast==1.0.0 \ # via # aio-core # envoy-base-utils -typing-extensions==4.5.0 \ - --hash=sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb \ - --hash=sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4 +typing-extensions==4.6.3 \ + --hash=sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26 \ + --hash=sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5 # via aiodocker uritemplate==4.1.1 \ --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e # via gidgethub -urllib3==2.0.2 \ - --hash=sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc \ - --hash=sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e - # via requests +urllib3==1.26.16 \ + --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \ + --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14 + # via + # google-auth + # requests uvloop==0.17.0 \ --hash=sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d \ --hash=sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1 \ @@ -1388,9 +1391,9 @@ wrapt==1.15.0 \ --hash=sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559 \ --hash=sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639 # via deprecated -yamllint==1.31.0 \ - --hash=sha256:15f4bdb645e6a4a0a22fe5415bc38b4a934c51419b30104896d2f3f95e329185 \ - --hash=sha256:2d83f1d12f733e162a87e06b176149d7bb9c5bae4a9e5fce1c771d7f703f7a65 +yamllint==1.32.0 \ + --hash=sha256:d01dde008c65de5b235188ab3110bebc59d18e5c65fc8a58267cd211cd9df34a \ + --hash=sha256:d97a66e48da820829d96077d76b8dfbe6c6140f106e558dae87e81ac4e6b30b7 # via envoy-code-check yapf==0.33.0 \ --hash=sha256:4c2b59bd5ffe46f3a7da48df87596877189148226ce267c16e8b44240e51578d \ From 741aec091014f2f4374c77a064812a5ca9917ae4 Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 5 Jun 2023 07:31:34 +0100 Subject: [PATCH 173/228] release/ci: Prevent release if Docker job fails (#27782) Signed-off-by: Ryan Northey --- .azure-pipelines/stage/publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml index b028aa88c9ea..7d4e5fef9887 100644 --- a/.azure-pipelines/stage/publish.yml +++ b/.azure-pipelines/stage/publish.yml @@ -392,6 +392,7 @@ jobs: dependsOn: ["success"] condition: | and(not(canceled()), + in(dependencies.success.result, 'Succeeded', 'SucceededWithIssues'), eq(${{ parameters.publishGithubRelease }}, 'true')) pool: vmImage: "ubuntu-20.04" From 22866f4c3af0a7875bb4ee32722703202e6b441e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 07:42:31 +0100 Subject: [PATCH 174/228] build(deps): bump confluentinc/cp-kafka from `328bb7b` to `187dac6` in /examples/kafka (#27767) build(deps): bump confluentinc/cp-kafka in /examples/kafka Bumps confluentinc/cp-kafka from `328bb7b` to `187dac6`. --- updated-dependencies: - dependency-name: confluentinc/cp-kafka dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/kafka/Dockerfile-kafka | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/kafka/Dockerfile-kafka b/examples/kafka/Dockerfile-kafka index 46f63575c21e..d354e9a3650f 100644 --- a/examples/kafka/Dockerfile-kafka +++ b/examples/kafka/Dockerfile-kafka @@ -1 +1 @@ -FROM confluentinc/cp-kafka:latest@sha256:328bb7b00e15f173bee5f68a9da0c97651ca961e2f7736563dc55bbebac80e5e +FROM confluentinc/cp-kafka:latest@sha256:187dac6627e7906c350f5f8c982f80ce735ff1a0e571a20de6000a309a12ce63 From 20f12ed907c588d7d0ed0d3320d22f663c13864b Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 5 Jun 2023 08:42:50 +0100 Subject: [PATCH 175/228] release/ci: Add dry-run var for non-postsubmit (#27784) Signed-off-by: Ryan Northey --- .azure-pipelines/env.yml | 7 +++++++ .azure-pipelines/stage/publish.yml | 6 ++++++ .azure-pipelines/stages.yml | 2 ++ ci/do_ci.sh | 2 +- ci/run_envoy_docker.sh | 1 + 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/env.yml b/.azure-pipelines/env.yml index 01a9a78d081f..9511877caf0a 100644 --- a/.azure-pipelines/env.yml +++ b/.azure-pipelines/env.yml @@ -183,6 +183,8 @@ jobs: set -e PUBLISH_GITHUB_RELEASE=$(run.packaging) + # NB: leave this empty as it is checked `-n` + PUBLISH_GITHUB_RELEASE_DRY_RUN= PUBLISH_DOCKERHUB=false PUBLISH_DOCS=false PUBLISH_DOCS_LATEST=false @@ -212,8 +214,12 @@ jobs: PUBLISH_DOCS=false fi fi + if [[ -z "$POSTSUBMIT" ]]; then + PUBLISH_GITHUB_RELEASE_DRY_RUN=true + fi echo "##vso[task.setvariable variable=githubRelease;isoutput=true]${PUBLISH_GITHUB_RELEASE}" + echo "##vso[task.setvariable variable=githubReleaseDryRun;isoutput=true]${PUBLISH_GITHUB_RELEASE_DRY_RUN}" echo "##vso[task.setvariable variable=dockerhub;isoutput=true]${PUBLISH_DOCKERHUB}" echo "##vso[task.setvariable variable=docs;isoutput=true]${PUBLISH_DOCS}" echo "##vso[task.setvariable variable=docsLatest;isoutput=true]${PUBLISH_DOCS_LATEST}" @@ -240,6 +246,7 @@ jobs: echo "env.outputs['run.packaging']: $(run.packaging)" echo echo "env.outputs['publish.githubRelease']: $(publish.githubRelease)" + echo "env.outputs['publish.githubReleaseDryRun']: $(publish.githubReleaseDryRun)" echo "env.outputs['publish.dockerhub]: $(publish.dockerhub)" echo "env.outputs['publish.docs]: $(publish.docs)" echo "env.outputs['publish.docsLatest]: $(publish.docsLatest)" diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml index 7d4e5fef9887..beb715a6b46d 100644 --- a/.azure-pipelines/stage/publish.yml +++ b/.azure-pipelines/stage/publish.yml @@ -90,6 +90,10 @@ parameters: displayName: "Publish Github release" type: string default: false +- name: publishGithubReleaseDryRun + displayName: "Publish Github release (dry run)" + type: string + default: false jobs: @@ -409,3 +413,5 @@ jobs: cacheVersion: $(cacheKeyBazel) publishEnvoy: false publishTestResults: false + env: + ENVOY_PUBLISH_DRY_RUN: ${{ parameters.publishGithubReleaseDryRun }} diff --git a/.azure-pipelines/stages.yml b/.azure-pipelines/stages.yml index de69153bfbf7..4100bd1258b9 100644 --- a/.azure-pipelines/stages.yml +++ b/.azure-pipelines/stages.yml @@ -122,6 +122,7 @@ stages: RUN_DOCKER: $[stageDependencies.env.repo.outputs['run.docker']] RUN_PACKAGING: $[stageDependencies.env.repo.outputs['run.packaging']] PUBLISH_GITHUB_RELEASE: $[stageDependencies.env.repo.outputs['publish.githubRelease']] + PUBLISH_GITHUB_RELEASE_DRY_RUN: $[stageDependencies.env.repo.outputs['publish.githubReleaseDryRun']] PUBLISH_DOCKERHUB: $[stageDependencies.env.repo.outputs['publish.dockerhub']] PUBLISH_DOCS: $[stageDependencies.env.repo.outputs['publish.docs']] PUBLISH_DOCS_LATEST: $[stageDependencies.env.repo.outputs['publish.docsLatest']] @@ -153,6 +154,7 @@ stages: publishDocsRelease: variables['PUBLISH_DOCS_RELEASE'] publishDockerhub: variables['PUBLISH_DOCKERHUB'] publishGithubRelease: variables['PUBLISH_GITHUB_RELEASE'] + publishGithubReleaseDryRun: variables['PUBLISH_GITHUB_RELEASE_DRY_RUN'] - stage: verify displayName: Verify diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 2d7b61298396..c320a7a29e4a 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -624,7 +624,7 @@ case $CI_TARGET in PUBLISH_ARGS=( --publish-commitish="$BUILD_SHA" --publish-assets=/build/release.signed/release.signed.tar.zst) - if [[ "$VERSION_DEV" == "dev" ]]; then + if [[ "$VERSION_DEV" == "dev" ]] || [[ -n "$ENVOY_PUBLISH_DRY_RUN" ]]; then PUBLISH_ARGS+=(--dry-run) fi bazel run "${BAZEL_BUILD_OPTIONS[@]}" \ diff --git a/ci/run_envoy_docker.sh b/ci/run_envoy_docker.sh index 7fd9bac73335..fdda903eae86 100755 --- a/ci/run_envoy_docker.sh +++ b/ci/run_envoy_docker.sh @@ -133,6 +133,7 @@ docker run --rm \ -e ENVOY_BUILD_FILTER_EXAMPLE \ -e ENVOY_COMMIT \ -e ENVOY_HEAD_REF \ + -e ENVOY_PUBLISH_DRY_RUN \ -e ENVOY_REPO \ -e SYSTEM_PULLREQUEST_PULLREQUESTNUMBER \ -e GCS_ARTIFACT_BUCKET \ From fe8fd73ef6fe46644fe65098ec8d629f3f384530 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 09:13:47 +0100 Subject: [PATCH 176/228] build(deps): bump mysql from `d6164ff` to `4bae986` in /examples/mysql (#27797) Bumps mysql from `d6164ff` to `4bae986`. --- updated-dependencies: - dependency-name: mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/mysql/Dockerfile-mysql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/mysql/Dockerfile-mysql b/examples/mysql/Dockerfile-mysql index de8c80df6a3e..d1038cf5ca42 100644 --- a/examples/mysql/Dockerfile-mysql +++ b/examples/mysql/Dockerfile-mysql @@ -1 +1 @@ -FROM mysql:8.0.33@sha256:d6164ff4855b9b3f2c7748c6ec564ccff841f79a7023db0f9293143481a44b6e +FROM mysql:8.0.33@sha256:4bae98614cd6ad1aecbdd32ff1b37b93fb0ee22b069469e7bc9679bacef1abd2 From 0d6fab926bb9f166200e90153ca3b403b0cf9640 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 09:16:27 +0100 Subject: [PATCH 177/228] build(deps): bump jaegertracing/all-in-one from `1cb8093` to `12e96c7` in /examples/shared/jaeger (#27798) build(deps): bump jaegertracing/all-in-one in /examples/shared/jaeger Bumps jaegertracing/all-in-one from `1cb8093` to `12e96c7`. --- updated-dependencies: - dependency-name: jaegertracing/all-in-one dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/jaeger/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/jaeger/Dockerfile b/examples/shared/jaeger/Dockerfile index b9fcb0029145..5c671c6b6cad 100644 --- a/examples/shared/jaeger/Dockerfile +++ b/examples/shared/jaeger/Dockerfile @@ -1,4 +1,4 @@ -FROM jaegertracing/all-in-one@sha256:1cb80937ebe12ed06267d2f773623d33a4610df9ef59d82e92c15613f31772ed +FROM jaegertracing/all-in-one@sha256:12e96c7396d758da7d300d162f2aab899c2f6cc51e037cc7bced8dbd6d3cfc5d HEALTHCHECK \ --interval=1s \ --timeout=1s \ From 1890fb1ea9101ea234e13de6dc43e37507081e79 Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Mon, 5 Jun 2023 12:10:24 -0400 Subject: [PATCH 178/228] xds: Add extension factory registration for EDS (#27793) Signed-off-by: Ali Beyad --- source/extensions/clusters/eds/BUILD | 1 + source/extensions/clusters/eds/eds.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/source/extensions/clusters/eds/BUILD b/source/extensions/clusters/eds/BUILD index cbdbbd402395..b7b2984fb8ec 100644 --- a/source/extensions/clusters/eds/BUILD +++ b/source/extensions/clusters/eds/BUILD @@ -20,6 +20,7 @@ envoy_cc_extension( "//envoy/config:subscription_factory_interface", "//envoy/config:subscription_interface", "//envoy/local_info:local_info_interface", + "//envoy/registry", "//envoy/secret:secret_manager_interface", "//envoy/upstream:cluster_factory_interface", "//envoy/upstream:locality_lib", diff --git a/source/extensions/clusters/eds/eds.h b/source/extensions/clusters/eds/eds.h index 7513f2f18e01..b362cd07325e 100644 --- a/source/extensions/clusters/eds/eds.h +++ b/source/extensions/clusters/eds/eds.h @@ -10,6 +10,7 @@ #include "envoy/config/subscription.h" #include "envoy/config/subscription_factory.h" #include "envoy/local_info/local_info.h" +#include "envoy/registry/registry.h" #include "envoy/secret/secret_manager.h" #include "envoy/service/discovery/v3/discovery.pb.h" #include "envoy/stats/scope.h" @@ -118,5 +119,7 @@ class EdsClusterFactory : public ClusterFactoryImplBase { ClusterFactoryContext& context) override; }; +DECLARE_FACTORY(EdsClusterFactory); + } // namespace Upstream } // namespace Envoy From a9ec898d6dfdb4875a5b3684a6ee84afd4bb9663 Mon Sep 17 00:00:00 2001 From: ohadvano <49730675+ohadvano@users.noreply.github.com> Date: Mon, 5 Jun 2023 21:23:10 +0300 Subject: [PATCH 179/228] application_logs: add bootstrap option to write logs in JSON format (#27278) Commit Message: application_logs: add bootstrap option to write logs in JSON format Additional Description: Adds an option in bootstrap config to write application logs in JSON format, while supporting all the log-format flags as defined in the CLI --log-format option. Related to #25959 - this is the first step in the implementation for supporting custom JSON properties, while printing the application logs output in JSON format. Risk Level: Low (all new code paths are only enabled by config option) Testing: Unit tests Docs Changes: API, Application logs docs Release Notes: None Platform Specific Features: None Signed-off-by: ohadvano Signed-off-by: ohadvano <49730675+ohadvano@users.noreply.github.com> --- api/envoy/config/bootstrap/v3/bootstrap.proto | 23 ++- changelogs/current.yaml | 5 + .../observability/application_logging.rst | 22 +++ envoy/server/options.h | 5 + .../integration/client_integration_test.cc | 2 +- source/common/common/BUILD | 1 + source/common/common/logger.cc | 25 ++++ source/common/common/logger.h | 6 + source/server/BUILD | 2 + source/server/config_validation/BUILD | 1 + source/server/config_validation/server.cc | 6 + source/server/options_impl.cc | 1 + source/server/options_impl.h | 7 +- source/server/server.cc | 5 + source/server/utils.cc | 24 ++++ source/server/utils.h | 9 ++ test/common/common/logger_test.cc | 136 ++++++++++++++++-- test/mocks/common.h | 12 ++ test/mocks/server/options.h | 1 + test/server/BUILD | 1 + test/server/config_validation/server_test.cc | 130 ++++++++++++++++- .../test_data/json_application_logs.yaml | 11 ++ ...json_application_logs_forbidden_flag_.yaml | 11 ++ ...json_application_logs_forbidden_flagv.yaml | 11 ++ test/server/options_impl_test.cc | 5 + test/server/server_test.cc | 36 +++++ .../server/json_application_log.yaml | 11 ++ .../json_application_log_forbidden_flag_.yaml | 11 ++ .../json_application_log_forbidden_flagv.yaml | 11 ++ test/server/utils_test.cc | 73 ++++++++++ tools/code_format/config.yaml | 1 + 31 files changed, 585 insertions(+), 20 deletions(-) create mode 100644 test/server/config_validation/test_data/json_application_logs.yaml create mode 100644 test/server/config_validation/test_data/json_application_logs_forbidden_flag_.yaml create mode 100644 test/server/config_validation/test_data/json_application_logs_forbidden_flagv.yaml create mode 100644 test/server/test_data/server/json_application_log.yaml create mode 100644 test/server/test_data/server/json_application_log_forbidden_flag_.yaml create mode 100644 test/server/test_data/server/json_application_log_forbidden_flagv.yaml diff --git a/api/envoy/config/bootstrap/v3/bootstrap.proto b/api/envoy/config/bootstrap/v3/bootstrap.proto index 6b230536cd86..f171068aaeed 100644 --- a/api/envoy/config/bootstrap/v3/bootstrap.proto +++ b/api/envoy/config/bootstrap/v3/bootstrap.proto @@ -41,7 +41,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // ` for more detail. // Bootstrap :ref:`configuration overview `. -// [#next-free-field: 38] +// [#next-free-field: 39] message Bootstrap { option (udpa.annotations.versioning).previous_message_type = "envoy.config.bootstrap.v2.Bootstrap"; @@ -101,6 +101,24 @@ message Bootstrap { core.v3.ApiConfigSource ads_config = 3; } + message ApplicationLogConfig { + message LogFormat { + oneof log_format { + option (validate.required) = true; + + // Flush application logs in JSON format. The configured JSON struct can + // support all the format flags specified in the :option:`--log-format` + // command line options section, except for the ``%v`` and ``%_`` flags. + google.protobuf.Struct json_format = 1; + } + } + + // Optional field to set the application logs format. If this field is set, it will override + // the default log format. Setting both this field and :option:`--log-format` command line + // option is not allowed, and will cause a bootstrap error. + LogFormat log_format = 1; + } + reserved 10, 11; reserved "runtime"; @@ -360,6 +378,9 @@ message Bootstrap { // Envoy only supports ListenerManager for this field and Envoy Mobile // supports ApiListenerManager. core.v3.TypedExtensionConfig listener_manager = 37; + + // Optional application log configuration. + ApplicationLogConfig application_log_config = 38; } // Administration interface :ref:`operations documentation diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 932d78b1e19f..123aa4ab1f55 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -287,6 +287,11 @@ new_features: change: | added new field ``envoy.extensions.filters.http.fault.v3.HTTPFault.filter_metadata`` to aid in logging. Metadata will be stored in StreamInfo dynamic metadata under a namespace corresponding to the name of the fault filter. +- area: application_logs + change: | + Added bootstrap option + :ref:`application_log_format ` + to enable setting application log format as JSON structure. - area: ext_proc change: | added new field ``filter_metadata `: * The ``--log-level`` flag can be set to control the log severity logged to Stackdriver. `Reference documentation `_ for Stackdriver on GKE. + +Printing logs in JSON format +---------------------------- + +It is possible to use the bootstrap config :ref:`json_format ` +to print the logs in custom JSON format. The json format struct can support all the format flags that are specified in :ref:`command line options `, +except for the ``%v`` and ``%_`` flags, as they may break the JSON structure log. Instead, use the ``%j`` flag. Example: + +.. code-block:: yaml + + application_log_config: + log_format: + json_format: + Timestamp: "%Y-%m-%dT%T.%F" + ThreadId: "%t" + SourceLine: "%s:%#" + Level: "%l" + Message: "%j" + FixedValue: "SomeFixedValue" + +.. note:: + Setting both ``application_log_config.log_format`` and CLI option ``--log-format`` is not allowed, and will cause a bootstrap error. diff --git a/envoy/server/options.h b/envoy/server/options.h index ab90efdd1f0e..327da389107a 100644 --- a/envoy/server/options.h +++ b/envoy/server/options.h @@ -169,6 +169,11 @@ class Options { */ virtual const std::string& logFormat() const PURE; + /** + * @return whether or not a log format was set by CLI option. + */ + virtual bool logFormatSet() const PURE; + /** * @return const bool indicating whether to escape c-style escape sequences in logs. */ diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index ac06e467d150..13b2e3997e89 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -97,7 +97,7 @@ void ClientIntegrationTest::trickleTest() { stream_prototype_->setOnData([this](envoy_data c_data, bool) { if (explicit_flow_control_) { - // Allow reading up to 100 bytes + // Allow reading up to 100 bytes. stream_->readData(100); } cc_.on_data_calls++; diff --git a/source/common/common/BUILD b/source/common/common/BUILD index 2f45fc1c671c..7c00df446757 100644 --- a/source/common/common/BUILD +++ b/source/common/common/BUILD @@ -211,6 +211,7 @@ envoy_cc_library( ":lock_guard_lib", ":macros", ":non_copyable", + "//source/common/protobuf:protobuf", ] + select({ "//bazel:android_logger": ["logger_impl_lib_android"], "//conditions:default": ["logger_impl_lib_standard"], diff --git a/source/common/common/logger.cc b/source/common/common/logger.cc index 9b02e6749660..476f2e06a9f9 100644 --- a/source/common/common/logger.cc +++ b/source/common/common/logger.cc @@ -254,6 +254,31 @@ void Registry::setLogFormat(const std::string& log_format) { } } +absl::Status Registry::setJsonLogFormat(const Protobuf::Message& log_format_struct) { + Protobuf::util::JsonPrintOptions json_options; + json_options.preserve_proto_field_names = true; + json_options.always_print_primitive_fields = true; + + std::string format_as_json; + const auto status = + Protobuf::util::MessageToJsonString(log_format_struct, &format_as_json, json_options); + + if (!status.ok()) { + return absl::InvalidArgumentError("Provided struct cannot be serialized as JSON string"); + } + + if (format_as_json.find("%v") != std::string::npos) { + return absl::InvalidArgumentError("Usage of %v is unavailable for JSON log formats"); + } + + if (format_as_json.find("%_") != std::string::npos) { + return absl::InvalidArgumentError("Usage of %_ is unavailable for JSON log formats"); + } + + setLogFormat(format_as_json); + return absl::OkStatus(); +} + Logger* Registry::logger(const std::string& log_name) { Logger* logger_to_return = nullptr; for (Logger& logger : loggers()) { diff --git a/source/common/common/logger.h b/source/common/common/logger.h index 7d7b86f29f2c..28aecaf86640 100644 --- a/source/common/common/logger.h +++ b/source/common/common/logger.h @@ -15,6 +15,7 @@ #include "source/common/common/logger_impl.h" #include "source/common/common/macros.h" #include "source/common/common/non_copyable.h" +#include "source/common/protobuf/protobuf.h" #include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" @@ -353,6 +354,11 @@ class Registry { */ static void setLogFormat(const std::string& log_format); + /** + * Sets the log format from a struct as a JSON string. + */ + static absl::Status setJsonLogFormat(const Protobuf::Message& log_format_struct); + /** * @return std::vector& the installed loggers. */ diff --git a/source/server/BUILD b/source/server/BUILD index a5709a05c6e1..fc81eafc00f3 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -513,7 +513,9 @@ envoy_cc_library( hdrs = ["utils.h"], deps = [ "//envoy/init:manager_interface", + "//envoy/server:options_interface", "//source/common/common:assert_lib", "@envoy_api//envoy/admin/v3:pkg_cc_proto", + "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", ], ) diff --git a/source/server/config_validation/BUILD b/source/server/config_validation/BUILD index 5d79fefce13a..f5e8bd30b1d9 100644 --- a/source/server/config_validation/BUILD +++ b/source/server/config_validation/BUILD @@ -101,6 +101,7 @@ envoy_cc_library( "//source/common/version:version_lib", "//source/server:configuration_lib", "//source/server:server_lib", + "//source/server:utils_lib", "//source/server/admin:admin_lib", "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index c836e4cd1d1a..dc80c3e7145b 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -15,6 +15,7 @@ #include "source/server/listener_manager_factory.h" #include "source/server/regex_engine.h" #include "source/server/ssl_context_manager.h" +#include "source/server/utils.h" namespace Envoy { namespace Server { @@ -85,6 +86,11 @@ void ValidationInstance::initialize(const Options& options, InstanceUtil::loadBootstrapConfig(bootstrap_, options, messageValidationContext().staticValidationVisitor(), *api_); + if (bootstrap_.has_application_log_config()) { + Utility::assertExclusiveLogFormatMethod(options_, bootstrap_.application_log_config()); + Utility::maybeSetApplicationLogFormat(bootstrap_.application_log_config()); + } + // Inject regex engine to singleton. Regex::EnginePtr regex_engine = createRegexEngine( bootstrap_, messageValidationContext().staticValidationVisitor(), serverFactoryContext()); diff --git a/source/server/options_impl.cc b/source/server/options_impl.cc index eae78c65d513..6345c789e897 100644 --- a/source/server/options_impl.cc +++ b/source/server/options_impl.cc @@ -194,6 +194,7 @@ OptionsImpl::OptionsImpl(std::vector args, } log_format_ = log_format.getValue(); + log_format_set_ = log_format.isSet(); log_format_escaped_ = log_format_escaped.getValue(); enable_fine_grain_logging_ = enable_fine_grain_logging.getValue(); diff --git a/source/server/options_impl.h b/source/server/options_impl.h index 6528e0aeb8a1..d02f37dce5bc 100644 --- a/source/server/options_impl.h +++ b/source/server/options_impl.h @@ -78,7 +78,10 @@ class OptionsImpl : public Server::Options, protected Logger::Loggable> component_log_levels_; std::string component_log_level_str_; std::string log_format_{Logger::Logger::DEFAULT_LOG_FORMAT}; + bool log_format_set_{false}; bool log_format_escaped_{false}; std::string log_path_; uint64_t restart_epoch_{0}; diff --git a/source/server/server.cc b/source/server/server.cc index f5c2b062ea8b..8ed78eb8b139 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -422,6 +422,11 @@ void InstanceImpl::initialize(Network::Address::InstanceConstSharedPtr local_add messageValidationContext().staticValidationVisitor(), *api_); bootstrap_config_update_time_ = time_source_.systemTime(); + if (bootstrap_.has_application_log_config()) { + Utility::assertExclusiveLogFormatMethod(options_, bootstrap_.application_log_config()); + Utility::maybeSetApplicationLogFormat(bootstrap_.application_log_config()); + } + #ifdef ENVOY_PERFETTO perfetto::TracingInitArgs args; // Include in-process events only. diff --git a/source/server/utils.cc b/source/server/utils.cc index fcb5e043ec99..7bb8957a59c6 100644 --- a/source/server/utils.cc +++ b/source/server/utils.cc @@ -1,5 +1,7 @@ #include "source/server/utils.h" +#include "envoy/common/exception.h" + #include "source/common/common/assert.h" namespace Envoy { @@ -21,6 +23,28 @@ envoy::admin::v3::ServerInfo::State serverState(Init::Manager::State state, return envoy::admin::v3::ServerInfo::PRE_INITIALIZING; } +void assertExclusiveLogFormatMethod( + const Options& options, + const envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig& application_log_config) { + if (options.logFormatSet() && application_log_config.has_log_format()) { + throw EnvoyException( + "Only one of ApplicationLogConfig.log_format or CLI option --log-format can be specified."); + } +} + +void maybeSetApplicationLogFormat( + const envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig& application_log_config) { + if (application_log_config.has_log_format() && + application_log_config.log_format().has_json_format()) { + const auto status = + Logger::Registry::setJsonLogFormat(application_log_config.log_format().json_format()); + + if (!status.ok()) { + throw EnvoyException(fmt::format("setJsonLogFormat error: {}", status.ToString())); + } + } +} + } // namespace Utility } // namespace Server } // namespace Envoy diff --git a/source/server/utils.h b/source/server/utils.h index 1ab4b51de275..2d3b981c2c87 100644 --- a/source/server/utils.h +++ b/source/server/utils.h @@ -1,7 +1,9 @@ #pragma once #include "envoy/admin/v3/server_info.pb.h" +#include "envoy/config/bootstrap/v3/bootstrap.pb.h" #include "envoy/init/manager.h" +#include "envoy/server/options.h" namespace Envoy { namespace Server { @@ -14,6 +16,13 @@ namespace Utility { envoy::admin::v3::ServerInfo::State serverState(Init::Manager::State state, bool health_check_failed); +void assertExclusiveLogFormatMethod( + const Options& options, + const envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig& application_log_config); + +void maybeSetApplicationLogFormat( + const envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig& application_log_config); + } // namespace Utility } // namespace Server } // namespace Envoy diff --git a/test/common/common/logger_test.cc b/test/common/common/logger_test.cc index b026eddc6419..e9998db311e3 100644 --- a/test/common/common/logger_test.cc +++ b/test/common/common/logger_test.cc @@ -4,6 +4,7 @@ #include "source/common/common/json_escape_string.h" #include "source/common/common/logger.h" +#include "test/mocks/common.h" #include "test/test_common/environment.h" #include "gmock/gmock.h" @@ -176,17 +177,6 @@ TEST_P(LoggerCustomFlagsTest, LogMessageAsJsonStringEscaped) { "StreamAggregatedResources gRPC config stream closed: 14, connection error: desc = " "\\\"transport: Error while dialing dial tcp [::1]:15012: connect: connection refused\\\""); } - -struct MockLogSink : SinkDelegate { - MockLogSink(DelegatingLogSinkSharedPtr log_sink) : SinkDelegate(log_sink) { setDelegate(); } - ~MockLogSink() override { restoreDelegate(); } - - MOCK_METHOD(void, log, (absl::string_view, const spdlog::details::log_msg&)); - MOCK_METHOD(void, logWithStableName, - (absl::string_view, absl::string_view, absl::string_view, absl::string_view)); - void flush() override {} -}; - class NamedLogTest : public Loggable, public testing::Test {}; TEST_F(NamedLogTest, NamedLogsAreSentToSink) { @@ -270,6 +260,130 @@ TEST(LoggerTest, LogWithLogDetails) { ENVOY_LOG_MISC(info, "hello"); } +TEST(LoggerTest, TestJsonFormatError) { + ProtobufWkt::Any log_struct; + log_struct.set_type_url("type.googleapis.com/bad.type.url"); + log_struct.set_value("asdf"); + + // This scenario shouldn't happen in production, the test is added mainly for coverage. + auto status = Envoy::Logger::Registry::setJsonLogFormat(log_struct); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("INVALID_ARGUMENT: Provided struct cannot be serialized as JSON string", + status.ToString()); +} + +TEST(LoggerTest, TestJsonFormatNonEscapedThrows) { + Envoy::Logger::Registry::setLogLevel(spdlog::level::info); + + { + ProtobufWkt::Struct log_struct; + (*log_struct.mutable_fields())["Message"].set_string_value("%v"); + (*log_struct.mutable_fields())["NullField"].set_null_value(ProtobufWkt::NULL_VALUE); + + auto status = Envoy::Logger::Registry::setJsonLogFormat(log_struct); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("INVALID_ARGUMENT: Usage of %v is unavailable for JSON log formats", + status.ToString()); + } + + { + ProtobufWkt::Struct log_struct; + (*log_struct.mutable_fields())["Message"].set_string_value("%_"); + (*log_struct.mutable_fields())["NullField"].set_null_value(ProtobufWkt::NULL_VALUE); + + auto status = Envoy::Logger::Registry::setJsonLogFormat(log_struct); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("INVALID_ARGUMENT: Usage of %_ is unavailable for JSON log formats", + status.ToString()); + } +} + +TEST(LoggerTest, TestJsonFormatEmptyStruct) { + ProtobufWkt::Struct log_struct; + Envoy::Logger::Registry::setLogLevel(spdlog::level::info); + EXPECT_TRUE(Envoy::Logger::Registry::setJsonLogFormat(log_struct).ok()); + + MockLogSink sink(Envoy::Logger::Registry::getSink()); + EXPECT_CALL(sink, log(_, _)).WillOnce(Invoke([](auto msg, auto& log) { + EXPECT_THAT(msg, HasSubstr("{}")); + EXPECT_EQ(log.logger_name, "misc"); + })); + + ENVOY_LOG_MISC(info, "hello"); +} + +TEST(LoggerTest, TestJsonFormatNullAndFixedField) { + ProtobufWkt::Struct log_struct; + (*log_struct.mutable_fields())["Message"].set_string_value("%j"); + (*log_struct.mutable_fields())["FixedValue"].set_string_value("Fixed"); + (*log_struct.mutable_fields())["NullField"].set_null_value(ProtobufWkt::NULL_VALUE); + Envoy::Logger::Registry::setLogLevel(spdlog::level::info); + EXPECT_TRUE(Envoy::Logger::Registry::setJsonLogFormat(log_struct).ok()); + + MockLogSink sink(Envoy::Logger::Registry::getSink()); + EXPECT_CALL(sink, log(_, _)).WillOnce(Invoke([](auto msg, auto&) { + EXPECT_NO_THROW(Json::Factory::loadFromString(std::string(msg))); + EXPECT_THAT(msg, HasSubstr("\"Message\":\"hello\"")); + EXPECT_THAT(msg, HasSubstr("\"FixedValue\":\"Fixed\"")); + EXPECT_THAT(msg, HasSubstr("\"NullField\":null")); + })); + + ENVOY_LOG_MISC(info, "hello"); +} + +TEST(LoggerTest, TestJsonFormat) { + ProtobufWkt::Struct log_struct; + (*log_struct.mutable_fields())["Level"].set_string_value("%l"); + (*log_struct.mutable_fields())["Message"].set_string_value("%j"); + Envoy::Logger::Registry::setLogLevel(spdlog::level::info); + EXPECT_TRUE(Envoy::Logger::Registry::setJsonLogFormat(log_struct).ok()); + + MockLogSink sink(Envoy::Logger::Registry::getSink()); + EXPECT_CALL(sink, log(_, _)) + .WillOnce(Invoke([](auto msg, auto& log) { + EXPECT_NO_THROW(Json::Factory::loadFromString(std::string(msg))); + EXPECT_THAT(msg, HasSubstr("\"Level\":\"info\"")); + EXPECT_THAT(msg, HasSubstr("\"Message\":\"hello\"")); + EXPECT_EQ(log.logger_name, "misc"); + })) + .WillOnce(Invoke([](auto msg, auto& log) { + EXPECT_NO_THROW(Json::Factory::loadFromString(std::string(msg))); + EXPECT_THAT(msg, HasSubstr("\"Level\":\"info\"")); + EXPECT_THAT(msg, HasSubstr("\"Message\":\"hel\\nlo\"")); + EXPECT_EQ(log.logger_name, "misc"); + })) + .WillOnce(Invoke([](auto msg, auto& log) { + EXPECT_NO_THROW(Json::Factory::loadFromString(std::string(msg))); + EXPECT_THAT(msg, HasSubstr("\"Level\":\"info\"")); + EXPECT_THAT(msg, HasSubstr("\"Message\":\"hel\\\"lo\"")); + EXPECT_EQ(log.logger_name, "misc"); + })); + + ENVOY_LOG_MISC(info, "hello"); + ENVOY_LOG_MISC(info, "hel\nlo"); + ENVOY_LOG_MISC(info, "hel\"lo"); +} + +TEST(LoggerTest, TestJsonFormatWithNestedJsonMessage) { + ProtobufWkt::Struct log_struct; + (*log_struct.mutable_fields())["Level"].set_string_value("%l"); + (*log_struct.mutable_fields())["Message"].set_string_value("%j"); + (*log_struct.mutable_fields())["FixedValue"].set_string_value("Fixed"); + Envoy::Logger::Registry::setLogLevel(spdlog::level::info); + EXPECT_TRUE(Envoy::Logger::Registry::setJsonLogFormat(log_struct).ok()); + + MockLogSink sink(Envoy::Logger::Registry::getSink()); + EXPECT_CALL(sink, log(_, _)).WillOnce(Invoke([](auto msg, auto& log) { + EXPECT_NO_THROW(Json::Factory::loadFromString(std::string(msg))); + EXPECT_THAT(msg, HasSubstr("\"Level\":\"info\"")); + EXPECT_THAT(msg, HasSubstr("\"Message\":\"{\\\"nested_message\\\":\\\"hello\\\"}\"")); + EXPECT_THAT(msg, HasSubstr("\"FixedValue\":\"Fixed\"")); + EXPECT_EQ(log.logger_name, "misc"); + })); + + ENVOY_LOG_MISC(info, "{\"nested_message\":\"hello\"}"); +} + } // namespace } // namespace Logger } // namespace Envoy diff --git a/test/mocks/common.h b/test/mocks/common.h index 058a7736af69..1e496030e4f9 100644 --- a/test/mocks/common.h +++ b/test/mocks/common.h @@ -143,4 +143,16 @@ class MockKeyValueStoreFactory : public KeyValueStoreFactory { std::string name() const override { return "mock_key_value_store_factory"; } }; +struct MockLogSink : Logger::SinkDelegate { + MockLogSink(Logger::DelegatingLogSinkSharedPtr log_sink) : Logger::SinkDelegate(log_sink) { + setDelegate(); + } + ~MockLogSink() override { restoreDelegate(); } + + MOCK_METHOD(void, log, (absl::string_view, const spdlog::details::log_msg&)); + MOCK_METHOD(void, logWithStableName, + (absl::string_view, absl::string_view, absl::string_view, absl::string_view)); + void flush() override {} +}; + } // namespace Envoy diff --git a/test/mocks/server/options.h b/test/mocks/server/options.h index fb64f4f1b664..0a0f7433124c 100644 --- a/test/mocks/server/options.h +++ b/test/mocks/server/options.h @@ -34,6 +34,7 @@ class MockOptions : public Options { MOCK_METHOD((const std::vector>&), componentLogLevels, (), (const)); MOCK_METHOD(const std::string&, logFormat, (), (const)); + MOCK_METHOD(bool, logFormatSet, (), (const)); MOCK_METHOD(bool, logFormatEscaped, (), (const)); MOCK_METHOD(bool, enableFineGrainLogging, (), (const)); MOCK_METHOD(const std::string&, logPath, (), (const)); diff --git a/test/server/BUILD b/test/server/BUILD index 74ae0259db08..e2c210dc293e 100644 --- a/test/server/BUILD +++ b/test/server/BUILD @@ -397,5 +397,6 @@ envoy_cc_test( srcs = envoy_select_admin_functionality(["utils_test.cc"]), deps = [ "//source/server:utils_lib", + "//test/mocks/server:options_mocks", ], ) diff --git a/test/server/config_validation/server_test.cc b/test/server/config_validation/server_test.cc index d52e83202b07..cda36802a3dd 100644 --- a/test/server/config_validation/server_test.cc +++ b/test/server/config_validation/server_test.cc @@ -6,6 +6,7 @@ #include "source/server/config_validation/server.h" #include "test/integration/server.h" +#include "test/mocks/common.h" #include "test/mocks/network/mocks.h" #include "test/mocks/server/options.h" #include "test/mocks/stats/mocks.h" @@ -14,6 +15,9 @@ #include "test/test_common/registry.h" #include "test/test_common/test_time.h" +using testing::HasSubstr; +using testing::Return; + namespace Envoy { namespace Server { namespace { @@ -73,14 +77,54 @@ class RuntimeFeatureValidationServerTest : public ValidationServerTest { static const std::vector getAllConfigFiles() { setupTestDirectory(); + return {"runtime_config.yaml"}; + } +}; - auto files = TestUtility::listFiles(ValidationServerTest::directory_, false); +class JsonApplicationLogsValidationServerTest : public ValidationServerTest { +public: + static void SetUpTestSuite() { // NOLINT(readability-identifier-naming) + setupTestDirectory(); + } - // Strip directory part. options_ adds it for each test. - for (auto& file : files) { - file = file.substr(directory_.length() + 1); - } - return files; + static void setupTestDirectory() { + directory_ = + TestEnvironment::runfilesDirectory("envoy/test/server/config_validation/test_data/"); + } + + static const std::vector getAllConfigFiles() { + setupTestDirectory(); + return {"json_application_logs.yaml"}; + } +}; + +class JsonApplicationLogsValidationServerForbiddenFlagvTest : public ValidationServerTest { +public: + static void SetUpTestSuite() { // NOLINT(readability-identifier-naming) + setupTestDirectory(); + } + static void setupTestDirectory() { + directory_ = + TestEnvironment::runfilesDirectory("envoy/test/server/config_validation/test_data/"); + } + static const std::vector getAllConfigFiles() { + setupTestDirectory(); + return {"json_application_logs_forbidden_flagv.yaml"}; + } +}; + +class JsonApplicationLogsValidationServerForbiddenFlag_Test : public ValidationServerTest { +public: + static void SetUpTestSuite() { // NOLINT(readability-identifier-naming) + setupTestDirectory(); + } + static void setupTestDirectory() { + directory_ = + TestEnvironment::runfilesDirectory("envoy/test/server/config_validation/test_data/"); + } + static const std::vector getAllConfigFiles() { + setupTestDirectory(); + return {"json_application_logs_forbidden_flag_.yaml"}; } }; @@ -206,6 +250,80 @@ INSTANTIATE_TEST_SUITE_P( AllConfigs, RuntimeFeatureValidationServerTest, ::testing::ValuesIn(RuntimeFeatureValidationServerTest::getAllConfigFiles())); +TEST_P(JsonApplicationLogsValidationServerTest, BootstrapApplicationLogsAndCLIThrows) { + Thread::MutexBasicLockable access_log_lock; + Stats::IsolatedStoreImpl stats_store; + DangerousDeprecatedTestTime time_system; + EXPECT_CALL(options_, logFormatSet()).WillRepeatedly(Return(true)); + EXPECT_THROW_WITH_MESSAGE( + ValidationInstance server(options_, time_system.timeSystem(), + Network::Address::InstanceConstSharedPtr(), stats_store, + access_log_lock, component_factory_, Thread::threadFactoryForTest(), + Filesystem::fileSystemForTest()), + EnvoyException, + "Only one of ApplicationLogConfig.log_format or CLI option --log-format can be specified."); +} + +TEST_P(JsonApplicationLogsValidationServerTest, JsonApplicationLogs) { + Thread::MutexBasicLockable access_log_lock; + Stats::IsolatedStoreImpl stats_store; + DangerousDeprecatedTestTime time_system; + ValidationInstance server(options_, time_system.timeSystem(), + Network::Address::InstanceConstSharedPtr(), stats_store, + access_log_lock, component_factory_, Thread::threadFactoryForTest(), + Filesystem::fileSystemForTest()); + + Envoy::Logger::Registry::setLogLevel(spdlog::level::info); + MockLogSink sink(Envoy::Logger::Registry::getSink()); + EXPECT_CALL(sink, log(_, _)).WillOnce(Invoke([](auto msg, auto& log) { + EXPECT_THAT(msg, HasSubstr("{\"MessageFromProto\":\"hello\"}")); + EXPECT_EQ(log.logger_name, "misc"); + })); + + ENVOY_LOG_MISC(info, "hello"); + server.shutdown(); +} + +INSTANTIATE_TEST_SUITE_P( + AllConfigs, JsonApplicationLogsValidationServerTest, + ::testing::ValuesIn(JsonApplicationLogsValidationServerTest::getAllConfigFiles())); + +TEST_P(JsonApplicationLogsValidationServerForbiddenFlagvTest, TestForbiddenFlag) { + Thread::MutexBasicLockable access_log_lock; + Stats::IsolatedStoreImpl stats_store; + DangerousDeprecatedTestTime time_system; + EXPECT_THROW_WITH_MESSAGE( + ValidationInstance server(options_, time_system.timeSystem(), + Network::Address::InstanceConstSharedPtr(), stats_store, + access_log_lock, component_factory_, Thread::threadFactoryForTest(), + Filesystem::fileSystemForTest()), + EnvoyException, + "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %v is unavailable for JSON log formats"); +} + +INSTANTIATE_TEST_SUITE_P( + AllConfigs, JsonApplicationLogsValidationServerForbiddenFlagvTest, + ::testing::ValuesIn( + JsonApplicationLogsValidationServerForbiddenFlagvTest::getAllConfigFiles())); + +TEST_P(JsonApplicationLogsValidationServerForbiddenFlag_Test, TestForbiddenFlag) { + Thread::MutexBasicLockable access_log_lock; + Stats::IsolatedStoreImpl stats_store; + DangerousDeprecatedTestTime time_system; + EXPECT_THROW_WITH_MESSAGE( + ValidationInstance server(options_, time_system.timeSystem(), + Network::Address::InstanceConstSharedPtr(), stats_store, + access_log_lock, component_factory_, Thread::threadFactoryForTest(), + Filesystem::fileSystemForTest()), + EnvoyException, + "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %_ is unavailable for JSON log formats"); +} + +INSTANTIATE_TEST_SUITE_P( + AllConfigs, JsonApplicationLogsValidationServerForbiddenFlag_Test, + ::testing::ValuesIn( + JsonApplicationLogsValidationServerForbiddenFlag_Test::getAllConfigFiles())); + } // namespace } // namespace Server } // namespace Envoy diff --git a/test/server/config_validation/test_data/json_application_logs.yaml b/test/server/config_validation/test_data/json_application_logs.yaml new file mode 100644 index 000000000000..2510444d9840 --- /dev/null +++ b/test/server/config_validation/test_data/json_application_logs.yaml @@ -0,0 +1,11 @@ +--- +application_log_config: + log_format: + json_format: + MessageFromProto: "%j" + +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9000 diff --git a/test/server/config_validation/test_data/json_application_logs_forbidden_flag_.yaml b/test/server/config_validation/test_data/json_application_logs_forbidden_flag_.yaml new file mode 100644 index 000000000000..3b3b8164adae --- /dev/null +++ b/test/server/config_validation/test_data/json_application_logs_forbidden_flag_.yaml @@ -0,0 +1,11 @@ +--- +application_log_config: + log_format: + json_format: + MessageFromProto: "%_" + +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9000 diff --git a/test/server/config_validation/test_data/json_application_logs_forbidden_flagv.yaml b/test/server/config_validation/test_data/json_application_logs_forbidden_flagv.yaml new file mode 100644 index 000000000000..16474cea24cd --- /dev/null +++ b/test/server/config_validation/test_data/json_application_logs_forbidden_flagv.yaml @@ -0,0 +1,11 @@ +--- +application_log_config: + log_format: + json_format: + MessageFromProto: "%v" + +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9000 diff --git a/test/server/options_impl_test.cc b/test/server/options_impl_test.cc index 79136c60e55e..b09db966bcc0 100644 --- a/test/server/options_impl_test.cc +++ b/test/server/options_impl_test.cc @@ -113,6 +113,7 @@ TEST_F(OptionsImplTest, All) { EXPECT_EQ(spdlog::level::info, options->logLevel()); EXPECT_EQ(2, options->componentLogLevels().size()); EXPECT_EQ("[%v]", options->logFormat()); + EXPECT_TRUE(options->logFormatSet()); EXPECT_EQ("/foo/bar", options->logPath()); EXPECT_EQ(true, options->enableFineGrainLogging()); EXPECT_EQ("cluster", options->serviceClusterName()); @@ -209,6 +210,7 @@ TEST_F(OptionsImplTest, SetAll) { EXPECT_EQ(Server::DrainStrategy::Immediate, options->drainStrategy()); EXPECT_EQ(spdlog::level::trace, options->logLevel()); EXPECT_EQ("%L %n %v", options->logFormat()); + EXPECT_TRUE(options->logFormatSet()); EXPECT_EQ("/foo/bar", options->logPath()); EXPECT_EQ(std::chrono::seconds(43), options->parentShutdownTime()); EXPECT_EQ(44, options->restartEpoch()); @@ -528,18 +530,21 @@ TEST_F(OptionsImplTest, SetCpusetOnly) { TEST_F(OptionsImplTest, LogFormatDefault) { std::unique_ptr options = createOptionsImpl({"envoy", "-c", "hello"}); EXPECT_EQ(options->logFormat(), "[%Y-%m-%d %T.%e][%t][%l][%n] [%g:%#] %v"); + EXPECT_FALSE(options->logFormatSet()); } TEST_F(OptionsImplTest, LogFormatOverride) { std::unique_ptr options = createOptionsImpl({"envoy", "-c", "hello", "--log-format", "%%v %v %t %v"}); EXPECT_EQ(options->logFormat(), "%%v %v %t %v"); + EXPECT_TRUE(options->logFormatSet()); } TEST_F(OptionsImplTest, LogFormatOverrideNoPrefix) { std::unique_ptr options = createOptionsImpl({"envoy", "-c", "hello", "--log-format", "%%v %v %t %v"}); EXPECT_EQ(options->logFormat(), "%%v %v %t %v"); + EXPECT_TRUE(options->logFormatSet()); } // Test that --base-id and --restart-epoch with non-default values are accepted. diff --git a/test/server/server_test.cc b/test/server/server_test.cc index 59cbd75f3644..c47df5d57c57 100644 --- a/test/server/server_test.cc +++ b/test/server/server_test.cc @@ -20,6 +20,7 @@ #include "test/common/stats/stat_test_utility.h" #include "test/config/v2_link_hacks.h" #include "test/integration/server.h" +#include "test/mocks/common.h" #include "test/mocks/server/bootstrap_extension_factory.h" #include "test/mocks/server/fatal_action_factory.h" #include "test/mocks/server/hot_restart.h" @@ -1624,6 +1625,41 @@ TEST_P(ServerInstanceImplTest, AdminAccessLogFilter) { EXPECT_NO_THROW(initialize("test/server/test_data/server/access_log_filter_bootstrap.yaml")); } +TEST_P(ServerInstanceImplTest, BootstrapApplicationLogsAndCLIThrows) { + EXPECT_CALL(options_, logFormatSet()).WillRepeatedly(Return(true)); + EXPECT_THROW_WITH_MESSAGE( + initialize("test/server/test_data/server/json_application_log.yaml"), EnvoyException, + "Only one of ApplicationLogConfig.log_format or CLI option --log-format can be specified."); +} + +TEST_P(ServerInstanceImplTest, JsonApplicationLog) { + EXPECT_NO_THROW(initialize("test/server/test_data/server/json_application_log.yaml")); + + Envoy::Logger::Registry::setLogLevel(spdlog::level::info); + MockLogSink sink(Envoy::Logger::Registry::getSink()); + EXPECT_CALL(sink, log(_, _)).WillOnce(Invoke([](auto msg, auto& log) { + EXPECT_NO_THROW(Json::Factory::loadFromString(std::string(msg))); + EXPECT_THAT(msg, HasSubstr("{\"MessageFromProto\":\"hello\"}")); + EXPECT_EQ(log.logger_name, "misc"); + })); + + ENVOY_LOG_MISC(info, "hello"); +} + +TEST_P(ServerInstanceImplTest, JsonApplicationLogFailWithForbiddenFlagv) { + EXPECT_THROW_WITH_MESSAGE( + initialize("test/server/test_data/server/json_application_log_forbidden_flagv.yaml"), + EnvoyException, + "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %v is unavailable for JSON log formats"); +} + +TEST_P(ServerInstanceImplTest, JsonApplicationLogFailWithForbiddenFlag_) { + EXPECT_THROW_WITH_MESSAGE( + initialize("test/server/test_data/server/json_application_log_forbidden_flag_.yaml"), + EnvoyException, + "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %_ is unavailable for JSON log formats"); +} + } // namespace } // namespace Server } // namespace Envoy diff --git a/test/server/test_data/server/json_application_log.yaml b/test/server/test_data/server/json_application_log.yaml new file mode 100644 index 000000000000..2510444d9840 --- /dev/null +++ b/test/server/test_data/server/json_application_log.yaml @@ -0,0 +1,11 @@ +--- +application_log_config: + log_format: + json_format: + MessageFromProto: "%j" + +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9000 diff --git a/test/server/test_data/server/json_application_log_forbidden_flag_.yaml b/test/server/test_data/server/json_application_log_forbidden_flag_.yaml new file mode 100644 index 000000000000..3b3b8164adae --- /dev/null +++ b/test/server/test_data/server/json_application_log_forbidden_flag_.yaml @@ -0,0 +1,11 @@ +--- +application_log_config: + log_format: + json_format: + MessageFromProto: "%_" + +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9000 diff --git a/test/server/test_data/server/json_application_log_forbidden_flagv.yaml b/test/server/test_data/server/json_application_log_forbidden_flagv.yaml new file mode 100644 index 000000000000..16474cea24cd --- /dev/null +++ b/test/server/test_data/server/json_application_log_forbidden_flagv.yaml @@ -0,0 +1,11 @@ +--- +application_log_config: + log_format: + json_format: + MessageFromProto: "%v" + +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9000 diff --git a/test/server/utils_test.cc b/test/server/utils_test.cc index 1e2ae258f5a0..7576e41522c1 100644 --- a/test/server/utils_test.cc +++ b/test/server/utils_test.cc @@ -1,9 +1,12 @@ #include "source/server/utils.h" +#include "test/mocks/server/options.h" #include "test/test_common/utility.h" #include "gtest/gtest.h" +using testing::Return; + namespace Envoy { namespace Server { namespace Utility { @@ -15,6 +18,76 @@ TEST(UtilsTest, BadServerState) { EXPECT_ENVOY_BUG(Utility::serverState(static_cast(123), true), "unexpected server state"); } + +TEST(UtilsTest, AssertExclusiveLogFormatMethod) { + { + testing::NiceMock options; + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + EXPECT_NO_THROW(Utility::assertExclusiveLogFormatMethod(options, log_config)); + } + + { + testing::NiceMock options; + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + EXPECT_CALL(options, logFormatSet()).WillRepeatedly(Return(true)); + EXPECT_NO_THROW(Utility::assertExclusiveLogFormatMethod(options, log_config)); + } + + { + testing::NiceMock options; + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + log_config.mutable_log_format(); + EXPECT_NO_THROW(Utility::assertExclusiveLogFormatMethod(options, log_config)); + } + + { + testing::NiceMock options; + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + EXPECT_CALL(options, logFormatSet()).WillRepeatedly(Return(true)); + log_config.mutable_log_format(); + EXPECT_THROW_WITH_MESSAGE( + Utility::assertExclusiveLogFormatMethod(options, log_config), EnvoyException, + "Only one of ApplicationLogConfig.log_format or CLI option --log-format can be specified."); + } +} + +TEST(UtilsTest, MaybeSetApplicationLogFormat) { + { + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + EXPECT_NO_THROW(Utility::maybeSetApplicationLogFormat(log_config)); + } + + { + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + log_config.mutable_log_format(); + EXPECT_NO_THROW(Utility::maybeSetApplicationLogFormat(log_config)); + } + + { + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + log_config.mutable_log_format()->mutable_json_format(); + EXPECT_NO_THROW(Utility::maybeSetApplicationLogFormat(log_config)); + } + + { + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + auto* format = log_config.mutable_log_format()->mutable_json_format(); + format->mutable_fields()->operator[]("Message").set_string_value("%v"); + EXPECT_THROW_WITH_MESSAGE(Utility::maybeSetApplicationLogFormat(log_config), EnvoyException, + "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %v is " + "unavailable for JSON log formats"); + } + + { + envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config; + auto* format = log_config.mutable_log_format()->mutable_json_format(); + format->mutable_fields()->operator[]("Message").set_string_value("%_"); + EXPECT_THROW_WITH_MESSAGE(Utility::maybeSetApplicationLogFormat(log_config), EnvoyException, + "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %_ is " + "unavailable for JSON log formats"); + } +} + } // namespace Utility } // namespace Server } // namespace Envoy diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index fed59e924743..f9c7f231773c 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -208,6 +208,7 @@ paths: - source/server/config_validation/server.cc - source/server/admin/html/active_stats.js - source/server/server.cc + - source/server/utils.cc - source/server/configuration_impl.h - source/server/hot_restarting_base.cc - source/server/hot_restart_impl.cc From 068adb188b025c48442d440d7942828e258ed467 Mon Sep 17 00:00:00 2001 From: Paul Sohn Date: Mon, 5 Jun 2023 15:24:03 -0400 Subject: [PATCH 180/228] QUIC deferred logging: add retransmission rate (#27699) Commit Message: [QUIC only] Log retransmitted packets and bytes. Additional Description: Adds to the deferred logging implementation from #23648 and implements the existing OnPacketRetransmitted function. Risk Level: Low Testing: Integration test Docs Changes: N/A Release Notes: added Signed-off-by: Paul Sohn --- changelogs/current.yaml | 3 ++ .../observability/access_log/usage.rst | 24 +++++++++++++ envoy/stream_info/stream_info.h | 20 +++++++++++ .../formatter/substitution_formatter.cc | 16 +++++++++ source/common/quic/quic_stats_gatherer.cc | 7 ++++ source/common/quic/quic_stats_gatherer.h | 4 ++- source/common/stream_info/stream_info_impl.h | 16 +++++++++ .../formatter/substitution_formatter_test.cc | 24 +++++++++++++ .../stream_info/stream_info_impl_test.cc | 12 +++++-- test/integration/BUILD | 1 + .../integration/quic_http_integration_test.cc | 36 +++++++++++++++++++ test/mocks/stream_info/mocks.h | 4 +++ tools/spelling/spelling_dictionary.txt | 1 + 13 files changed, 165 insertions(+), 3 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 123aa4ab1f55..71e667638643 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -194,6 +194,9 @@ new_features: - area: access_log change: | added :ref:`CEL ` access log formatter to print CEL expression. +- area: access_log + change: | + (QUIC only) Added support for %BYTES_RETRANSMITTED% and %PACKETS_RETRANSMITTED%. - area: dynamic_forward_proxy change: | added :ref:`sub_clusters_config diff --git a/docs/root/configuration/observability/access_log/usage.rst b/docs/root/configuration/observability/access_log/usage.rst index 7b707de2bf53..344a36aa12dd 100644 --- a/docs/root/configuration/observability/access_log/usage.rst +++ b/docs/root/configuration/observability/access_log/usage.rst @@ -187,6 +187,30 @@ The following command operators are supported: Renders a numeric value in typed JSON logs. +%BYTES_RETRANSMITTED% + HTTP/3 (QUIC) + Body bytes retransmitted. + + HTTP/1 and HTTP/2 + Not implemented (0). + + TCP/UDP + Not implemented (0). + + Renders a numeric value in typed JSON logs. + +%PACKETS_RETRANSMITTED% + HTTP/3 (QUIC) + Number of packets retransmitted. + + HTTP/1 and HTTP/2 + Not implemented (0). + + TCP/UDP + Not implemented (0). + + Renders a numeric value in typed JSON logs. + %PROTOCOL% HTTP Protocol. Currently either *HTTP/1.1* *HTTP/2* or *HTTP/3*. diff --git a/envoy/stream_info/stream_info.h b/envoy/stream_info/stream_info.h index 0b31d8aaf2f3..d7176c3dcaec 100644 --- a/envoy/stream_info/stream_info.h +++ b/envoy/stream_info/stream_info.h @@ -580,6 +580,26 @@ class StreamInfo { */ virtual uint64_t bytesReceived() const PURE; + /** + * @param bytes_retransmitted denotes number of bytes to add to total retransmitted bytes. + */ + virtual void addBytesRetransmitted(uint64_t bytes_retransmitted) PURE; + + /** + * @return the number of bytes retransmitted by the stream. + */ + virtual uint64_t bytesRetransmitted() const PURE; + + /** + * @param packets_retransmitted denotes number of packets to add to total retransmitted packets. + */ + virtual void addPacketsRetransmitted(uint64_t packets_retransmitted) PURE; + + /** + * @return the number of packets retransmitted by the stream. + */ + virtual uint64_t packetsRetransmitted() const PURE; + /** * @return the protocol of the request. */ diff --git a/source/common/formatter/substitution_formatter.cc b/source/common/formatter/substitution_formatter.cc index bf97b1df017c..6d2d50cdf922 100644 --- a/source/common/formatter/substitution_formatter.cc +++ b/source/common/formatter/substitution_formatter.cc @@ -969,6 +969,22 @@ const StreamInfoFormatter::FieldExtractorLookupTbl& StreamInfoFormatter::getKnow return stream_info.bytesReceived(); }); }}}, + {"BYTES_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, const absl::optional&) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.bytesRetransmitted(); + }); + }}}, + {"PACKETS_RETRANSMITTED", + {CommandSyntaxChecker::COMMAND_ONLY, + [](const std::string&, const absl::optional&) { + return std::make_unique( + [](const StreamInfo::StreamInfo& stream_info) { + return stream_info.packetsRetransmitted(); + }); + }}}, {"UPSTREAM_WIRE_BYTES_RECEIVED", {CommandSyntaxChecker::COMMAND_ONLY, [](const std::string&, const absl::optional&) { diff --git a/source/common/quic/quic_stats_gatherer.cc b/source/common/quic/quic_stats_gatherer.cc index e632062c5c70..d7acb9ffc0e6 100644 --- a/source/common/quic/quic_stats_gatherer.cc +++ b/source/common/quic/quic_stats_gatherer.cc @@ -13,6 +13,11 @@ void QuicStatsGatherer::OnPacketAcked(int acked_bytes, } } +void QuicStatsGatherer::OnPacketRetransmitted(int retransmitted_bytes) { + retransmitted_packets_++; + retransmitted_bytes_ += retransmitted_bytes; +} + void QuicStatsGatherer::maybeDoDeferredLog(bool record_ack_timing) { logging_done_ = true; if (stream_info_ == nullptr) { @@ -21,6 +26,8 @@ void QuicStatsGatherer::maybeDoDeferredLog(bool record_ack_timing) { if (time_source_ != nullptr && record_ack_timing) { stream_info_->downstreamTiming().onLastDownstreamAckReceived(*time_source_); } + stream_info_->addBytesRetransmitted(retransmitted_bytes_); + stream_info_->addPacketsRetransmitted(retransmitted_packets_); const Http::RequestHeaderMap* request_headers = request_header_map_.get(); const Http::ResponseHeaderMap* response_headers = response_header_map_.get(); const Http::ResponseTrailerMap* response_trailers = response_trailer_map_.get(); diff --git a/source/common/quic/quic_stats_gatherer.h b/source/common/quic/quic_stats_gatherer.h index 9708ab07f5cc..f704eeebc238 100644 --- a/source/common/quic/quic_stats_gatherer.h +++ b/source/common/quic/quic_stats_gatherer.h @@ -20,7 +20,7 @@ class QuicStatsGatherer : public quic::QuicAckListenerInterface { // QuicAckListenerInterface void OnPacketAcked(int acked_bytes, quic::QuicTime::Delta delta_largest_observed) override; - void OnPacketRetransmitted(int /* retransmitted_bytes */) override {} + void OnPacketRetransmitted(int retransmitted_bytes) override; // Add bytes sent for this stream, for internal tracking of bytes acked. void addBytesSent(uint64_t bytes_sent, bool end_stream) { @@ -58,6 +58,8 @@ class QuicStatsGatherer : public quic::QuicAckListenerInterface { std::unique_ptr stream_info_; Envoy::TimeSource* time_source_ = nullptr; bool logging_done_ = false; + uint64_t retransmitted_packets_ = 0; + uint64_t retransmitted_bytes_ = 0; }; } // namespace Quic diff --git a/source/common/stream_info/stream_info_impl.h b/source/common/stream_info/stream_info_impl.h index b71bad0a7b1e..af11fcc817d3 100644 --- a/source/common/stream_info/stream_info_impl.h +++ b/source/common/stream_info/stream_info_impl.h @@ -185,6 +185,18 @@ struct StreamInfoImpl : public StreamInfo { uint64_t bytesReceived() const override { return bytes_received_; } + void addBytesRetransmitted(uint64_t bytes_retransmitted) override { + bytes_retransmitted_ += bytes_retransmitted; + } + + uint64_t bytesRetransmitted() const override { return bytes_retransmitted_; } + + void addPacketsRetransmitted(uint64_t packets_retransmitted) override { + packets_retransmitted_ += packets_retransmitted; + } + + uint64_t packetsRetransmitted() const override { return packets_retransmitted_; } + absl::optional protocol() const override { return protocol_; } void protocol(Http::Protocol protocol) override { protocol_ = protocol; } @@ -344,6 +356,8 @@ struct StreamInfoImpl : public StreamInfo { start_time_ = info.startTime(); start_time_monotonic_ = info.startTimeMonotonic(); downstream_transport_failure_reason_ = std::string(info.downstreamTransportFailureReason()); + bytes_retransmitted_ = info.bytesRetransmitted(); + packets_retransmitted_ = info.packetsRetransmitted(); } // This function is used to copy over every field exposed in the StreamInfo interface, with a @@ -435,6 +449,8 @@ struct StreamInfoImpl : public StreamInfo { std::shared_ptr upstream_info_; uint64_t bytes_received_{}; + uint64_t bytes_retransmitted_{}; + uint64_t packets_retransmitted_{}; uint64_t bytes_sent_{}; const Network::ConnectionInfoProviderSharedPtr downstream_connection_info_provider_; const Http::RequestHeaderMap* request_headers_{}; diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index c5211b117cc7..94ce4f716bce 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -402,6 +402,30 @@ TEST(SubstitutionFormatterTest, streamInfoFormatter) { ProtoEq(ValueUtil::numberValue(25.0))); } + { + StreamInfoFormatter bytes_retransmitted_format("BYTES_RETRANSMITTED"); + EXPECT_CALL(stream_info, bytesRetransmitted()).WillRepeatedly(Return(1)); + EXPECT_EQ("1", bytes_retransmitted_format.format(request_headers, response_headers, + response_trailers, stream_info, body, + AccessLog::AccessLogType::NotSet)); + EXPECT_THAT(bytes_retransmitted_format.formatValue(request_headers, response_headers, + response_trailers, stream_info, body, + AccessLog::AccessLogType::NotSet), + ProtoEq(ValueUtil::numberValue(1.0))); + } + + { + StreamInfoFormatter packets_retransmitted_format("PACKETS_RETRANSMITTED"); + EXPECT_CALL(stream_info, packetsRetransmitted()).WillRepeatedly(Return(1)); + EXPECT_EQ("1", packets_retransmitted_format.format(request_headers, response_headers, + response_trailers, stream_info, body, + AccessLog::AccessLogType::NotSet)); + EXPECT_THAT(packets_retransmitted_format.formatValue(request_headers, response_headers, + response_trailers, stream_info, body, + AccessLog::AccessLogType::NotSet), + ProtoEq(ValueUtil::numberValue(1.0))); + } + { StreamInfoFormatter bytes_received_format("BYTES_RECEIVED"); EXPECT_CALL(stream_info, bytesReceived()).WillRepeatedly(Return(1)); diff --git a/test/common/stream_info/stream_info_impl_test.cc b/test/common/stream_info/stream_info_impl_test.cc index 9c6cad4abccd..149e2dc04e29 100644 --- a/test/common/stream_info/stream_info_impl_test.cc +++ b/test/common/stream_info/stream_info_impl_test.cc @@ -37,8 +37,8 @@ std::chrono::nanoseconds checkDuration(std::chrono::nanoseconds last, class StreamInfoImplTest : public testing::Test { protected: void assertStreamInfoSize(StreamInfoImpl stream_info) { - ASSERT_TRUE(sizeof(stream_info) == 824 || sizeof(stream_info) == 840 || - sizeof(stream_info) == 872) + ASSERT_TRUE(sizeof(stream_info) == 840 || sizeof(stream_info) == 856 || + sizeof(stream_info) == 888) << "If adding fields to StreamInfoImpl, please check to see if you " "need to add them to setFromForRecreateStream or setFrom! Current size " << sizeof(stream_info); @@ -245,6 +245,8 @@ TEST_F(StreamInfoImplTest, SetFromForRecreateStream) { s1.addBytesReceived(1); s1.downstreamTiming().onLastDownstreamRxByteReceived(test_time_.timeSystem()); + s1.addBytesRetransmitted(1); + s1.addPacketsRetransmitted(1); #ifdef __clang__ #if defined(__linux__) @@ -264,6 +266,8 @@ TEST_F(StreamInfoImplTest, SetFromForRecreateStream) { EXPECT_EQ(s1.bytesReceived(), s2.bytesReceived()); EXPECT_EQ(s1.getDownstreamBytesMeter(), s2.getDownstreamBytesMeter()); EXPECT_EQ(s1.downstreamTransportFailureReason(), s2.downstreamTransportFailureReason()); + EXPECT_EQ(s1.bytesRetransmitted(), s2.bytesRetransmitted()); + EXPECT_EQ(s1.packetsRetransmitted(), s2.packetsRetransmitted()); } TEST_F(StreamInfoImplTest, SetFrom) { @@ -272,6 +276,8 @@ TEST_F(StreamInfoImplTest, SetFrom) { // setFromForRecreateStream s1.addBytesReceived(1); s1.downstreamTiming().onLastDownstreamRxByteReceived(test_time_.timeSystem()); + s1.addBytesRetransmitted(1); + s1.addPacketsRetransmitted(1); // setFrom s1.setRouteName("foo"); @@ -322,6 +328,8 @@ TEST_F(StreamInfoImplTest, SetFrom) { EXPECT_EQ(s1.bytesReceived(), s2.bytesReceived()); EXPECT_EQ(s1.getDownstreamBytesMeter(), s2.getDownstreamBytesMeter()); EXPECT_EQ(s1.downstreamTransportFailureReason(), s2.downstreamTransportFailureReason()); + EXPECT_EQ(s1.bytesRetransmitted(), s2.bytesRetransmitted()); + EXPECT_EQ(s1.packetsRetransmitted(), s2.packetsRetransmitted()); // Copied by setFrom EXPECT_EQ(s1.getRouteName(), s2.getRouteName()); diff --git a/test/integration/BUILD b/test/integration/BUILD index c918f09fadf1..2f53109884c5 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -2275,6 +2275,7 @@ envoy_cc_test( "//test/common/config:dummy_config_proto_cc_proto", "//test/extensions/transport_sockets/tls/cert_validator:timed_cert_validator", ":http_integration_lib", + ":socket_interface_swap_lib", "//source/common/quic:client_connection_factory_lib", "//source/common/quic:envoy_quic_client_connection_lib", "//source/common/quic:envoy_quic_client_session_lib", diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 97f93cda361e..64dc3b724b47 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -28,6 +28,7 @@ #include "test/config/utility.h" #include "test/extensions/transport_sockets/tls/cert_validator/timed_cert_validator.h" #include "test/integration/http_integration.h" +#include "test/integration/socket_interface_swap.h" #include "test/integration/ssl_utility.h" #include "test/test_common/registry.h" #include "test/test_common/test_runtime.h" @@ -1380,6 +1381,41 @@ TEST_P(QuicHttpIntegrationTest, DeferredLoggingWithInternalRedirect) { EXPECT_EQ(/* RESP(test-header) */ metrics.at(21), "-"); } +TEST_P(QuicHttpIntegrationTest, DeferredLoggingWithRetransmission) { + useAccessLog("%BYTES_RETRANSMITTED%,%PACKETS_RETRANSMITTED%"); + initialize(); + + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + IntegrationStreamDecoderPtr response = + codec_client_->makeHeaderOnlyRequest(default_request_headers_); + waitForNextUpstreamRequest(0, TestUtility::DefaultTimeout); + + // Temporarily prevent server from writing packets (i.e. to respond to downstream) + // to simulate packet loss and trigger retransmissions. + SocketInterfaceSwap socket_swap(upstreamProtocol() == Http::CodecType::HTTP3 + ? Network::Socket::Type::Datagram + : Network::Socket::Type::Stream); + Network::IoSocketError* ebadf = Network::IoSocketError::getIoSocketEbadfInstance(); + socket_swap.write_matcher_->setDestinationPort(lookupPort("http")); + socket_swap.write_matcher_->setWriteOverride(ebadf); + upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, true); + absl::SleepFor(absl::Milliseconds(500 * TSAN_TIMEOUT_FACTOR)); + // Allow the response to be sent downstream again. + socket_swap.write_matcher_->setWriteOverride(nullptr); + + ASSERT_TRUE(response->waitForEndStream()); + codec_client_->close(); + ASSERT_TRUE(response->complete()); + + // Confirm that retransmissions are logged. + std::string log = waitForAccessLog(access_log_name_); + std::vector metrics = absl::StrSplit(log, ','); + ASSERT_EQ(metrics.size(), 2); + EXPECT_GT(/* BYTES_RETRANSMITTED */ std::stoi(metrics.at(0)), 0); + EXPECT_GT(/* PACKETS_RETRANSMITTED */ std::stoi(metrics.at(1)), 0); + EXPECT_GE(std::stoi(metrics.at(0)), std::stoi(metrics.at(1))); +} + TEST_P(QuicHttpIntegrationTest, InvalidTrailer) { initialize(); // Empty string in trailer key is invalid. diff --git a/test/mocks/stream_info/mocks.h b/test/mocks/stream_info/mocks.h index f965a739b9f6..7ad098443b98 100644 --- a/test/mocks/stream_info/mocks.h +++ b/test/mocks/stream_info/mocks.h @@ -85,6 +85,10 @@ class MockStreamInfo : public StreamInfo { MOCK_METHOD(OptRef, downstreamTiming, (), (const)); MOCK_METHOD(void, addBytesReceived, (uint64_t)); MOCK_METHOD(uint64_t, bytesReceived, (), (const)); + MOCK_METHOD(void, addBytesRetransmitted, (uint64_t)); + MOCK_METHOD(uint64_t, bytesRetransmitted, (), (const)); + MOCK_METHOD(void, addPacketsRetransmitted, (uint64_t)); + MOCK_METHOD(uint64_t, packetsRetransmitted, (), (const)); MOCK_METHOD(void, addWireBytesReceived, (uint64_t)); MOCK_METHOD(uint64_t, wireBytesReceived, (), (const)); MOCK_METHOD(void, setRouteName, (absl::string_view route_name)); diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index ef68770145af..dd3785342239 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -1160,6 +1160,7 @@ responder restarter resync ret +retransmissions retransmitted retransmitting retriable From 92e7b1c8a2373ce1193398e9105c14813abfecc6 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Mon, 5 Jun 2023 16:51:55 -0400 Subject: [PATCH 181/228] mobile: better filter docs (#27810) Signed-off-by: Alyssa Wilk --- mobile/docs/root/api/starting_envoy.rst | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mobile/docs/root/api/starting_envoy.rst b/mobile/docs/root/api/starting_envoy.rst index f40d8244122e..67b68a5a101a 100644 --- a/mobile/docs/root/api/starting_envoy.rst +++ b/mobile/docs/root/api/starting_envoy.rst @@ -226,23 +226,26 @@ This information is sent as metadata when flushing stats. builder.addAppId("com.mydomain.myapp) ~~~~~~~~~~~~~~~~~~~~~~~~~ -``enableAdminInterface`` +``addNativeFilter`` ~~~~~~~~~~~~~~~~~~~~~~~~~ -Enable admin interface on 127.0.0.1:9901 address. +Add a C++ filter to the Envoy Mobile filter chain .. attention:: - Admin interface is intended to be used for development/debugging purposes only. - Enabling it in production may open your app to security vulnerabilities. + This will only work if the C++ filter specified is linked into your Envoy Mobile build. + For C++ and Android testing, calling addNativeFilter and linking the Envoy library by adding the + library to ``envoy_build_config/extensions_build_config.bzl`` is sufficient. + For iOS, due to enthusiastic garbage collection, and for upstream CI, to catch bugs, you will + also need to forceRegister the filter in ``envoy_build_config/extension_registry.cc`` **Example**:: // Kotlin - builder.enableAdminInterface() + builder.addNativeFilter("envoy.filters.http.buffer", "{\"@type\":\"type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer\",\"max_request_bytes\":5242880}") // Swift - builder.enableAdminInterface() + builder.addNativeFilter("envoy.filters.http.buffer", "{\"@type\":\"type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer\",\"max_request_bytes\":5242880}") ~~~~~~~~~~~~~~~~~~~~~~ ``setOnEngineRunning`` From 3b7328f253c9cdd82dc81b736a85aeaa622262dd Mon Sep 17 00:00:00 2001 From: ohadvano <49730675+ohadvano@users.noreply.github.com> Date: Tue, 6 Jun 2023 09:56:14 +0300 Subject: [PATCH 182/228] Fix post-submit clang tidy (#27815) Signed-off-by: ohadvano <49730675+ohadvano@users.noreply.github.com> --- test/server/config_validation/server_test.cc | 8 ++++---- test/server/server_test.cc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/server/config_validation/server_test.cc b/test/server/config_validation/server_test.cc index cda36802a3dd..f03ec5f21719 100644 --- a/test/server/config_validation/server_test.cc +++ b/test/server/config_validation/server_test.cc @@ -113,7 +113,7 @@ class JsonApplicationLogsValidationServerForbiddenFlagvTest : public ValidationS } }; -class JsonApplicationLogsValidationServerForbiddenFlag_Test : public ValidationServerTest { +class JsonApplicationLogsValidationServerForbiddenFlagUnderscoreTest : public ValidationServerTest { public: static void SetUpTestSuite() { // NOLINT(readability-identifier-naming) setupTestDirectory(); @@ -306,7 +306,7 @@ INSTANTIATE_TEST_SUITE_P( ::testing::ValuesIn( JsonApplicationLogsValidationServerForbiddenFlagvTest::getAllConfigFiles())); -TEST_P(JsonApplicationLogsValidationServerForbiddenFlag_Test, TestForbiddenFlag) { +TEST_P(JsonApplicationLogsValidationServerForbiddenFlagUnderscoreTest, TestForbiddenFlag) { Thread::MutexBasicLockable access_log_lock; Stats::IsolatedStoreImpl stats_store; DangerousDeprecatedTestTime time_system; @@ -320,9 +320,9 @@ TEST_P(JsonApplicationLogsValidationServerForbiddenFlag_Test, TestForbiddenFlag) } INSTANTIATE_TEST_SUITE_P( - AllConfigs, JsonApplicationLogsValidationServerForbiddenFlag_Test, + AllConfigs, JsonApplicationLogsValidationServerForbiddenFlagUnderscoreTest, ::testing::ValuesIn( - JsonApplicationLogsValidationServerForbiddenFlag_Test::getAllConfigFiles())); + JsonApplicationLogsValidationServerForbiddenFlagUnderscoreTest::getAllConfigFiles())); } // namespace } // namespace Server diff --git a/test/server/server_test.cc b/test/server/server_test.cc index c47df5d57c57..abbc3690e0f5 100644 --- a/test/server/server_test.cc +++ b/test/server/server_test.cc @@ -1653,7 +1653,7 @@ TEST_P(ServerInstanceImplTest, JsonApplicationLogFailWithForbiddenFlagv) { "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %v is unavailable for JSON log formats"); } -TEST_P(ServerInstanceImplTest, JsonApplicationLogFailWithForbiddenFlag_) { +TEST_P(ServerInstanceImplTest, JsonApplicationLogFailWithForbiddenFlagUnderscore) { EXPECT_THROW_WITH_MESSAGE( initialize("test/server/test_data/server/json_application_log_forbidden_flag_.yaml"), EnvoyException, From bbcc855c1bb1a9882ada62859de97b618abf0ea5 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 6 Jun 2023 09:24:35 -0400 Subject: [PATCH 183/228] mobile: running compile time options build on all Envoy PRs (#27707) the no-YAML build is easy to break and we've move this off the constrained machines. Signed-off-by: Alyssa Wilk --- .github/workflows/mobile-compile_time_options.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/mobile-compile_time_options.yml b/.github/workflows/mobile-compile_time_options.yml index c6c246432436..3c9693112247 100644 --- a/.github/workflows/mobile-compile_time_options.yml +++ b/.github/workflows/mobile-compile_time_options.yml @@ -17,7 +17,6 @@ jobs: secrets: inherit cc_test: - if: ${{ needs.env.outputs.mobile_compile_time_options == 'true' }} needs: env name: cc_test runs-on: ubuntu-20.04 From 1c25c51275ad99fe411a6ea73bc634fcedcd0289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20B=C3=A9ky?= Date: Tue, 6 Jun 2023 10:29:16 -0400 Subject: [PATCH 184/228] [balsa] Disallow extended ASCII in header names. (#27738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [balsa] Disallow extended ASCII in header names. This is for parity with http-parser. Note that BalsaParser already disallows control characters, space, and certain separator characters [1, 2], but not characters above 127. [1] https://github.com/google/quiche/blob/ef9e527e14440794cc18813ef079ebdb3650f8ad/quiche/balsa/header_properties.h#L21-L30 [2] https://github.com/google/quiche/blob/ef9e527e14440794cc18813ef079ebdb3650f8ad/quiche/balsa/balsa_frame.cc#L414 Signed-off-by: Bence Béky --- source/common/http/http1/balsa_parser.cc | 36 ++++-- test/common/http/http1/codec_impl_test.cc | 149 ++++++++++++++++++++++ tools/spelling/spelling_dictionary.txt | 1 + 3 files changed, 172 insertions(+), 14 deletions(-) diff --git a/source/common/http/http1/balsa_parser.cc b/source/common/http/http1/balsa_parser.cc index 8826994d7bc3..7a354a8afe8c 100644 --- a/source/common/http/http1/balsa_parser.cc +++ b/source/common/http/http1/balsa_parser.cc @@ -23,6 +23,14 @@ constexpr absl::string_view kColonSlashSlash = "://"; // Response must start with "HTTP". constexpr char kResponseFirstByte = 'H'; +// Allowed characters for field names according to Section 5.1 +// and for methods according to Section 9.1 of RFC 9110: +// https://www.rfc-editor.org/rfc/rfc9110.html +constexpr absl::string_view kValidCharacters = + "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~"; +constexpr absl::string_view::iterator kValidCharactersBegin = kValidCharacters.begin(); +constexpr absl::string_view::iterator kValidCharactersEnd = kValidCharacters.end(); + bool isFirstCharacterOfValidMethod(char c) { static constexpr char kValidFirstCharacters[] = {'A', 'B', 'C', 'D', 'G', 'H', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U'}; @@ -36,20 +44,9 @@ bool isFirstCharacterOfValidMethod(char c) { // enabled. bool isMethodValid(absl::string_view method, bool allow_custom_methods) { if (allow_custom_methods) { - // Allowed characters in method according to RFC 9110, - // https://www.rfc-editor.org/rfc/rfc9110.html#section-5.1. - static constexpr char kValidCharacters[] = { - '!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '0', '1', '2', '3', '4', '5', - '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '^', '_', - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '~'}; - const auto* begin = &kValidCharacters[0]; - const auto* end = &kValidCharacters[ABSL_ARRAYSIZE(kValidCharacters) - 1] + 1; - return !method.empty() && - std::all_of(method.begin(), method.end(), [begin, end](absl::string_view::value_type c) { - return std::binary_search(begin, end, c); + std::all_of(method.begin(), method.end(), [](absl::string_view::value_type c) { + return std::binary_search(kValidCharactersBegin, kValidCharactersEnd, c); }); } @@ -138,6 +135,12 @@ bool isVersionValid(absl::string_view version_input) { return regex->match(version_input); } +bool isHeaderNameValid(absl::string_view name) { + return std::all_of(name.begin(), name.end(), [](absl::string_view::value_type c) { + return std::binary_search(kValidCharactersBegin, kValidCharactersEnd, c); + }); +} + } // anonymous namespace BalsaParser::BalsaParser(MessageType type, ParserCallbacks* connection, size_t max_header_length, @@ -394,8 +397,13 @@ void BalsaParser::processHeadersOrTrailersImpl(const quiche::BalsaHeaders& heade } absl::string_view key = key_value.first; - status_ = convertResult(connection_->onHeaderField(key.data(), key.length())); + if (!isHeaderNameValid(key)) { + status_ = ParserStatus::Error; + error_message_ = "HPE_INVALID_HEADER_TOKEN"; + return; + } + status_ = convertResult(connection_->onHeaderField(key.data(), key.length())); if (status_ == ParserStatus::Error) { return; } diff --git a/test/common/http/http1/codec_impl_test.cc b/test/common/http/http1/codec_impl_test.cc index 54bfa2561372..c269f4513533 100644 --- a/test/common/http/http1/codec_impl_test.cc +++ b/test/common/http/http1/codec_impl_test.cc @@ -4599,5 +4599,154 @@ TEST_P(Http1ServerConnectionImplTest, Http10Rejected) { EXPECT_THAT(status.message(), StartsWith("Upgrade required")); } +TEST_P(Http1ClientConnectionImplTest, SeparatorInHeaderName) { + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + EXPECT_TRUE(request_encoder.encodeHeaders(headers, true).ok()); + + Buffer::OwnedImpl response("HTTP/1.1 200 OK\r\n" + "fo[o: bar\r\n" + "\r\n"); + auto status = codec_->dispatch(response); + + EXPECT_FALSE(status.ok()); + if (parser_impl_ == Http1ParserImpl::BalsaParser) { + EXPECT_EQ(status.message(), "http/1.1 protocol error: INVALID_HEADER_NAME_CHARACTER"); + } else { + EXPECT_EQ(status.message(), "http/1.1 protocol error: HPE_INVALID_HEADER_TOKEN"); + } +} + +TEST_P(Http1ServerConnectionImplTest, SeparatorInHeaderName) { + initialize(); + + StrictMock decoder; + EXPECT_CALL(callbacks_, newStream(_, _)).WillOnce(ReturnRef(decoder)); + EXPECT_CALL(decoder, + sendLocalReply(Http::Code::BadRequest, "Bad Request", _, _, "http1.codec_error")); + + Buffer::OwnedImpl buffer("GET / HTTP/1.1\r\n" + "fo[o: bar\r\n" + "\r\n"); + auto status = codec_->dispatch(buffer); + + EXPECT_FALSE(status.ok()); + if (parser_impl_ == Http1ParserImpl::BalsaParser) { + EXPECT_EQ(status.message(), "http/1.1 protocol error: INVALID_HEADER_NAME_CHARACTER"); + } else { + EXPECT_EQ(status.message(), "http/1.1 protocol error: HPE_INVALID_HEADER_TOKEN"); + } +} + +// BalsaParser always rejects a header name with space. HttpParser only rejects +// it in strict mode, which is disabled when ENVOY_ENABLE_UHV is defined. +TEST_P(Http1ClientConnectionImplTest, SpaceInHeaderName) { + bool accept = parser_impl_ == Http1ParserImpl::HttpParser; +#ifndef ENVOY_ENABLE_UHV + accept = false; +#endif + + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + EXPECT_TRUE(request_encoder.encodeHeaders(headers, true).ok()); + + if (accept) { + EXPECT_CALL(response_decoder, decodeHeaders_(_, false)); + } + + Buffer::OwnedImpl response("HTTP/1.1 200 OK\r\n" + "fo o: bar\r\n" + "\r\n"); + auto status = codec_->dispatch(response); + + if (accept) { + EXPECT_TRUE(status.ok()); + } else { + EXPECT_FALSE(status.ok()); + if (parser_impl_ == Http1ParserImpl::BalsaParser) { + EXPECT_EQ(status.message(), "http/1.1 protocol error: INVALID_HEADER_NAME_CHARACTER"); + } else { + EXPECT_EQ(status.message(), "http/1.1 protocol error: HPE_INVALID_HEADER_TOKEN"); + } + } +} + +TEST_P(Http1ServerConnectionImplTest, SpaceInHeaderName) { + bool accept = parser_impl_ == Http1ParserImpl::HttpParser; +#ifndef ENVOY_ENABLE_UHV + accept = false; +#endif + + initialize(); + + StrictMock decoder; + EXPECT_CALL(callbacks_, newStream(_, _)).WillOnce(ReturnRef(decoder)); + + if (accept) { + EXPECT_CALL(decoder, decodeHeaders_(_, true)); + } else { + EXPECT_CALL(decoder, + sendLocalReply(Http::Code::BadRequest, "Bad Request", _, _, "http1.codec_error")); + } + + Buffer::OwnedImpl buffer("GET / HTTP/1.1\r\n" + "fo o: bar\r\n" + "\r\n"); + auto status = codec_->dispatch(buffer); + + if (accept) { + EXPECT_TRUE(status.ok()); + } else { + EXPECT_FALSE(status.ok()); + if (parser_impl_ == Http1ParserImpl::BalsaParser) { + EXPECT_EQ(status.message(), "http/1.1 protocol error: INVALID_HEADER_NAME_CHARACTER"); + } else { + EXPECT_EQ(status.message(), "http/1.1 protocol error: HPE_INVALID_HEADER_TOKEN"); + } + } +} + +TEST_P(Http1ClientConnectionImplTest, ExtendedAsciiInHeaderName) { + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + EXPECT_TRUE(request_encoder.encodeHeaders(headers, true).ok()); + + // SPELLCHECKER(off) + Buffer::OwnedImpl response("HTTP/1.1 200 OK\r\n" + "föö: bar\r\n" + "\r\n"); + // SPELLCHECKER(on) + auto status = codec_->dispatch(response); + EXPECT_FALSE(status.ok()); + EXPECT_EQ(status.message(), "http/1.1 protocol error: HPE_INVALID_HEADER_TOKEN"); +} + +TEST_P(Http1ServerConnectionImplTest, ExtendedAsciiInHeaderName) { + initialize(); + + StrictMock decoder; + EXPECT_CALL(callbacks_, newStream(_, _)).WillOnce(ReturnRef(decoder)); + EXPECT_CALL(decoder, + sendLocalReply(Http::Code::BadRequest, "Bad Request", _, _, "http1.codec_error")); + + // SPELLCHECKER(off) + Buffer::OwnedImpl buffer("GET / HTTP/1.1\r\n" + "föö: bar\r\n" + "\r\n"); + // SPELLCHECKER(on) + auto status = codec_->dispatch(buffer); + EXPECT_FALSE(status.ok()); + EXPECT_EQ(status.message(), "http/1.1 protocol error: HPE_INVALID_HEADER_TOKEN"); +} + } // namespace Http } // namespace Envoy diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index dd3785342239..429f6a848cd3 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -815,6 +815,7 @@ idx ifdef iff ified +ifndef impl implementors impls From 845be282e9968884dd2beef386a1946fac54df56 Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Tue, 6 Jun 2023 12:09:10 -0400 Subject: [PATCH 185/228] cel_matcher: match on xds attributes. (#27790) With PR #25818, xds attributes (like upstream cluster metadata) are provided via streamInfo and are available to CEL library. This PR enables them and tests upstream cluster metadata specifically. --- .../matching/http/cel_input/cel_input.h | 9 +-- .../cel_matcher/cel_matcher_test.cc | 42 +++++++++++-- .../cel_matcher/cel_matcher_test.h | 60 +++++++++++++++++++ test/mocks/stream_info/mocks.cc | 5 ++ test/mocks/stream_info/mocks.h | 1 + 5 files changed, 105 insertions(+), 12 deletions(-) diff --git a/source/extensions/matching/http/cel_input/cel_input.h b/source/extensions/matching/http/cel_input/cel_input.h index 0e5707c4e2e4..324d2fd264cd 100644 --- a/source/extensions/matching/http/cel_input/cel_input.h +++ b/source/extensions/matching/http/cel_input/cel_input.h @@ -39,13 +39,8 @@ class HttpCelDataInput : public Matcher::DataInput activation = Extensions::Filters::Common::Expr::createActivation( data.streamInfo(), maybe_request_headers.ptr(), maybe_response_headers.ptr(), diff --git a/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc index f1d3378a800d..0a46dfdc1133 100644 --- a/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc +++ b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.cc @@ -40,10 +40,15 @@ enum class ExpressionType { NoExpression = 2, }; +constexpr absl::string_view kFilterNamespace = "cel_matcher"; +constexpr absl::string_view kMetadataKey = "service_name"; +constexpr absl::string_view kMetadataValue = "test_service"; + class CelMatcherTest : public ::testing::Test { public: CelMatcherTest() : inject_action_(action_factory_), + cluster_info_(std::make_shared>()), data_(Envoy::Http::Matching::HttpMatchingDataImpl(stream_info_)) {} void buildCustomHeader(const absl::flat_hash_map& custom_value_pairs, @@ -112,11 +117,21 @@ class CelMatcherTest : public ::testing::Test { return match_tree(); } + void setUpstreamClusterMetadata(const std::string& namespace_str, const std::string& metadata_key, + const std::string& metadata_value) { + Envoy::Config::Metadata::mutableMetadataValue(metadata_, namespace_str, metadata_key) + .set_string_value(metadata_value); + EXPECT_CALL(*cluster_info_, metadata()).WillRepeatedly(testing::ReturnPointee(&metadata_)); + stream_info_.setUpstreamClusterInfo(cluster_info_); + } + Matcher::StringActionFactory action_factory_; Registry::InjectFactory> inject_action_; + std::shared_ptr> cluster_info_; testing::NiceMock stream_info_; absl::string_view context_ = ""; testing::NiceMock factory_context_; + envoy::config::core::v3::Metadata metadata_; TestRequestHeaderMapImpl default_headers_{ {":method", "GET"}, {":scheme", "http"}, {":authority", "host"}}; @@ -130,7 +145,6 @@ TEST_F(CelMatcherTest, CelMatcherRequestHeaderMatched) { TestRequestHeaderMapImpl request_headers = default_headers_; buildCustomHeader({{"authenticated_user", "staging"}}, request_headers); data_.onRequestHeaders(request_headers); - // data.onRequestHeaders(request_headers); const auto result = matcher_tree->match(data_); // The match was complete, match found. @@ -164,13 +178,31 @@ TEST_F(CelMatcherTest, CelMatcherRequestHeaderNotMatched) { EXPECT_EQ(result_2.on_match_, absl::nullopt); } -TEST_F(CelMatcherTest, CelMatcherNoRequestAttributes) { - auto matcher_tree = buildMatcherTree(RequestHeaderCelExprString); +TEST_F(CelMatcherTest, CelMatcherClusterMetadataMatched) { + setUpstreamClusterMetadata(std::string(kFilterNamespace), std::string(kMetadataKey), + std::string(kMetadataValue)); + Envoy::Http::Matching::HttpMatchingDataImpl data = + Envoy::Http::Matching::HttpMatchingDataImpl(stream_info_); + auto matcher_tree = buildMatcherTree(absl::StrFormat( + UpstreamClusterMetadataCelString, kFilterNamespace, kMetadataKey, kMetadataValue)); + const auto result = matcher_tree->match(data_); + // The match was complete, match found. + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); + EXPECT_TRUE(result.on_match_.has_value()); + EXPECT_NE(result.on_match_->action_cb_, nullptr); +} + +TEST_F(CelMatcherTest, CelMatcherClusterMetadataNotMatched) { + setUpstreamClusterMetadata(std::string(kFilterNamespace), std::string(kMetadataKey), + "wrong_service"); + Envoy::Http::Matching::HttpMatchingDataImpl data = + Envoy::Http::Matching::HttpMatchingDataImpl(stream_info_); + auto matcher_tree = buildMatcherTree(absl::StrFormat( + UpstreamClusterMetadataCelString, kFilterNamespace, kMetadataKey, kMetadataValue)); - // No request attributes added to matching data. const auto result = matcher_tree->match(data_); // The match was completed, no match found. - EXPECT_EQ(result.match_state_, Matcher::MatchState::UnableToMatch); + EXPECT_EQ(result.match_state_, Matcher::MatchState::MatchComplete); EXPECT_EQ(result.on_match_, absl::nullopt); } diff --git a/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h index efadd414fe34..65d6b0626f13 100644 --- a/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h +++ b/test/extensions/matching/input_matchers/cel_matcher/cel_matcher_test.h @@ -1,5 +1,7 @@ #pragma once +#include "absl/strings/string_view.h" + namespace Envoy { namespace Extensions { namespace Matching { @@ -547,6 +549,64 @@ inline constexpr char RequestAndResponseCelString[] = R"pb( } )pb"; +// xds.cluster_metadata.filter_metadata['cel_matcher']['service_name'] == 'test_service' +inline constexpr absl::string_view UpstreamClusterMetadataCelString = R"pb( + expr { + id: 8 + call_expr { + function: "_==_" + args { + id: 6 + call_expr { + function: "_[_]" + args { + id: 4 + call_expr { + function: "_[_]" + args { + id: 3 + select_expr { + operand { + id: 2 + select_expr { + operand { + id: 1 + ident_expr { + name: "xds" + } + } + field: "cluster_metadata" + } + } + field: "filter_metadata" + } + } + args { + id: 5 + const_expr { + string_value: "%s" + } + } + } + } + args { + id: 7 + const_expr { + string_value: "%s" + } + } + } + } + args { + id: 9 + const_expr { + string_value: "%s" + } + } + } + } +)pb"; + } // namespace CelMatcher } // namespace InputMatchers } // namespace Matching diff --git a/test/mocks/stream_info/mocks.cc b/test/mocks/stream_info/mocks.cc index d62ebea53694..141512314d4b 100644 --- a/test/mocks/stream_info/mocks.cc +++ b/test/mocks/stream_info/mocks.cc @@ -190,6 +190,11 @@ MockStreamInfo::MockStreamInfo() })); ON_CALL(*this, downstreamTransportFailureReason()) .WillByDefault(ReturnPointee(&downstream_transport_failure_reason_)); + ON_CALL(*this, setUpstreamClusterInfo(_)) + .WillByDefault(Invoke([this](const Upstream::ClusterInfoConstSharedPtr& cluster_info) { + upstream_cluster_info_ = std::move(cluster_info); + })); + ON_CALL(*this, upstreamClusterInfo()).WillByDefault(ReturnPointee(&upstream_cluster_info_)); } MockStreamInfo::~MockStreamInfo() = default; diff --git a/test/mocks/stream_info/mocks.h b/test/mocks/stream_info/mocks.h index 7ad098443b98..469169332a5b 100644 --- a/test/mocks/stream_info/mocks.h +++ b/test/mocks/stream_info/mocks.h @@ -150,6 +150,7 @@ class MockStreamInfo : public StreamInfo { absl::optional response_code_; absl::optional response_code_details_; absl::optional connection_termination_details_; + absl::optional upstream_cluster_info_; std::shared_ptr upstream_info_; uint64_t response_flags_{}; envoy::config::core::v3::Metadata metadata_; From 64e334de55386060e3124a0e9471e5b60804a4c0 Mon Sep 17 00:00:00 2001 From: ericorth <57926619+ericorth@users.noreply.github.com> Date: Tue, 6 Jun 2023 12:23:45 -0400 Subject: [PATCH 186/228] QUIC: remove all usage of quic::kRVCM (#27774) Commit Message: remove all usage of quic::kRVCM Additional Description: This QUIC connection option no longer does anything and is no longer needed after some recent (~1 month ago) changes in QUICHE. Now, QUICHE is removing the definition of quic::kRVCM. Removing all usage from Envoy to unblock QUICHE rolls to Envoy. Risk Level: Low Testing: Covered by existing unit tests Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a Signed-off-by: Eric Orth --- source/common/quic/client_connection_factory_impl.cc | 7 ------- test/common/quic/client_connection_factory_impl_test.cc | 3 --- test/integration/quic_http_integration_test.cc | 4 ++-- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/source/common/quic/client_connection_factory_impl.cc b/source/common/quic/client_connection_factory_impl.cc index 67f4fc103731..269dbbdf078f 100644 --- a/source/common/quic/client_connection_factory_impl.cc +++ b/source/common/quic/client_connection_factory_impl.cc @@ -23,13 +23,6 @@ createPersistentQuicInfoForCluster(Event::Dispatcher& dispatcher, quic_info->quic_config_.max_idle_time_before_crypto_handshake()) { quic_info->quic_config_.set_max_idle_time_before_crypto_handshake(crypto_timeout); } - // Default enable RVCM connection option so that port migration is enabled. - quic::QuicTagVector connection_options; - if (quic_info->quic_config_.HasSendConnectionOptions()) { - connection_options = quic_info->quic_config_.SendConnectionOptions(); - } - connection_options.push_back(quic::kRVCM); - quic_info->quic_config_.SetConnectionOptionsToSend(connection_options); return quic_info; } diff --git a/test/common/quic/client_connection_factory_impl_test.cc b/test/common/quic/client_connection_factory_impl_test.cc index 9a27e6cd33f0..f93fcce3482f 100644 --- a/test/common/quic/client_connection_factory_impl_test.cc +++ b/test/common/quic/client_connection_factory_impl_test.cc @@ -41,9 +41,6 @@ class QuicNetworkConnectionTest : public Event::TestUsingSimulatedTime, protocol_options->max_concurrent_streams().value()); EXPECT_EQ(quic_info_->quic_config_.GetInitialMaxStreamDataBytesIncomingBidirectionalToSend(), protocol_options->initial_stream_window_size().value()); - ASSERT_TRUE(quic_info_->quic_config_.HasSendConnectionOptions()); - EXPECT_TRUE( - quic::ContainsQuicTag(quic_info_->quic_config_.SendConnectionOptions(), quic::kRVCM)); test_address_ = Network::Utility::resolveUrl( absl::StrCat("tcp://", Network::Test::getLoopbackAddressUrlString(GetParam()), ":30")); diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 64dc3b724b47..c11b91987849 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -1704,7 +1704,7 @@ TEST_P(QuicHttpIntegrationTest, UsesPreferredAddress) { }); initialize(); - quic::QuicTagVector connection_options{quic::kRVCM, quic::kSPAD}; + quic::QuicTagVector connection_options{quic::kSPAD}; dynamic_cast(*quic_connection_persistent_info_) .quic_config_.SetConnectionOptionsToSend(connection_options); codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); @@ -1767,7 +1767,7 @@ TEST_P(QuicHttpIntegrationTest, UsesPreferredAddressDualStack) { }); initialize(); - quic::QuicTagVector connection_options{quic::kRVCM, quic::kSPAD}; + quic::QuicTagVector connection_options{quic::kSPAD}; dynamic_cast(*quic_connection_persistent_info_) .quic_config_.SetConnectionOptionsToSend(connection_options); codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); From e7bb2feaf8299239ce9f3cc591886965149bb263 Mon Sep 17 00:00:00 2001 From: DiazAlan <109677874+DiazAlan@users.noreply.github.com> Date: Tue, 6 Jun 2023 15:48:28 -0400 Subject: [PATCH 187/228] Add hidden functionality to stats_request (#27643) Commit Message: Implement hidden functionality of gauges to stats_request Additional Description: Risk Level: Low Testing: Added three tests to stats_requests_test Signed-off-by: AlanDiaz --- changelogs/current.yaml | 4 ++ docs/root/operations/admin.rst | 12 ++++ envoy/stats/sink.h | 2 +- envoy/stats/stats.h | 7 +-- source/common/stats/allocator_impl.cc | 6 +- source/server/admin/prometheus_stats.cc | 15 ++++- source/server/admin/stats_params.cc | 14 +++++ source/server/admin/stats_params.h | 7 +++ source/server/admin/stats_request.cc | 8 +++ test/common/stats/allocator_impl_test.cc | 59 +++++++++++++++++++ .../open_telemetry_impl_test.cc | 8 +-- test/server/admin/prometheus_stats_test.cc | 59 +++++++++++++++++-- test/server/admin/stats_handler_test.cc | 56 ++++++++++++++++++ test/server/admin/stats_params_test.cc | 17 ++++++ test/server/admin/stats_request_test.cc | 30 ++++++++++ 15 files changed, 287 insertions(+), 17 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 71e667638643..00ce45b7b76b 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -90,6 +90,10 @@ minor_behavior_changes: change: | Filter metadata containing ext proc stats has been moved from ext-proc-logging-info to a namespace corresponding to the name of the ext_proc filter. +- area: stats + change: | + Added new type of gauge with type hidden. These stats are hidden from admin/stats-sinks but can shown with a + query-parameter of ``/stats?hidden=include`` or ``/stats?hidden=showonly``. bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* diff --git a/docs/root/operations/admin.rst b/docs/root/operations/admin.rst index d0957b906108..bcc938406ce6 100644 --- a/docs/root/operations/admin.rst +++ b/docs/root/operations/admin.rst @@ -450,6 +450,18 @@ modify different aspects of the server: Outputs statistics that Envoy has updated (counters incremented at least once, gauges changed at least once, and histograms added to at least once). + .. http::get:: /stats?hidden=showonly + + Only outputs statistics that are internally marked as hidden. + + .. http::get:: /stats?hidden=include + + Hidden stats will be shown along side non-hidden stats. + + .. http::get:: /stats?hidden=exclude + + Hidden stats will be excluded from the output. This is the default behavior. + .. http:get:: /stats?filter=regex Filters the returned stats to those with names matching the regular diff --git a/envoy/stats/sink.h b/envoy/stats/sink.h index e833c44c554c..b83a06241b65 100644 --- a/envoy/stats/sink.h +++ b/envoy/stats/sink.h @@ -61,7 +61,7 @@ class SinkPredicates { virtual bool includeCounter(const Counter& counter) PURE; /** - * @return true if @param gague needs to be flushed to sinks. + * @return true if @param gauge needs to be flushed to sinks. */ virtual bool includeGauge(const Gauge& gauge) PURE; diff --git a/envoy/stats/stats.h b/envoy/stats/stats.h index cdc1ba896c9b..b2768144c60f 100644 --- a/envoy/stats/stats.h +++ b/envoy/stats/stats.h @@ -137,10 +137,9 @@ class Gauge : public Metric { public: // TODO(diazalan): Rename ImportMode to more generic name enum class ImportMode { - Uninitialized, // Gauge was discovered during hot-restart transfer. - NeverImport, // On hot-restart, each process starts with gauge at 0. - Accumulate, // Transfers gauge state on hot-restart. - // TODO(Diazalan): Add functionality for Hidden to be ignored by admin/stats-sink + Uninitialized, // Gauge was discovered during hot-restart transfer. + NeverImport, // On hot-restart, each process starts with gauge at 0. + Accumulate, // Transfers gauge state on hot-restart. HiddenAccumulate, // Will be transferred on hot-restart and ignored by admin/stats-sink }; diff --git a/source/common/stats/allocator_impl.cc b/source/common/stats/allocator_impl.cc index a8c9745461c2..c8c6905f4f48 100644 --- a/source/common/stats/allocator_impl.cc +++ b/source/common/stats/allocator_impl.cc @@ -419,7 +419,11 @@ void AllocatorImpl::forEachSinkedGauge(SizeFn f_size, StatFn f_stat) cons f_stat(*gauge); } } else { - forEachGauge(f_size, f_stat); + forEachGauge(f_size, [&f_stat](Gauge& gauge) { + if (!gauge.hidden()) { + f_stat(gauge); + } + }); } } diff --git a/source/server/admin/prometheus_stats.cc b/source/server/admin/prometheus_stats.cc index d65891f1c29a..195f047a4c6b 100644 --- a/source/server/admin/prometheus_stats.cc +++ b/source/server/admin/prometheus_stats.cc @@ -43,9 +43,12 @@ std::string sanitizeValue(const absl::string_view value) { }); } -/* - * Determine whether a metric has never been emitted and choose to - * not show it if we only wanted used metrics. +/** + * Determines whether a metric should be shown based on the specified query-parameters. This covers: + * ``usedonly``, hidden, and filter. + * + * @param metric the metric to test + * @param params captures query parameters indicating which metrics should be included. */ template static bool shouldShowMetric(const StatType& metric, const StatsParams& params) { @@ -55,6 +58,12 @@ static bool shouldShowMetric(const StatType& metric, const StatsParams& params) if (params.used_only_ && !metric.used()) { return false; } + if (params.hidden_ == HiddenFlag::ShowOnly && !metric.hidden()) { + return false; + } + if (params.hidden_ == HiddenFlag::Exclude && metric.hidden()) { + return false; + } if (params.re2_filter_ != nullptr && !re2::RE2::PartialMatch(metric.name(), *params.re2_filter_)) { return false; diff --git a/source/server/admin/stats_params.cc b/source/server/admin/stats_params.cc index 4c143a238dcf..3c5c95eb6e54 100644 --- a/source/server/admin/stats_params.cc +++ b/source/server/admin/stats_params.cc @@ -50,6 +50,20 @@ Http::Code StatsParams::parse(absl::string_view url, Buffer::Instance& response) return Http::Code::BadRequest; } + const absl::optional hidden_value = Utility::queryParam(query_, "hidden"); + if (hidden_value.has_value()) { + if (hidden_value.value() == "include") { + hidden_ = HiddenFlag::Include; + } else if (hidden_value.value() == "only") { + hidden_ = HiddenFlag::ShowOnly; + } else if (hidden_value.value() == "exclude") { + hidden_ = HiddenFlag::Exclude; + } else { + response.add("usage: /stats?hidden=(include|only|exclude)\n\n"); + return Http::Code::BadRequest; + } + } + const absl::optional format_value = Utility::formatParam(query_); if (format_value.has_value()) { if (format_value.value() == "prometheus") { diff --git a/source/server/admin/stats_params.h b/source/server/admin/stats_params.h index 208bcfa7162e..09b82a96ce04 100644 --- a/source/server/admin/stats_params.h +++ b/source/server/admin/stats_params.h @@ -40,6 +40,12 @@ enum class StatsType { All, }; +enum class HiddenFlag { + Include, // Will include hidden stats along side non-hidden stats + ShowOnly, // Will only show hidden stats and exclude hidden stats + Exclude, // Default behavior. Will exclude all hidden stats +}; + struct StatsParams { /** * Parses the URL's query parameter, populating this. @@ -59,6 +65,7 @@ struct StatsParams { bool prometheus_text_readouts_{false}; bool pretty_{false}; StatsFormat format_{StatsFormat::Text}; + HiddenFlag hidden_{HiddenFlag::Exclude}; std::string filter_string_; std::shared_ptr re2_filter_; Utility::HistogramBucketsMode histogram_buckets_mode_{Utility::HistogramBucketsMode::NoBuckets}; diff --git a/source/server/admin/stats_request.cc b/source/server/admin/stats_request.cc index 954eb1127dbf..181094ff836e 100644 --- a/source/server/admin/stats_request.cc +++ b/source/server/admin/stats_request.cc @@ -183,6 +183,14 @@ template void StatsRequest::populateStatsFromScopes(const Scope return true; } + if (params_.hidden_ == HiddenFlag::Exclude && stat->hidden()) { + return true; + } + + if (params_.hidden_ == HiddenFlag::ShowOnly && !stat->hidden()) { + return true; + } + // Capture the name if we did not early-exit due to used_only -- we'll use // the name for both filtering and for capturing the stat in the map. // stat->name() takes a symbol table lock and builds a string, so we only diff --git a/test/common/stats/allocator_impl_test.cc b/test/common/stats/allocator_impl_test.cc index eea975dcb3ea..38fcb17466b2 100644 --- a/test/common/stats/allocator_impl_test.cc +++ b/test/common/stats/allocator_impl_test.cc @@ -524,6 +524,65 @@ TEST_F(AllocatorImplTest, ForEachSinkedGauge) { EXPECT_EQ(num_iterations, 0); } +TEST_F(AllocatorImplTest, ForEachSinkedGaugeHidden) { + GaugeSharedPtr unhidden_gauge; + GaugeSharedPtr hidden_gauge; + + auto unhidden_stat_name = makeStat(absl::StrCat("unhidden.gauge")); + auto hidden_stat_name = makeStat(absl::StrCat("hidden.gauge")); + + size_t num_gauges = 0; + size_t num_iterations = 0; + + unhidden_gauge = + alloc_.makeGauge(unhidden_stat_name, StatName(), {}, Gauge::ImportMode::Accumulate); + + hidden_gauge = + alloc_.makeGauge(hidden_stat_name, StatName(), {}, Gauge::ImportMode::HiddenAccumulate); + + alloc_.forEachSinkedGauge([&num_gauges](std::size_t size) { num_gauges = size; }, + [&num_iterations, unhidden_stat_name](Gauge& gauge) { + EXPECT_EQ(unhidden_stat_name, gauge.statName()); + num_iterations++; + }); + EXPECT_EQ(num_gauges, 2); + EXPECT_EQ(num_iterations, 1); +} + +TEST_F(AllocatorImplTest, ForEachSinkedGaugeHiddenPredicate) { + std::unique_ptr moved_sink_predicates = + std::make_unique(); + TestUtil::TestSinkPredicates* sink_predicates = moved_sink_predicates.get(); + GaugeSharedPtr unhidden_gauge; + GaugeSharedPtr hidden_gauge; + + alloc_.setSinkPredicates(std::move(moved_sink_predicates)); + + auto unhidden_stat_name = makeStat(absl::StrCat("unhidden.gauge")); + auto hidden_stat_name = makeStat(absl::StrCat("hidden.gauge")); + + sink_predicates->add(unhidden_stat_name); + sink_predicates->add(hidden_stat_name); + + size_t num_gauges = 0; + size_t num_iterations = 0; + + unhidden_gauge = + alloc_.makeGauge(unhidden_stat_name, StatName(), {}, Gauge::ImportMode::Accumulate); + + hidden_gauge = + alloc_.makeGauge(hidden_stat_name, StatName(), {}, Gauge::ImportMode::HiddenAccumulate); + + alloc_.forEachSinkedGauge([&num_gauges](std::size_t size) { num_gauges = size; }, + [&num_iterations, &sink_predicates](Gauge& gauge) { + ++num_iterations; + EXPECT_TRUE(sink_predicates->has(gauge.statName())); + }); + + EXPECT_EQ(num_gauges, 2); + EXPECT_EQ(num_iterations, 2); +} + TEST_F(AllocatorImplTest, ForEachSinkedTextReadout) { std::unique_ptr moved_sink_predicates = std::make_unique(); diff --git a/test/extensions/stats_sinks/open_telemetry/open_telemetry_impl_test.cc b/test/extensions/stats_sinks/open_telemetry/open_telemetry_impl_test.cc index 8d4007efc6fe..5f5b253b63bc 100644 --- a/test/extensions/stats_sinks/open_telemetry/open_telemetry_impl_test.cc +++ b/test/extensions/stats_sinks/open_telemetry/open_telemetry_impl_test.cc @@ -289,13 +289,13 @@ TEST_F(OtlpMetricsFlusherTests, MetricsWithNoAttributes) { TEST_F(OtlpMetricsFlusherTests, GaugeMetric) { OtlpMetricsFlusherImpl flusher(otlpOptions()); - addGaugeToSnapshot("test_guage1", 1); - addGaugeToSnapshot("test_guage2", 2); + addGaugeToSnapshot("test_gauge1", 1); + addGaugeToSnapshot("test_gauge2", 2); MetricsExportRequestSharedPtr metrics = flusher.flush(snapshot_); expectMetricsCount(metrics, 2); - expectGauge(metricAt(0, metrics), getTagExtractedName("test_guage1"), 1); - expectGauge(metricAt(1, metrics), getTagExtractedName("test_guage2"), 2); + expectGauge(metricAt(0, metrics), getTagExtractedName("test_gauge1"), 1); + expectGauge(metricAt(1, metrics), getTagExtractedName("test_gauge2"), 2); } TEST_F(OtlpMetricsFlusherTests, CumulativeCounterMetric) { diff --git a/test/server/admin/prometheus_stats_test.cc b/test/server/admin/prometheus_stats_test.cc index dcf9ab510bd2..18a5b3ab83e2 100644 --- a/test/server/admin/prometheus_stats_test.cc +++ b/test/server/admin/prometheus_stats_test.cc @@ -53,12 +53,12 @@ class PrometheusStatsFormatterTest : public testing::Test { tag_extracted_name_storage.statName(), cluster_tags)); } - void addGauge(const std::string& name, Stats::StatNameTagVector cluster_tags) { + void addGauge(const std::string& name, Stats::StatNameTagVector cluster_tags, + Stats::Gauge::ImportMode import_mode = Stats::Gauge::ImportMode::Accumulate) { Stats::StatNameManagedStorage name_storage(baseName(name, cluster_tags), *symbol_table_); Stats::StatNameManagedStorage tag_extracted_name_storage(name, *symbol_table_); - gauges_.push_back(alloc_.makeGauge(name_storage.statName(), - tag_extracted_name_storage.statName(), cluster_tags, - Stats::Gauge::ImportMode::Accumulate)); + gauges_.push_back(alloc_.makeGauge( + name_storage.statName(), tag_extracted_name_storage.statName(), cluster_tags, import_mode)); } void addTextReadout(const std::string& name, const std::string& value, @@ -81,6 +81,7 @@ class PrometheusStatsFormatterTest : public testing::Test { histogram->setTagExtractedName(name); histogram->setTags(cluster_tags); histogram->used_ = true; + histogram->hidden_ = false; return histogram; } @@ -779,6 +780,56 @@ envoy_cluster_test_1_upstream_rq_time_count{key1="value1",key2="value2"} 7 EXPECT_EQ(expected_output, response.toString()); } +TEST_F(PrometheusStatsFormatterTest, OutputWithHiddenGauge) { + Stats::CustomStatNamespacesImpl custom_namespaces; + + addGauge("cluster.test_cluster_2.upstream_cx_total", + {{makeStat("another_tag_name_3"), makeStat("another_tag_3-value")}}); + addGauge("cluster.test_cluster_2.upstream_cx_total", + {{makeStat("another_tag_name_4"), makeStat("another_tag_4-value")}}, + Stats::Gauge::ImportMode::HiddenAccumulate); + + StatsParams params; + + { + Buffer::OwnedImpl response; + params.hidden_ = HiddenFlag::Exclude; + const uint64_t size = PrometheusStatsFormatter::statsAsPrometheus( + counters_, gauges_, histograms_, textReadouts_, response, params, custom_namespaces); + const std::string expected_output = + R"EOF(# TYPE envoy_cluster_test_cluster_2_upstream_cx_total gauge +envoy_cluster_test_cluster_2_upstream_cx_total{another_tag_name_3="another_tag_3-value"} 0 +)EOF"; + EXPECT_EQ(expected_output, response.toString()); + EXPECT_EQ(1UL, size); + } + { + Buffer::OwnedImpl response; + params.hidden_ = HiddenFlag::ShowOnly; + const uint64_t size = PrometheusStatsFormatter::statsAsPrometheus( + counters_, gauges_, histograms_, textReadouts_, response, params, custom_namespaces); + const std::string expected_output = + R"EOF(# TYPE envoy_cluster_test_cluster_2_upstream_cx_total gauge +envoy_cluster_test_cluster_2_upstream_cx_total{another_tag_name_4="another_tag_4-value"} 0 +)EOF"; + EXPECT_EQ(expected_output, response.toString()); + EXPECT_EQ(1UL, size); + } + { + Buffer::OwnedImpl response; + params.hidden_ = HiddenFlag::Include; + const uint64_t size = PrometheusStatsFormatter::statsAsPrometheus( + counters_, gauges_, histograms_, textReadouts_, response, params, custom_namespaces); + const std::string expected_output = + R"EOF(# TYPE envoy_cluster_test_cluster_2_upstream_cx_total gauge +envoy_cluster_test_cluster_2_upstream_cx_total{another_tag_name_3="another_tag_3-value"} 0 +envoy_cluster_test_cluster_2_upstream_cx_total{another_tag_name_4="another_tag_4-value"} 0 +)EOF"; + EXPECT_EQ(expected_output, response.toString()); + EXPECT_EQ(1UL, size); + } +} + TEST_F(PrometheusStatsFormatterTest, OutputWithUsedOnlyHistogram) { Stats::CustomStatNamespacesImpl custom_namespaces; const std::vector h1_values = {}; diff --git a/test/server/admin/stats_handler_test.cc b/test/server/admin/stats_handler_test.cc index 529f0f0993e3..225525e0b31c 100644 --- a/test/server/admin/stats_handler_test.cc +++ b/test/server/admin/stats_handler_test.cc @@ -416,6 +416,62 @@ TEST_F(AdminStatsFilterTest, HandlerStatsJsonHistogramBucketsCumulative) { EXPECT_THAT(expected_json_used_and_filter, JsonStringEq(code_response.second)); } +TEST_F(AdminStatsFilterTest, HandlerStatsJsonHiddenGauges) { + // Test that hidden=include shows all hidden and non hidden values. + const std::string url_hidden_include = "/stats?gauges&format=json&hidden=include"; + + Stats::Gauge& g1 = + store_->gaugeFromString("hiddenG1", Stats::Gauge::ImportMode::HiddenAccumulate); + g1.inc(); + + Stats::Gauge& g2 = store_->gaugeFromString("nonHiddenG2", Stats::Gauge::ImportMode::Accumulate); + g2.add(2); + + CodeResponse code_response = handlerStats(url_hidden_include); + EXPECT_EQ(Http::Code::OK, code_response.first); + const std::string expected_json_hidden_include = R"EOF({ + "stats": [ + {"name":"hiddenG1", "value":1}, + {"name":"nonHiddenG2", "value":2}, + ] +})EOF"; + EXPECT_THAT(expected_json_hidden_include, JsonStringEq(code_response.second)); + + // Test that hidden-only will not show non-hidden gauges. + const std::string url_hidden_show_only = "/stats?gauges&format=json&hidden=only"; + + code_response = handlerStats(url_hidden_show_only); + EXPECT_EQ(Http::Code::OK, code_response.first); + const std::string expected_json_hidden_show_only = R"EOF({ + "stats": [ + {"name":"hiddenG1", "value":1}, + ] +})EOF"; + EXPECT_THAT(expected_json_hidden_show_only, JsonStringEq(code_response.second)); + + // Test that hidden=exclude will not show hidden gauges. + const std::string url_hidden_exclude = "/stats?gauges&format=json&hidden=exclude"; + + code_response = handlerStats(url_hidden_exclude); + EXPECT_EQ(Http::Code::OK, code_response.first); + const std::string expected_json_hidden_exclude = R"EOF({ + "stats": [ + {"name":"nonHiddenG2", "value":2}, + ] +})EOF"; + + EXPECT_THAT(expected_json_hidden_exclude, JsonStringEq(code_response.second)); +} + +TEST_F(AdminStatsFilterTest, HandlerStatsHiddenInvalid) { + // Test that hidden=(bad inputs) returns error. + const std::string url_hidden_bad_input = "/stats?gauges&format=json&hidden=foo"; + + CodeResponse code_response = handlerStats(url_hidden_bad_input); + EXPECT_EQ(Http::Code::BadRequest, code_response.first); + EXPECT_EQ("usage: /stats?hidden=(include|only|exclude)\n\n", code_response.second); +} + TEST_F(AdminStatsFilterTest, HandlerStatsJsonHistogramBucketsDisjoint) { const std::string url = "/stats?histogram_buckets=disjoint&format=json"; // Set h as prefix to match both histograms. diff --git a/test/server/admin/stats_params_test.cc b/test/server/admin/stats_params_test.cc index cc6d7e787ef7..505893f61559 100644 --- a/test/server/admin/stats_params_test.cc +++ b/test/server/admin/stats_params_test.cc @@ -53,6 +53,23 @@ TEST(StatsParamsTest, ParseParamsFormat) { EXPECT_EQ(Http::Code::BadRequest, params.parse("?format=bogus", response)); } +TEST(StatsParamsTest, ParseParamsHidden) { + Buffer::OwnedImpl response; + StatsParams params; + + EXPECT_EQ(HiddenFlag::Exclude, params.hidden_); + + ASSERT_EQ(Http::Code::OK, params.parse("?hidden=include", response)); + EXPECT_EQ(HiddenFlag::Include, params.hidden_); + ASSERT_EQ(Http::Code::OK, params.parse("?hidden=only", response)); + EXPECT_EQ(HiddenFlag::ShowOnly, params.hidden_); + ASSERT_EQ(Http::Code::OK, params.parse("?hidden=exclude", response)); + EXPECT_EQ(HiddenFlag::Exclude, params.hidden_); + ASSERT_EQ(Http::Code::BadRequest, params.parse("?hidden=foo", response)); + ASSERT_EQ(Http::Code::OK, params.parse("?hidden", response)); + EXPECT_EQ(HiddenFlag::Exclude, params.hidden_); +} + TEST(StatsParamsTest, ParseParamsFilter) { Buffer::OwnedImpl response; diff --git a/test/server/admin/stats_request_test.cc b/test/server/admin/stats_request_test.cc index 23bd46a4e2c1..bf8012662381 100644 --- a/test/server/admin/stats_request_test.cc +++ b/test/server/admin/stats_request_test.cc @@ -38,6 +38,15 @@ class StatsRequestTest : public testing::Test { return std::make_unique(store_, params); } + std::unique_ptr makeHiddenRequest(HiddenFlag hidden, StatsFormat format, + StatsType type) { + StatsParams params; + params.hidden_ = hidden; + params.type_ = type; + params.format_ = format; + return std::make_unique(store_, params); + } + // Executes a request, counting the chunks that were generated. uint32_t iterateChunks(StatsRequest& request, bool drain = true, Http::Code expect_code = Http::Code::OK) { @@ -147,6 +156,27 @@ TEST_F(StatsRequestTest, OneStatUsedOnly) { EXPECT_EQ(0, iterateChunks(*makeRequest(true, StatsFormat::Text, StatsType::All))); } +TEST_F(StatsRequestTest, OneStatHiddenExclude) { + store_.rootScope()->gaugeFromStatName(makeStatName("foo"), + Stats::Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ( + 0, iterateChunks(*makeHiddenRequest(HiddenFlag::Exclude, StatsFormat::Text, StatsType::All))); +} + +TEST_F(StatsRequestTest, OneStatHiddenShowOnly) { + store_.rootScope()->gaugeFromStatName(makeStatName("foo"), + Stats::Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ(1, iterateChunks( + *makeHiddenRequest(HiddenFlag::ShowOnly, StatsFormat::Text, StatsType::All))); +} + +TEST_F(StatsRequestTest, OneStatHiddenInclude) { + store_.rootScope()->gaugeFromStatName(makeStatName("foo"), + Stats::Gauge::ImportMode::HiddenAccumulate); + EXPECT_EQ( + 1, iterateChunks(*makeHiddenRequest(HiddenFlag::Include, StatsFormat::Text, StatsType::All))); +} + TEST_F(StatsRequestTest, OneStatJson) { store_.rootScope()->counterFromStatName(makeStatName("foo")); EXPECT_THAT(response(*makeRequest(false, StatsFormat::Json, StatsType::All)), StartsWith("{")); From 2904bdb496a9ed6a7848ec26630b0f44abaaa82a Mon Sep 17 00:00:00 2001 From: Kevin Baichoo Date: Tue, 6 Jun 2023 16:19:58 -0400 Subject: [PATCH 188/228] TLS Inspector: Capture bytes analyzed distribution. (#27742) * Add a histogram for the tls inspector to capture the amount of data the filter parsed. Signed-off-by: Kevin Baichoo --- changelogs/current.yaml | 7 ++ .../listener_filters/tls_inspector.rst | 53 ++++++++++-- .../listener/tls_inspector/tls_inspector.cc | 83 ++++++++++++------- .../listener/tls_inspector/tls_inspector.h | 10 ++- test/common/stats/stat_test_utility.cc | 4 + test/common/stats/stat_test_utility.h | 3 + .../filters/listener/tls_inspector/BUILD | 1 + .../tls_inspector_integration_test.cc | 10 +++ .../tls_inspector/tls_inspector_test.cc | 45 +++++++++- test/test_common/utility.cc | 15 ++++ test/test_common/utility.h | 8 ++ 11 files changed, 197 insertions(+), 42 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 00ce45b7b76b..39444ae95ea7 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -241,6 +241,13 @@ new_features: added new configuration field :ref:`domain ` to allow for setting rate limit domains on a per-route basis. +- area: tls_inspector + change: | + added histogram ``bytes_processed`` which records the number of bytes of + the tls_inspector processed while analyzing for tls usage. In cases where + the connection uses tls this records the tls client hello size. In cases + where the connection doesn't use tls this records the amount of bytes the + tls_inspector processed until it realized the connection was not using tls. - area: access_log change: | added access log filter :ref:`log_type_filter ` diff --git a/docs/root/configuration/listeners/listener_filters/tls_inspector.rst b/docs/root/configuration/listeners/listener_filters/tls_inspector.rst index b5fdadf4b924..d2a29785eaf9 100644 --- a/docs/root/configuration/listeners/listener_filters/tls_inspector.rst +++ b/docs/root/configuration/listeners/listener_filters/tls_inspector.rst @@ -35,15 +35,50 @@ Statistics This filter has a statistics tree rooted at *tls_inspector* with the following statistics: -.. csv-table:: - :header: Name, Type, Description +.. list-table:: + :header-rows: 1 :widths: 1, 1, 2 - client_hello_too_large, Counter, Total unreasonably large Client Hello received - tls_found, Counter, Total number of times TLS was found - tls_not_found, Counter, Total number of times TLS was not found - alpn_found, Counter, Total number of times `Application-Layer Protocol Negotiation `_ was successful - alpn_not_found, Counter, Total number of times `Application-Layer Protocol Negotiation `_ has failed - sni_found, Counter, Total number of times `Server Name Indication `_ was found - sni_not_found, Counter, Total number of times `Server Name Indication `_ was not found + * - Name + - Type + - Description + + * - client_hello_too_large + - counter + - total unreasonably large client hello received + + * - tls_found + - Counter + - Total number of times TLS was found + + * - tls_not_found + - Counter + - Total number of times TLS was not found + + * - alpn_found + - Counter + - Total number of times `Application-Layer Protocol Negotiation `_ was successful + + * - alpn_not_found + - Counter + - Total number of times `Application-Layer Protocol Negotiation `_ has failed + + * - sni_found + - Counter + - Total number of times `Server Name Indication `_ was found + + * - sni_not_found + - Counter + - Total number of times `Server Name Indication `_ was not found + + * - bytes_processed + - Histogram + - Records sizes which records the number of bytes the tls_inspector processed while analyzing for tls usage. + If the connection uses TLS: this is the size of client hello. If the client hello is too large, then the + recorded value will be 64KiB which is the maximum client hello size. + If the connection does not use TLS: it is the number of bytes processed + until the inspector determined the connection was not using TLS. + If the connection terminates early nothing is recorded if we didn't have + sufficient bytes for either of the cases above. + diff --git a/source/extensions/filters/listener/tls_inspector/tls_inspector.cc b/source/extensions/filters/listener/tls_inspector/tls_inspector.cc index fb78a4fcafd1..31f849087866 100644 --- a/source/extensions/filters/listener/tls_inspector/tls_inspector.cc +++ b/source/extensions/filters/listener/tls_inspector/tls_inspector.cc @@ -26,6 +26,20 @@ namespace Envoy { namespace Extensions { namespace ListenerFilters { namespace TlsInspector { +namespace { + +uint64_t computeClientHelloSize(const BIO* bio, uint64_t prior_bytes_read, + size_t original_bio_length) { + const uint8_t* remaining_buffer; + size_t remaining_bytes; + const int rc = BIO_mem_contents(bio, &remaining_buffer, &remaining_bytes); + ASSERT(rc == 1); + ASSERT(original_bio_length >= remaining_bytes); + const size_t processed_bio_bytes = original_bio_length - remaining_bytes; + return processed_bio_bytes + prior_bytes_read; +} + +} // namespace // Min/max TLS version recognized by the underlying TLS/SSL library. const unsigned Config::TLS_MIN_SUPPORTED_VERSION = TLS1_VERSION; @@ -35,7 +49,8 @@ Config::Config( Stats::Scope& scope, const envoy::extensions::filters::listener::tls_inspector::v3::TlsInspector& proto_config, uint32_t max_client_hello_size) - : stats_{ALL_TLS_INSPECTOR_STATS(POOL_COUNTER_PREFIX(scope, "tls_inspector."))}, + : stats_{ALL_TLS_INSPECTOR_STATS(POOL_COUNTER_PREFIX(scope, "tls_inspector."), + POOL_HISTOGRAM_PREFIX(scope, "tls_inspector."))}, ssl_ctx_(SSL_CTX_new(TLS_with_buffers_method())), enable_ja3_fingerprinting_( PROTOBUF_GET_WRAPPED_OR_DEFAULT(proto_config, enable_ja3_fingerprinting, false)), @@ -130,8 +145,9 @@ Network::FilterStatus Filter::onData(Network::ListenerFilterBuffer& buffer) { if (static_cast(raw_slice.len_) > read_) { const uint8_t* data = static_cast(raw_slice.mem_) + read_; const size_t len = raw_slice.len_ - read_; + const uint64_t bytes_already_processed = read_; read_ = raw_slice.len_; - ParseState parse_state = parseClientHello(data, len); + ParseState parse_state = parseClientHello(data, len, bytes_already_processed); switch (parse_state) { case ParseState::Error: cb_->socket().ioHandle().close(); @@ -148,46 +164,57 @@ Network::FilterStatus Filter::onData(Network::ListenerFilterBuffer& buffer) { return Network::FilterStatus::StopIteration; } -ParseState Filter::parseClientHello(const void* data, size_t len) { - // Ownership is passed to ssl_ in SSL_set_bio() +ParseState Filter::parseClientHello(const void* data, size_t len, + uint64_t bytes_already_processed) { + // Ownership remains here though we pass a reference to it in `SSL_set0_rbio()`. bssl::UniquePtr bio(BIO_new_mem_buf(data, len)); // Make the mem-BIO return that there is more data - // available beyond it's end + // available beyond it's end. BIO_set_mem_eof_return(bio.get(), -1); - SSL_set_bio(ssl_.get(), bio.get(), bio.get()); - bio.release(); + // We only do reading as we abort the handshake early. + SSL_set0_rbio(ssl_.get(), bssl::UpRef(bio).release()); int ret = SSL_do_handshake(ssl_.get()); // This should never succeed because an error is always returned from the SNI callback. ASSERT(ret <= 0); - switch (SSL_get_error(ssl_.get(), ret)) { - case SSL_ERROR_WANT_READ: - if (read_ == config_->maxClientHelloSize()) { - // We've hit the specified size limit. This is an unreasonably large ClientHello; - // indicate failure. - config_->stats().client_hello_too_large_.inc(); - return ParseState::Error; - } - return ParseState::Continue; - case SSL_ERROR_SSL: - if (clienthello_success_) { - config_->stats().tls_found_.inc(); - if (alpn_found_) { - config_->stats().alpn_found_.inc(); + ParseState state = [this, ret]() { + switch (SSL_get_error(ssl_.get(), ret)) { + case SSL_ERROR_WANT_READ: + if (read_ == config_->maxClientHelloSize()) { + // We've hit the specified size limit. This is an unreasonably large ClientHello; + // indicate failure. + config_->stats().client_hello_too_large_.inc(); + return ParseState::Error; + } + return ParseState::Continue; + case SSL_ERROR_SSL: + if (clienthello_success_) { + config_->stats().tls_found_.inc(); + if (alpn_found_) { + config_->stats().alpn_found_.inc(); + } else { + config_->stats().alpn_not_found_.inc(); + } + cb_->socket().setDetectedTransportProtocol("tls"); } else { - config_->stats().alpn_not_found_.inc(); + config_->stats().tls_not_found_.inc(); } - cb_->socket().setDetectedTransportProtocol("tls"); - } else { - config_->stats().tls_not_found_.inc(); + return ParseState::Done; + default: + return ParseState::Error; } - return ParseState::Done; - default: - return ParseState::Error; + }(); + + if (state != ParseState::Continue) { + // Record bytes analyzed as we're done processing. + config_->stats().bytes_processed_.recordValue( + computeClientHelloSize(bio.get(), bytes_already_processed, len)); } + + return state; } // Google GREASE values (https://datatracker.ietf.org/doc/html/rfc8701) diff --git a/source/extensions/filters/listener/tls_inspector/tls_inspector.h b/source/extensions/filters/listener/tls_inspector/tls_inspector.h index ad837c8b7efc..fd463f0234cb 100644 --- a/source/extensions/filters/listener/tls_inspector/tls_inspector.h +++ b/source/extensions/filters/listener/tls_inspector/tls_inspector.h @@ -4,6 +4,7 @@ #include "envoy/event/timer.h" #include "envoy/extensions/filters/listener/tls_inspector/v3/tls_inspector.pb.h" #include "envoy/network/filter.h" +#include "envoy/stats/histogram.h" #include "envoy/stats/scope.h" #include "envoy/stats/stats_macros.h" @@ -19,20 +20,21 @@ namespace TlsInspector { /** * All stats for the TLS inspector. @see stats_macros.h */ -#define ALL_TLS_INSPECTOR_STATS(COUNTER) \ +#define ALL_TLS_INSPECTOR_STATS(COUNTER, HISTOGRAM) \ COUNTER(client_hello_too_large) \ COUNTER(tls_found) \ COUNTER(tls_not_found) \ COUNTER(alpn_found) \ COUNTER(alpn_not_found) \ COUNTER(sni_found) \ - COUNTER(sni_not_found) + COUNTER(sni_not_found) \ + HISTOGRAM(bytes_processed, Bytes) /** * Definition of all stats for the TLS inspector. @see stats_macros.h */ struct TlsInspectorStats { - ALL_TLS_INSPECTOR_STATS(GENERATE_COUNTER_STRUCT) + ALL_TLS_INSPECTOR_STATS(GENERATE_COUNTER_STRUCT, GENERATE_HISTOGRAM_STRUCT) }; enum class ParseState { @@ -83,7 +85,7 @@ class Filter : public Network::ListenerFilter, Logger::LoggablemaxClientHelloSize(); } private: - ParseState parseClientHello(const void* data, size_t len); + ParseState parseClientHello(const void* data, size_t len, uint64_t bytes_already_processed); ParseState onRead(); void onALPN(const unsigned char* data, unsigned int len); void onServername(absl::string_view name); diff --git a/test/common/stats/stat_test_utility.cc b/test/common/stats/stat_test_utility.cc index 1454a8a74a70..73621b20d11c 100644 --- a/test/common/stats/stat_test_utility.cc +++ b/test/common/stats/stat_test_utility.cc @@ -294,6 +294,10 @@ std::vector TestStore::histogramValues(const std::string& name, bool c return copy; } +bool TestStore::histogramRecordedValues(const std::string& name) const { + return histogram_values_map_.contains(name); +} + // TODO(jmarantz): this utility is intended to be used both for unit tests // and fuzz tests. But those have different checking macros, e.g. EXPECT_EQ vs // FUZZ_ASSERT. diff --git a/test/common/stats/stat_test_utility.h b/test/common/stats/stat_test_utility.h index 9112c039754c..5ea1edb97441 100644 --- a/test/common/stats/stat_test_utility.h +++ b/test/common/stats/stat_test_utility.h @@ -149,6 +149,9 @@ class TestStore : public SymbolTableProvider, public IsolatedStoreImpl { GaugeOptConstRef findGaugeByString(const std::string& name) const; HistogramOptConstRef findHistogramByString(const std::string& name) const; std::vector histogramValues(const std::string& name, bool clear); + // Returns whether the given histogram has recorded any value since it was + // created. + bool histogramRecordedValues(const std::string& name) const; protected: ScopeSharedPtr makeScope(StatName name) override; diff --git a/test/extensions/filters/listener/tls_inspector/BUILD b/test/extensions/filters/listener/tls_inspector/BUILD index dfad8b7ec3af..8c2ef09bdddf 100644 --- a/test/extensions/filters/listener/tls_inspector/BUILD +++ b/test/extensions/filters/listener/tls_inspector/BUILD @@ -26,6 +26,7 @@ envoy_cc_test( "//source/common/network:listener_filter_buffer_lib", "//source/extensions/filters/listener/tls_inspector:config", "//source/extensions/filters/listener/tls_inspector:tls_inspector_lib", + "//test/common/stats:stat_test_utility_lib", "//test/mocks/api:api_mocks", "//test/mocks/network:network_mocks", "//test/mocks/stats:stats_mocks", diff --git a/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc b/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc index adf7513e1ded..51a252af2bb2 100644 --- a/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc +++ b/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc @@ -188,8 +188,18 @@ TEST_P(TlsInspectorIntegrationTest, JA3FingerprintIsSet) { /*ssl_options=*/ssl_options, /*curves_list=*/"P-256", /*enable_`ja3`_fingerprinting=*/true); client_->close(Network::ConnectionCloseType::NoFlush); + EXPECT_THAT(waitForAccessLog(listener_access_log_name_), testing::Eq("71d1f47d1125ac53c3c6a4863c087cfe")); + + test_server_->waitUntilHistogramHasSamples("tls_inspector.bytes_processed"); + auto bytes_processed_histogram = test_server_->histogram("tls_inspector.bytes_processed"); + EXPECT_EQ( + TestUtility::readSampleCount(test_server_->server().dispatcher(), *bytes_processed_histogram), + 1); + EXPECT_EQ(static_cast(TestUtility::readSampleSum(test_server_->server().dispatcher(), + *bytes_processed_histogram)), + 115); } INSTANTIATE_TEST_SUITE_P(IpVersions, TlsInspectorIntegrationTest, diff --git a/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc b/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc index e7e423c54300..e9ae319ab3d3 100644 --- a/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc +++ b/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc @@ -4,6 +4,7 @@ #include "source/common/network/listener_filter_buffer_impl.h" #include "source/extensions/filters/listener/tls_inspector/tls_inspector.h" +#include "test/common/stats/stat_test_utility.h" #include "test/extensions/filters/listener/tls_inspector/tls_utility.h" #include "test/mocks/api/mocks.h" #include "test/mocks/network/mocks.h" @@ -83,7 +84,7 @@ class TlsInspectorTest : public testing::TestWithParam os_sys_calls_; TestThreadsafeSingletonInjector os_calls_{&os_sys_calls_}; - Stats::IsolatedStoreImpl store_; + Stats::TestUtil::TestStore store_; ConfigSharedPtr cfg_; std::unique_ptr filter_; Network::MockListenerFilterCallbacks cb_; @@ -145,10 +146,15 @@ TEST_P(TlsInspectorTest, AlpnRegistered) { // trigger the event to copy the client hello message into buffer file_event_callback_(Event::FileReadyType::Read); auto state = filter_->onData(*buffer_); + EXPECT_EQ(Network::FilterStatus::Continue, state); EXPECT_EQ(1, cfg_->stats().tls_found_.value()); EXPECT_EQ(1, cfg_->stats().sni_not_found_.value()); EXPECT_EQ(1, cfg_->stats().alpn_found_.value()); + const std::vector bytes_processed = + store_.histogramValues("tls_inspector.bytes_processed", false); + ASSERT_EQ(1, bytes_processed.size()); + EXPECT_EQ(client_hello.size(), bytes_processed[0]); } // Test with the ClientHello spread over multiple socket reads. @@ -208,6 +214,10 @@ TEST_P(TlsInspectorTest, MultipleReads) { EXPECT_EQ(1, cfg_->stats().tls_found_.value()); EXPECT_EQ(1, cfg_->stats().sni_found_.value()); EXPECT_EQ(1, cfg_->stats().alpn_found_.value()); + const std::vector bytes_processed = + store_.histogramValues("tls_inspector.bytes_processed", false); + ASSERT_EQ(1, bytes_processed.size()); + EXPECT_EQ(client_hello.size(), bytes_processed[0]); } // Test that the filter correctly handles a ClientHello with no extensions present. @@ -276,6 +286,10 @@ TEST_P(TlsInspectorTest, ClientHelloTooBig) { auto state = filter_->onData(*buffer_); EXPECT_EQ(Network::FilterStatus::StopIteration, state); EXPECT_EQ(1, cfg_->stats().client_hello_too_large_.value()); + const std::vector bytes_processed = + store_.histogramValues("tls_inspector.bytes_processed", false); + ASSERT_EQ(1, bytes_processed.size()); + EXPECT_EQ(max_size, bytes_processed[0]); } // Test that the filter sets the `JA3` hash @@ -397,6 +411,35 @@ TEST_P(TlsInspectorTest, NotSsl) { auto state = filter_->onData(*buffer_); EXPECT_EQ(Network::FilterStatus::Continue, state); EXPECT_EQ(1, cfg_->stats().tls_not_found_.value()); + const std::vector bytes_processed = + store_.histogramValues("tls_inspector.bytes_processed", false); + ASSERT_EQ(1, bytes_processed.size()); + EXPECT_EQ(5, bytes_processed[0]); +} + +TEST_P(TlsInspectorTest, EarlyTerminationShouldNotRecordBytesProcessed) { + envoy::extensions::filters::listener::tls_inspector::v3::TlsInspector proto_config; + cfg_ = std::make_shared(*store_.rootScope(), proto_config); + std::vector client_hello = Tls::Test::generateClientHello( + std::get<0>(GetParam()), std::get<1>(GetParam()), "example.com", ""); + + // Clobber half of client_hello so we don't have sufficient bytes to finish inspection. + client_hello.resize(client_hello.size() / 2); + + init(); + mockSysCallForPeek(client_hello); + EXPECT_CALL(socket_, setRequestedServerName(_)).Times(0); + EXPECT_CALL(socket_, setRequestedApplicationProtocols(_)).Times(0); + EXPECT_CALL(socket_, detectedTransportProtocol()).Times(::testing::AnyNumber()); + // Trigger the event to copy the client hello message into buffer + file_event_callback_(Event::FileReadyType::Read); + auto state = filter_->onData(*buffer_); + EXPECT_EQ(Network::FilterStatus::StopIteration, state); + + // Terminate early. + filter_.reset(); + + ASSERT_FALSE(store_.histogramRecordedValues("tls_inspector.bytes_processed")); } } // namespace diff --git a/test/test_common/utility.cc b/test/test_common/utility.cc index f090c095bad5..593745501702 100644 --- a/test/test_common/utility.cc +++ b/test/test_common/utility.cc @@ -285,6 +285,21 @@ uint64_t TestUtility::readSampleCount(Event::Dispatcher& main_dispatcher, return sample_count; } +double TestUtility::readSampleSum(Event::Dispatcher& main_dispatcher, + const Stats::ParentHistogram& histogram) { + // Note: we need to read the sample count from the main thread, to avoid data races. + double sample_sum = 0; + absl::Notification notification; + + main_dispatcher.post([&] { + sample_sum = histogram.cumulativeStatistics().sampleSum(); + notification.Notify(); + }); + notification.WaitForNotification(); + + return sample_sum; +} + std::list TestUtility::makeDnsResponse(const std::list& addresses, std::chrono::seconds ttl) { std::list ret; diff --git a/test/test_common/utility.h b/test/test_common/utility.h index 2995e0d7d843..e5cc0c5cfcd5 100644 --- a/test/test_common/utility.h +++ b/test/test_common/utility.h @@ -328,6 +328,14 @@ class TestUtility { */ static uint64_t readSampleCount(Event::Dispatcher& main_dispatcher, const Stats::ParentHistogram& histogram); + /** + * Read a histogram's sum from the main thread. + * @param store supplies the stats store. + * @param name histogram name. + * @return double the sample sum. + */ + static double readSampleSum(Event::Dispatcher& main_dispatcher, + const Stats::ParentHistogram& histogram); /** * Find a readout in a stats store. From 878d26f3b5ab7bfe3321f6f8d48b51763e9630d6 Mon Sep 17 00:00:00 2001 From: Kuat Date: Tue, 6 Jun 2023 13:21:58 -0700 Subject: [PATCH 189/228] tests: remove additional no_extension_lookup_by_name runtime override in tests (#27642) Signed-off-by: Kuat Yessenov --- test/common/config/BUILD | 1 - .../custom_config_validators_impl_test.cc | 26 ++++----- .../tracing/tracer_manager_impl_test.cc | 16 ++---- .../upstream/cluster_manager_impl_test.cc | 10 ++-- test/common/upstream/upstream_impl_test.cc | 33 ++++------- test/config/utility.cc | 2 +- test/extensions/access_loggers/grpc/BUILD | 1 + .../tcp_grpc_access_log_integration_test.cc | 5 +- test/extensions/clusters/eds/BUILD | 1 - test/extensions/clusters/eds/eds_test.cc | 6 +- .../aws_metadata_fetcher_integration_test.cc | 2 + .../common/dynamic_forward_proxy/BUILD | 1 - .../dns_cache_impl_test.cc | 17 +++--- test/extensions/filters/http/geoip/BUILD | 11 +++- .../filters/http/geoip/config_test.cc | 17 +++--- .../extensions/filters/http/geoip/dummy.proto | 6 ++ .../filters/http/geoip/geoip_filter_test.cc | 4 +- test/extensions/filters/http/geoip/mocks.h | 5 +- .../tls_inspector_integration_test.cc | 2 + .../network/echo/echo_integration_test.cc | 4 ++ .../filters/network/rbac/integration_test.cc | 2 + .../udp_proxy/udp_proxy_integration_test.cc | 2 + .../listener_managers/listener_manager/BUILD | 7 +++ .../listener_manager/config.proto | 15 +++++ .../listener_manager_impl_test.cc | 56 ++++++++----------- .../transport_sockets/proxy_protocol/BUILD | 2 + .../proxy_protocol_integration_test.cc | 54 +++++++++--------- .../transport_sockets/tcp_stats/BUILD | 2 + .../tcp_stats/tcp_stats_integration_test.cc | 4 ++ test/integration/base_integration_test.cc | 3 - .../filter_manager_integration_test.cc | 12 +++- test/integration/http_integration.cc | 3 + .../listener_lds_integration_test.cc | 5 +- .../multiplexed_upstream_integration_test.cc | 6 +- .../socket_interface_integration_test.cc | 2 + .../tcp_conn_pool_integration_test.cc | 1 + test/server/server_test.cc | 12 ---- .../callbacks_stats_sink_bootstrap.yaml | 2 + .../server/stats_sink_bootstrap.yaml | 2 + .../stats_sink_manual_flush_bootstrap.yaml | 2 + 40 files changed, 204 insertions(+), 160 deletions(-) create mode 100644 test/extensions/filters/http/geoip/dummy.proto create mode 100644 test/extensions/listener_managers/listener_manager/config.proto diff --git a/test/common/config/BUILD b/test/common/config/BUILD index dd5035c98579..13aed4619e3d 100644 --- a/test/common/config/BUILD +++ b/test/common/config/BUILD @@ -248,6 +248,5 @@ envoy_cc_test( "//test/mocks/protobuf:protobuf_mocks", "//test/mocks/server:instance_mocks", "//test/test_common:registry_lib", - "//test/test_common:test_runtime_lib", ], ) diff --git a/test/common/config/custom_config_validators_impl_test.cc b/test/common/config/custom_config_validators_impl_test.cc index 8b119603d1d9..f907fedaf238 100644 --- a/test/common/config/custom_config_validators_impl_test.cc +++ b/test/common/config/custom_config_validators_impl_test.cc @@ -3,7 +3,6 @@ #include "test/mocks/protobuf/mocks.h" #include "test/mocks/server/instance.h" #include "test/test_common/registry.h" -#include "test/test_common/test_runtime.h" #include "gtest/gtest.h" @@ -44,11 +43,10 @@ class FakeConfigValidatorFactory : public ConfigValidatorFactory { Envoy::ProtobufTypes::MessagePtr createEmptyConfigProto() override { // Using Struct instead of a custom empty config proto. This is only allowed in tests. - return ProtobufTypes::MessagePtr{new Envoy::ProtobufWkt::Struct()}; + return should_reject_ ? ProtobufTypes::MessagePtr{new Envoy::ProtobufWkt::Struct()} + : ProtobufTypes::MessagePtr{new Envoy::ProtobufWkt::Value()}; } - std::set configTypes() override { return {}; } - std::string name() const override { return absl::StrCat(category(), ".fake_config_validator_", should_reject_ ? "reject" : "accept"); @@ -65,10 +63,7 @@ class CustomConfigValidatorsImplTest : public testing::Test { public: CustomConfigValidatorsImplTest() : factory_accept_(false), factory_reject_(true), register_factory_accept_(factory_accept_), - register_factory_reject_(factory_reject_) { - scoped_runtime_.mergeValues( - {{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - } + register_factory_reject_(factory_reject_) {} static envoy::config::core::v3::TypedExtensionConfig parseConfig(const std::string& config) { envoy::config::core::v3::TypedExtensionConfig proto; @@ -83,12 +78,17 @@ class CustomConfigValidatorsImplTest : public testing::Test { testing::NiceMock validation_visitor_; const testing::NiceMock server_; const std::string type_url_{Envoy::Config::getTypeUrl()}; - TestScopedRuntime scoped_runtime_; - static constexpr char AcceptValidatorConfig[] = - "name: envoy.config.validators.fake_config_validator_accept"; - static constexpr char RejectValidatorConfig[] = - "name: envoy.config.validators.fake_config_validator_reject"; + static constexpr char AcceptValidatorConfig[] = R"EOF( + name: envoy.config.validators.fake_config_validator_accept + typed_config: + "@type": type.googleapis.com/google.protobuf.Value + )EOF"; + static constexpr char RejectValidatorConfig[] = R"EOF( + name: envoy.config.validators.fake_config_validator_reject + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct + )EOF"; }; // Validates that empty config that has no validators is always accepted. diff --git a/test/common/tracing/tracer_manager_impl_test.cc b/test/common/tracing/tracer_manager_impl_test.cc index 75864ff587fb..e9eeb4ec6da2 100644 --- a/test/common/tracing/tracer_manager_impl_test.cc +++ b/test/common/tracing/tracer_manager_impl_test.cc @@ -64,10 +64,9 @@ TEST_F(TracerManagerImplTest, ShouldReturnWhenNoTracingProviderHasBeenConfigured } TEST_F(TracerManagerImplTest, ShouldUseProperTracerFactory) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); envoy::config::trace::v3::Tracing_Http tracing_config; tracing_config.set_name("envoy.tracers.sample"); + tracing_config.mutable_typed_config()->PackFrom(ProtobufWkt::Struct()); auto tracer = tracer_manager_.getOrCreateTracer(&tracing_config); @@ -119,19 +118,16 @@ TEST_F(TracerManagerImplTest, ShouldCacheTracersBasedOnFullConfig) { } TEST_F(TracerManagerImplTest, ShouldFailIfTracerProviderIsUnknown) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); envoy::config::trace::v3::Tracing_Http tracing_config; tracing_config.set_name("invalid"); + tracing_config.mutable_typed_config()->PackFrom(ProtobufWkt::Value()); EXPECT_THROW_WITH_MESSAGE(tracer_manager_.getOrCreateTracer(&tracing_config), EnvoyException, - "Didn't find a registered implementation for name: 'invalid'"); + "Didn't find a registered implementation for 'invalid' " + "with type URL: 'google.protobuf.Value'"); } TEST_F(TracerManagerImplTest, ShouldFailIfProviderSpecificConfigIsNotValid) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - envoy::config::trace::v3::Tracing_Http tracing_config; tracing_config.set_name("envoy.tracers.sample"); tracing_config.mutable_typed_config()->PackFrom(ValueUtil::stringValue("value")); @@ -139,8 +135,8 @@ TEST_F(TracerManagerImplTest, ShouldFailIfProviderSpecificConfigIsNotValid) { ProtobufWkt::Any expected_any_proto; expected_any_proto.PackFrom(ValueUtil::stringValue("value")); EXPECT_THROW_WITH_MESSAGE(tracer_manager_.getOrCreateTracer(&tracing_config), EnvoyException, - fmt::format("Unable to unpack as google.protobuf.Struct: {}", - expected_any_proto.DebugString())); + "Didn't find a registered implementation for 'envoy.tracers.sample' " + "with type URL: 'google.protobuf.Value'"); } class TracerManagerImplCacheTest : public testing::Test { diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index 97a7283a3d00..ce084f9c4a65 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -1028,9 +1028,6 @@ TEST_F(ClusterManagerImplTest, ClusterProvidedLbNotConfigured) { // Verify that multiple load balancing policies can be specified, and Envoy selects the first // policy that it has a factory for. TEST_F(ClusterManagerImplTest, LbPolicyConfig) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - // envoy.load_balancers.custom_lb is registered by linking in // //test/integration/load_balancers:custom_lb_policy. const std::string yaml = fmt::format(R"EOF( @@ -1046,6 +1043,8 @@ TEST_F(ClusterManagerImplTest, LbPolicyConfig) { name: envoy.load_balancers.unknown_lb - typed_extension_config: name: envoy.load_balancers.custom_lb + typed_config: + "@type": type.googleapis.com/test.integration.custom_lb.CustomLbConfig load_assignment: cluster_name: cluster_1 endpoints: @@ -4433,9 +4432,6 @@ class TestUpstreamNetworkFilterConfigFactory // Verify that configured upstream filters are added to client connections. TEST_F(ClusterManagerImplTest, AddUpstreamFilters) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - TestUpstreamNetworkFilterConfigFactory factory; Registry::InjectFactory registry( factory); @@ -4457,6 +4453,8 @@ TEST_F(ClusterManagerImplTest, AddUpstreamFilters) { port_value: 11001 filters: - name: envoy.test.filter + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct )EOF"; create(parseBootstrapFromV3Yaml(yaml)); diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index 49c105eea8b3..b6d23ac41c2e 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -2348,9 +2348,6 @@ TEST_F(StaticClusterImplTest, UnsupportedLBType) { // load_balancing_policy should be used when lb_policy is set to LOAD_BALANCING_POLICY_CONFIG. TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithLbPolicy) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - const std::string yaml = R"EOF( name: staticcluster connect_timeout: 0.25s @@ -2360,6 +2357,8 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithLbPolicy) { policies: - typed_extension_config: name: custom_lb + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct load_assignment: endpoints: - lb_endpoints: @@ -2392,9 +2391,6 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithLbPolicy) { // lb_policy is set to LOAD_BALANCING_POLICY_CONFIG and has no load_balancing_policy. TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithoutConfiguration) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - const std::string yaml = R"EOF( name: staticcluster connect_timeout: 0.25s @@ -2426,9 +2422,6 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithoutConfiguration) { // load_balancing_policy is set and common_lb_config is set. TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithCommonLbConfig) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - const std::string yaml = R"EOF( name: staticcluster connect_timeout: 0.25s @@ -2437,6 +2430,8 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithCommonLbConfig) { policies: - typed_extension_config: name: custom_lb + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct common_lb_config: update_merge_window: 1s load_assignment: @@ -2464,9 +2459,6 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithCommonLbConfig) { // load_balancing_policy is set and some fields in common_lb_config are set. TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithCommonLbConfigAndSpecificFields) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - const std::string yaml = R"EOF( name: staticcluster connect_timeout: 0.25s @@ -2475,6 +2467,8 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithCommonLbConfigAndSpecificFi policies: - typed_extension_config: name: custom_lb + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct common_lb_config: locality_weighted_lb_config: {} load_assignment: @@ -2506,9 +2500,6 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithCommonLbConfigAndSpecificFi // load_balancing_policy is set and lb_subset_config is set. TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithLbSubsetConfig) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - const std::string yaml = R"EOF( name: staticcluster connect_timeout: 0.25s @@ -2517,6 +2508,8 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithLbSubsetConfig) { policies: - typed_extension_config: name: custom_lb + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct lb_subset_config: fallback_policy: ANY_ENDPOINT subset_selectors: @@ -2590,9 +2583,6 @@ TEST_F(StaticClusterImplTest, LbPolicyConfigThrowsExceptionIfNoLbPoliciesFound) // load_balancing_policy should also be used when lb_policy is set to something else besides // LOAD_BALANCING_POLICY_CONFIG. TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithOtherLbPolicy) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - const std::string yaml = R"EOF( name: staticcluster connect_timeout: 0.25s @@ -2602,6 +2592,8 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithOtherLbPolicy) { policies: - typed_extension_config: name: custom_lb + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct load_assignment: endpoints: - lb_endpoints: @@ -2632,9 +2624,6 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithOtherLbPolicy) { // load_balancing_policy should also be used when lb_policy is omitted. TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithoutLbPolicy) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - const std::string yaml = R"EOF( name: staticcluster connect_timeout: 0.25s @@ -2643,6 +2632,8 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithoutLbPolicy) { policies: - typed_extension_config: name: custom_lb + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct load_assignment: endpoints: - lb_endpoints: diff --git a/test/config/utility.cc b/test/config/utility.cc index b9b15c102ad3..f55bcbf0b362 100644 --- a/test/config/utility.cc +++ b/test/config/utility.cc @@ -207,7 +207,7 @@ std::string ConfigHelper::testInspectorFilter() { return R"EOF( name: "envoy.filters.listener.test" typed_config: - "@type": type.googleapis.com/google.protobuf.Struct + "@type": type.googleapis.com/test.integration.filters.TestInspectorFilterConfig )EOF"; } diff --git a/test/extensions/access_loggers/grpc/BUILD b/test/extensions/access_loggers/grpc/BUILD index 38747fdfc134..423c8734457f 100644 --- a/test/extensions/access_loggers/grpc/BUILD +++ b/test/extensions/access_loggers/grpc/BUILD @@ -130,6 +130,7 @@ envoy_extension_cc_test( "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/access_loggers/grpc/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/filters/network/echo/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/network/rbac/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/network/tcp_proxy/v3:pkg_cc_proto", "@envoy_api//envoy/service/accesslog/v3:pkg_cc_proto", diff --git a/test/extensions/access_loggers/grpc/tcp_grpc_access_log_integration_test.cc b/test/extensions/access_loggers/grpc/tcp_grpc_access_log_integration_test.cc index f84a0549a5c8..c962d56706ce 100644 --- a/test/extensions/access_loggers/grpc/tcp_grpc_access_log_integration_test.cc +++ b/test/extensions/access_loggers/grpc/tcp_grpc_access_log_integration_test.cc @@ -1,6 +1,8 @@ #include "envoy/config/bootstrap/v3/bootstrap.pb.h" #include "envoy/config/core/v3/address.pb.h" #include "envoy/extensions/access_loggers/grpc/v3/als.pb.h" +#include "envoy/extensions/filters/network/echo/v3/echo.pb.h" +#include "envoy/extensions/filters/network/echo/v3/echo.pb.validate.h" #include "envoy/extensions/filters/network/rbac/v3/rbac.pb.h" #include "envoy/extensions/filters/network/rbac/v3/rbac.pb.validate.h" #include "envoy/extensions/filters/network/tcp_proxy/v3/tcp_proxy.pb.h" @@ -125,8 +127,9 @@ class TcpGrpcAccessLogIntegrationTest : public Grpc::GrpcClientIntegrationParamT auto* alpn = filter_chain->mutable_filter_chain_match()->add_application_protocols(); *alpn = "envoyalpn"; auto* filter = filter_chain->mutable_filters(0); + envoy::extensions::filters::network::echo::v3::Echo echo; filter->set_name("envoy.filters.network.echo"); - filter->clear_typed_config(); + filter->mutable_typed_config()->PackFrom(echo); }); if (ssl_terminate) { config_helper_.addSslConfig(); diff --git a/test/extensions/clusters/eds/BUILD b/test/extensions/clusters/eds/BUILD index fe0af3d42039..b38d03fe9077 100644 --- a/test/extensions/clusters/eds/BUILD +++ b/test/extensions/clusters/eds/BUILD @@ -30,7 +30,6 @@ envoy_cc_test( "//test/mocks/ssl:ssl_mocks", "//test/mocks/upstream:cluster_manager_mocks", "//test/mocks/upstream:health_checker_mocks", - "//test/test_common:test_runtime_lib", "//test/test_common:utility_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", diff --git a/test/extensions/clusters/eds/eds_test.cc b/test/extensions/clusters/eds/eds_test.cc index a308a65a64a6..3457970f8ae9 100644 --- a/test/extensions/clusters/eds/eds_test.cc +++ b/test/extensions/clusters/eds/eds_test.cc @@ -22,7 +22,6 @@ #include "test/mocks/ssl/mocks.h" #include "test/mocks/upstream/cluster_manager.h" #include "test/mocks/upstream/health_checker.h" -#include "test/test_common/test_runtime.h" #include "test/test_common/utility.h" #include "gmock/gmock.h" @@ -1781,9 +1780,6 @@ TEST_F(EdsLocalityWeightsTest, WeightsPresentWithLocalityWeightedConfig) { // Validate that onConfigUpdate() propagates locality weights to the host set when the cluster uses // load balancing policy extensions. TEST_F(EdsLocalityWeightsTest, WeightsPresentWithLoadBalancingPolicyConfig) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - // envoy.load_balancers.custom_lb is registered by linking in // //test/integration/load_balancers:custom_lb_policy. expectLocalityWeightsPresentForClusterConfig(R"EOF( @@ -1795,6 +1791,8 @@ TEST_F(EdsLocalityWeightsTest, WeightsPresentWithLoadBalancingPolicyConfig) { policies: - typed_extension_config: name: envoy.load_balancers.custom_lb + typed_config: + "@type": type.googleapis.com/test.integration.custom_lb.CustomLbConfig eds_cluster_config: service_name: fare eds_config: diff --git a/test/extensions/common/aws/aws_metadata_fetcher_integration_test.cc b/test/extensions/common/aws/aws_metadata_fetcher_integration_test.cc index 4422cc7d3ac6..6e71984ee8a7 100644 --- a/test/extensions/common/aws/aws_metadata_fetcher_integration_test.cc +++ b/test/extensions/common/aws/aws_metadata_fetcher_integration_test.cc @@ -36,6 +36,8 @@ class AwsMetadataIntegrationTestBase : public ::testing::Test, public BaseIntegr numerator: 100 denominator: HUNDRED - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router codec_type: HTTP1 route_config: virtual_hosts: diff --git a/test/extensions/common/dynamic_forward_proxy/BUILD b/test/extensions/common/dynamic_forward_proxy/BUILD index 5bbcf74c2823..d57b03e6b71d 100644 --- a/test/extensions/common/dynamic_forward_proxy/BUILD +++ b/test/extensions/common/dynamic_forward_proxy/BUILD @@ -28,7 +28,6 @@ envoy_cc_test( "//test/mocks/thread_local:thread_local_mocks", "//test/test_common:registry_lib", "//test/test_common:simulated_time_system_lib", - "//test/test_common:test_runtime_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/common/dynamic_forward_proxy/v3:pkg_cc_proto", diff --git a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc index b33e2ed770b4..212e38eceeb5 100644 --- a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc +++ b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc @@ -18,7 +18,6 @@ #include "test/mocks/thread_local/mocks.h" #include "test/test_common/registry.h" #include "test/test_common/simulated_time_system.h" -#include "test/test_common/test_runtime.h" #include "test/test_common/utility.h" using testing::AtLeast; @@ -1337,9 +1336,6 @@ TEST(UtilityTest, PrepareDnsRefreshStrategy) { } TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - auto* time_source = new NiceMock(); context_.dispatcher_.time_system_.reset(time_source); @@ -1361,7 +1357,10 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { })); Registry::InjectFactory injector(factory); - config_.mutable_key_value_config()->mutable_config()->set_name("mock_key_value_store_factory"); + auto* key_value_config = config_.mutable_key_value_config()->mutable_config(); + key_value_config->set_name("mock_key_value_store_factory"); + key_value_config->mutable_typed_config()->PackFrom( + envoy::extensions::key_value::file_based::v3::FileBasedKeyValueStoreConfig()); initialize(); InSequence s; @@ -1471,9 +1470,6 @@ TEST_F(DnsCacheImplTest, ResolveSuccessWithCaching) { } TEST_F(DnsCacheImplTest, CacheLoad) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - auto* time_source = new NiceMock(); context_.dispatcher_.time_system_.reset(time_source); @@ -1501,7 +1497,10 @@ TEST_F(DnsCacheImplTest, CacheLoad) { return ret; })); Registry::InjectFactory injector(factory); - config_.mutable_key_value_config()->mutable_config()->set_name("mock_key_value_store_factory"); + auto* key_value_config = config_.mutable_key_value_config()->mutable_config(); + key_value_config->set_name("mock_key_value_store_factory"); + key_value_config->mutable_typed_config()->PackFrom( + envoy::extensions::key_value::file_based::v3::FileBasedKeyValueStoreConfig()); initialize(); ASSERT(store != nullptr); diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index 98b555a13e5d..03ce9172a8ff 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -1,6 +1,7 @@ load( "//bazel:envoy_build_system.bzl", "envoy_package", + "envoy_proto_library", ) load( "//test/extensions:extensions_build_system.bzl", @@ -13,6 +14,11 @@ licenses(["notice"]) # Apache 2 envoy_package() +envoy_proto_library( + name = "dummy", + srcs = ["dummy.proto"], +) + envoy_extension_cc_test( name = "config_test", size = "small", @@ -51,7 +57,10 @@ envoy_extension_cc_mock( name = "geoip_mocks", hdrs = ["mocks.h"], extension_names = ["envoy.filters.http.geoip"], - deps = ["//source/extensions/filters/http/geoip:provider_config"], + deps = [ + ":dummy_cc_proto", + "//source/extensions/filters/http/geoip:provider_config", + ], ) envoy_extension_cc_test_library( diff --git a/test/extensions/filters/http/geoip/config_test.cc b/test/extensions/filters/http/geoip/config_test.cc index 6b0471db7460..7c27734d1b91 100644 --- a/test/extensions/filters/http/geoip/config_test.cc +++ b/test/extensions/filters/http/geoip/config_test.cc @@ -94,7 +94,6 @@ MATCHER_P(HasAnonGeoHeadersSize, expected_size, "") { TEST(GeoipFilterConfigTest, GeoipFilterDefaultValues) { TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); DummyGeoipProviderFactory dummy_factory; Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( @@ -102,7 +101,8 @@ TEST(GeoipFilterConfigTest, GeoipFilterDefaultValues) { city: "x-geo-city" provider: name: "envoy.geoip_providers.dummy" - typed_config: {} + typed_config: + "@type": type.googleapis.com/test.extensions.filters.http.geoip.DummyProvider )EOF"; GeoipFilterConfig filter_config; TestUtility::loadFromYaml(filter_config_yaml, filter_config); @@ -120,7 +120,6 @@ TEST(GeoipFilterConfigTest, GeoipFilterDefaultValues) { TEST(GeoipFilterConfigTest, GeoipFilterConfigWithCorrectProto) { TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); DummyGeoipProviderFactory dummy_factory; Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( @@ -132,7 +131,8 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigWithCorrectProto) { anon_vpn: "x-anon-vpn" provider: name: "envoy.geoip_providers.dummy" - typed_config: {} + typed_config: + "@type": type.googleapis.com/test.extensions.filters.http.geoip.DummyProvider )EOF"; GeoipFilterConfig filter_config; TestUtility::loadFromYaml(filter_config_yaml, filter_config); @@ -151,14 +151,14 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigWithCorrectProto) { TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingGeoHeaders) { TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); DummyGeoipProviderFactory dummy_factory; Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( xff_config: xff_num_trusted_hops: 0 provider: - name: "envoy.geoip_providers.dummy" + typed_config: + "@type": type.googleapis.com/test.extensions.filters.http.geoip.DummyProvider )EOF"; GeoipFilterConfig filter_config; @@ -173,7 +173,6 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingGeoHeaders) { TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingProvider) { TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); DummyGeoipProviderFactory dummy_factory; Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( @@ -194,7 +193,6 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingProvider) { TEST(GeoipFilterConfigTest, GeoipFilterConfigUnknownProvider) { TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); DummyGeoipProviderFactory dummy_factory; Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( @@ -213,7 +211,8 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigUnknownProvider) { EXPECT_THROW_WITH_MESSAGE( factory.createFilterFactoryFromProtoTyped(filter_config, "geoip", context), Envoy::EnvoyException, - "Didn't find a registered implementation for name: 'envoy.geoip_providers.unknown'"); + "Didn't find a registered implementation for 'envoy.geoip_providers.unknown' with type URL: " + "''"); } } // namespace diff --git a/test/extensions/filters/http/geoip/dummy.proto b/test/extensions/filters/http/geoip/dummy.proto new file mode 100644 index 000000000000..ed0e15d29275 --- /dev/null +++ b/test/extensions/filters/http/geoip/dummy.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +package test.extensions.filters.http.geoip; + +message DummyProvider { +} diff --git a/test/extensions/filters/http/geoip/geoip_filter_test.cc b/test/extensions/filters/http/geoip/geoip_filter_test.cc index 2dfa2697077e..035827901bc6 100644 --- a/test/extensions/filters/http/geoip/geoip_filter_test.cc +++ b/test/extensions/filters/http/geoip/geoip_filter_test.cc @@ -59,8 +59,6 @@ class GeoipFilterTest : public testing::Test { void initializeProviderFactory() { TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues( - {{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); Registry::InjectFactory registered(*dummy_factory_); } @@ -90,6 +88,8 @@ TEST_F(GeoipFilterTest, NoXffSuccessfulLookup) { city: "x-geo-city" provider: name: "envoy.geoip_providers.dummy" + typed_config: + "@type": type.googleapis.com/test.extensions.filters.http.geoip.DummyProvider )EOF"; initializeFilter(external_request_yaml); Http::TestRequestHeaderMapImpl request_headers; diff --git a/test/extensions/filters/http/geoip/mocks.h b/test/extensions/filters/http/geoip/mocks.h index 7fb49f398f34..ffc2c361d9ec 100644 --- a/test/extensions/filters/http/geoip/mocks.h +++ b/test/extensions/filters/http/geoip/mocks.h @@ -1,5 +1,8 @@ #include "source/extensions/filters/http/geoip/geoip_provider_config.h" +#include "test/extensions/filters/http/geoip/dummy.pb.h" +#include "test/extensions/filters/http/geoip/dummy.pb.validate.h" + #include "gmock/gmock.h" namespace Envoy { @@ -27,7 +30,7 @@ class DummyGeoipProviderFactory : public GeoipProviderFactory { std::string name() const override { return "envoy.geoip_providers.dummy"; } ProtobufTypes::MessagePtr createEmptyConfigProto() override { - return std::make_unique(); + return std::make_unique(); } private: diff --git a/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc b/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc index 51a252af2bb2..d36447a068ba 100644 --- a/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc +++ b/test/extensions/filters/listener/tls_inspector/tls_inspector_integration_test.cc @@ -30,6 +30,8 @@ class TlsInspectorIntegrationTest : public testing::TestWithParam(); + return std::make_unique< + test::extensions::listener_managers::listener_manager::NonTerminalFilter>(); } std::string name() const override { return "non_terminal"; } }; TEST_P(ListenerManagerImplWithRealFiltersTest, TerminalNotLast) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - NonTerminalFilterFactory filter; Registry::InjectFactory registered(filter); @@ -621,6 +619,8 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, TerminalNotLast) { filter_chains: - filters: - name: non_terminal + typed_config: + "@type": type.googleapis.com/test.extensions.listener_managers.listener_manager.NonTerminalFilter name: foo )EOF"; @@ -680,9 +680,8 @@ class TestStatsConfigFactory : public Configuration::NamedNetworkFilterConfigFac } ProtobufTypes::MessagePtr createEmptyConfigProto() override { - // Using Struct instead of a custom per-filter empty config proto - // This is only allowed in tests. - return std::make_unique(); + return std::make_unique< + test::extensions::listener_managers::listener_manager::TestStatsFilter>(); } std::string name() const override { return "stats_test"; } @@ -700,9 +699,6 @@ class TestStatsConfigFactory : public Configuration::NamedNetworkFilterConfigFac }; TEST_P(ListenerManagerImplWithRealFiltersTest, StatsScopeTest) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - TestStatsConfigFactory filter; Registry::InjectFactory registered(filter); @@ -715,6 +711,8 @@ bind_to_port: false filter_chains: - filters: - name: stats_test + typed_config: + "@type": type.googleapis.com/test.extensions.listener_managers.listener_manager.TestStatsFilter name: foo )EOF"; @@ -728,9 +726,6 @@ bind_to_port: false } TEST_P(ListenerManagerImplWithRealFiltersTest, UsingAddressAsStatsPrefixForMultipleAddresses) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - TestStatsConfigFactory filter; Registry::InjectFactory registered(filter); @@ -748,6 +743,8 @@ bind_to_port: false filter_chains: - filters: - name: stats_test + typed_config: + "@type": type.googleapis.com/test.extensions.listener_managers.listener_manager.TestStatsFilter name: foo )EOF"; @@ -5919,18 +5916,14 @@ class OriginalDstTestConfigFactory : public Configuration::NamedListenerFilterCo } ProtobufTypes::MessagePtr createEmptyConfigProto() override { - // Using Struct instead of a custom per-filter empty config proto - // This is only allowed in tests. - return std::make_unique(); + return std::make_unique< + test::extensions::listener_managers::listener_manager::OriginalDstTestFilter>(); } std::string name() const override { return "test.listener.original_dst"; } }; TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - #ifdef SOL_IP OriginalDstTestConfigFactory factory; Registry::InjectFactory registration(factory); @@ -5944,6 +5937,8 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { traffic_direction: OUTBOUND listener_filters: - name: "test.listener.original_dst" + typed_config: + "@type": type.googleapis.com/test.extensions.listener_managers.listener_manager.OriginalDstTestFilter )EOF", Network::Address::IpVersion::v4); @@ -5988,9 +5983,6 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterOutbound) { } TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - #if defined(WIN32) && defined(SOL_IP) OriginalDstTestConfigFactory factory; Registry::InjectFactory registration(factory); @@ -6004,6 +5996,8 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) traffic_direction: OUTBOUND listener_filters: - name: "test.listener.original_dst" + typed_config: + "@type": type.googleapis.com/test.extensions.listener_managers.listener_manager.OriginalDstTestFilter )EOF", Network::Address::IpVersion::v4); @@ -6043,9 +6037,6 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstFilterStopsIteration) } TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterInbound) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - #ifdef SOL_IP OriginalDstTestConfigFactory factory; Registry::InjectFactory registration(factory); @@ -6059,6 +6050,8 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterInbound) { traffic_direction: INBOUND listener_filters: - name: "test.listener.original_dst" + typed_config: + "@type": type.googleapis.com/test.extensions.listener_managers.listener_manager.OriginalDstTestFilter )EOF", Network::Address::IpVersion::v4); @@ -6123,16 +6116,13 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterIPv6) { } ProtobufTypes::MessagePtr createEmptyConfigProto() override { - // Using Struct instead of a custom per-filter empty config proto - // This is only allowed in tests. - return std::make_unique(); + return std::make_unique< + test::extensions::listener_managers::listener_manager::OriginalDstTestIPv6Filter>(); } std::string name() const override { return "test.listener.original_dstipv6"; } }; - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); OriginalDstTestConfigFactory factory; Registry::InjectFactory registration(factory); @@ -6144,6 +6134,8 @@ TEST_P(ListenerManagerImplWithRealFiltersTest, OriginalDstTestFilterIPv6) { name: foo listener_filters: - name: "test.listener.original_dstipv6" + typed_config: + "@type": type.googleapis.com/test.extensions.listener_managers.listener_manager.OriginalDstTestIPv6Filter )EOF", Network::Address::IpVersion::v6); diff --git a/test/extensions/transport_sockets/proxy_protocol/BUILD b/test/extensions/transport_sockets/proxy_protocol/BUILD index d615d59ce61c..7311e817b101 100644 --- a/test/extensions/transport_sockets/proxy_protocol/BUILD +++ b/test/extensions/transport_sockets/proxy_protocol/BUILD @@ -38,10 +38,12 @@ envoy_extension_cc_test( "//source/extensions/health_checkers/http:health_checker_lib", "//source/extensions/health_checkers/tcp:health_checker_lib", "//source/extensions/transport_sockets/proxy_protocol:upstream_config", + "//source/extensions/transport_sockets/raw_buffer:config", "//test/integration:http_integration_lib", "//test/integration:integration_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/listener/proxy_protocol/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/transport_sockets/proxy_protocol/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/transport_sockets/raw_buffer/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc b/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc index af6675d5f3fe..f7c11c24359c 100644 --- a/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc +++ b/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc @@ -3,6 +3,8 @@ #include "envoy/config/core/v3/proxy_protocol.pb.h" #include "envoy/extensions/filters/listener/proxy_protocol/v3/proxy_protocol.pb.h" #include "envoy/extensions/transport_sockets/proxy_protocol/v3/upstream_proxy_protocol.pb.h" +#include "envoy/extensions/transport_sockets/raw_buffer/v3/raw_buffer.pb.h" +#include "envoy/extensions/transport_sockets/raw_buffer/v3/raw_buffer.pb.validate.h" #include "test/integration/http_integration.h" #include "test/integration/integration.h" @@ -24,10 +26,10 @@ class ProxyProtocolTcpIntegrationTest : public testing::TestWithParammutable_clusters(0)->mutable_transport_socket(); transport_socket->set_name("envoy.transport_sockets.upstream_proxy_protocol"); envoy::config::core::v3::TransportSocket inner_socket; - inner_socket.set_name(inner_socket_); + if (inner_tls_) { + envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext tls; + inner_socket.set_name("tls"); + inner_socket.mutable_typed_config()->PackFrom(tls); + } else { + envoy::extensions::transport_sockets::raw_buffer::v3::RawBuffer raw_buffer; + inner_socket.set_name("raw"); + inner_socket.mutable_typed_config()->PackFrom(raw_buffer); + } envoy::config::core::v3::ProxyProtocolConfig proxy_proto_config; proxy_proto_config.set_version(version_); envoy::extensions::transport_sockets::proxy_protocol::v3::ProxyProtocolUpstreamTransport @@ -70,7 +80,7 @@ class ProxyProtocolTcpIntegrationTest : public testing::TestWithParam void { std::string observed_data; @@ -187,8 +194,7 @@ TEST_P(ProxyProtocolTcpIntegrationTest, TestProxyProtocolHealthCheck) { // Test sending proxy protocol v2 TEST_P(ProxyProtocolTcpIntegrationTest, TestV2ProxyProtocol) { - setup(envoy::config::core::v3::ProxyProtocolConfig::V2, false, - "envoy.transport_sockets.raw_buffer"); + setup(envoy::config::core::v3::ProxyProtocolConfig::V2, false, false); initialize(); auto listener_port = lookupPort("listener_0"); @@ -246,11 +252,9 @@ class ProxyProtocolHttpIntegrationTest : public testing::TestWithParammutable_clusters(0)->mutable_transport_socket(); transport_socket->set_name("envoy.transport_sockets.upstream_proxy_protocol"); envoy::config::core::v3::TransportSocket inner_socket; - inner_socket.set_name(inner_socket_); + envoy::extensions::transport_sockets::raw_buffer::v3::RawBuffer raw_buffer; + inner_socket.set_name("raw"); + inner_socket.mutable_typed_config()->PackFrom(raw_buffer); envoy::config::core::v3::ProxyProtocolConfig proxy_proto_config; proxy_proto_config.set_version(version_); envoy::extensions::transport_sockets::proxy_protocol::v3::ProxyProtocolUpstreamTransport @@ -289,7 +295,6 @@ class ProxyProtocolHttpIntegrationTest : public testing::TestWithParam void { std::string observed_data; @@ -443,7 +445,9 @@ class ProxyProtocolTLVsIntegrationTest : public testing::TestWithParammutable_clusters(0)->mutable_transport_socket(); transport_socket->set_name("envoy.transport_sockets.upstream_proxy_protocol"); envoy::config::core::v3::TransportSocket inner_socket; - inner_socket.set_name("envoy.transport_sockets.raw_buffer"); + envoy::extensions::transport_sockets::raw_buffer::v3::RawBuffer raw_buffer; + inner_socket.set_name("raw"); + inner_socket.mutable_typed_config()->PackFrom(raw_buffer); envoy::config::core::v3::ProxyProtocolConfig proxy_protocol; proxy_protocol.set_version(envoy::config::core::v3::ProxyProtocolConfig::V2); diff --git a/test/extensions/transport_sockets/tcp_stats/BUILD b/test/extensions/transport_sockets/tcp_stats/BUILD index bbabcbb0efb2..67f79849bf86 100644 --- a/test/extensions/transport_sockets/tcp_stats/BUILD +++ b/test/extensions/transport_sockets/tcp_stats/BUILD @@ -36,9 +36,11 @@ envoy_extension_cc_test( extension_names = ["envoy.transport_sockets.tcp_stats"], deps = [ "//source/extensions/filters/network/tcp_proxy:config", + "//source/extensions/transport_sockets/raw_buffer:config", "//source/extensions/transport_sockets/tcp_stats:config", "//test/integration:http_integration_lib", "//test/integration:integration_lib", + "@envoy_api//envoy/extensions/transport_sockets/raw_buffer/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/transport_sockets/tcp_stats/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/transport_sockets/tcp_stats/tcp_stats_integration_test.cc b/test/extensions/transport_sockets/tcp_stats/tcp_stats_integration_test.cc index 2b8d37ee37e2..47f8b59c1608 100644 --- a/test/extensions/transport_sockets/tcp_stats/tcp_stats_integration_test.cc +++ b/test/extensions/transport_sockets/tcp_stats/tcp_stats_integration_test.cc @@ -1,4 +1,6 @@ #if defined(__linux__) +#include "envoy/extensions/transport_sockets/raw_buffer/v3/raw_buffer.pb.h" +#include "envoy/extensions/transport_sockets/raw_buffer/v3/raw_buffer.pb.validate.h" #include "envoy/extensions/transport_sockets/tcp_stats/v3/tcp_stats.pb.h" #include "test/integration/integration.h" @@ -18,6 +20,8 @@ class TcpStatsSocketIntegrationTest : public testing::TestWithParamPackFrom(raw_buffer); envoy::extensions::transport_sockets::tcp_stats::v3::Config proto_config; proto_config.mutable_transport_socket()->MergeFrom(inner_socket); diff --git a/test/integration/base_integration_test.cc b/test/integration/base_integration_test.cc index 5a2bbfa161fa..0e767fb33833 100644 --- a/test/integration/base_integration_test.cc +++ b/test/integration/base_integration_test.cc @@ -74,9 +74,6 @@ BaseIntegrationTest::BaseIntegrationTest(const InstanceConstSharedPtrFn& upstrea })); ON_CALL(factory_context_.server_context_, api()).WillByDefault(ReturnRef(*api_)); ON_CALL(factory_context_, statsScope()).WillByDefault(ReturnRef(*stats_store_.rootScope())); - // Allow extension lookup by name in the integration tests. - config_helper_.addRuntimeOverride("envoy.reloadable_features.no_extension_lookup_by_name", - "false"); #ifndef ENVOY_ADMIN_FUNCTIONALITY config_helper_.addConfigModifier( diff --git a/test/integration/filter_manager_integration_test.cc b/test/integration/filter_manager_integration_test.cc index cfa5cdccd74c..8d758b288751 100644 --- a/test/integration/filter_manager_integration_test.cc +++ b/test/integration/filter_manager_integration_test.cc @@ -420,7 +420,10 @@ class InjectDataToFilterChainIntegrationTest tick_interval_ms: 1 max_chunk_length: 5 )EOF" - : ""; + : R"EOF( + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct + )EOF"; } }; @@ -434,6 +437,8 @@ class InjectDataWithEchoFilterIntegrationTest : public InjectDataToFilterChainIn filter_chains: filters: - name: envoy.filters.network.echo + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.echo.v3.Echo )EOF"); } @@ -617,7 +622,10 @@ class InjectDataWithHttpConnectionManagerIntegrationTest tick_interval_ms: 1 max_chunk_length: 10 )EOF" - : ""; + : R"EOF( + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct + )EOF"; } }; diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc index 7dbb1dd7e1be..802a4a0391be 100644 --- a/test/integration/http_integration.cc +++ b/test/integration/http_integration.cc @@ -341,6 +341,9 @@ HttpIntegrationTest::HttpIntegrationTest(Http::CodecType downstream_protocol, // lookupPort calls. config_helper_.renameListener("http"); config_helper_.setClientCodec(typeToCodecType(downstream_protocol_)); + // Allow extension lookup by name in the integration tests. + config_helper_.addRuntimeOverride("envoy.reloadable_features.no_extension_lookup_by_name", + "false"); } void HttpIntegrationTest::useAccessLog( diff --git a/test/integration/listener_lds_integration_test.cc b/test/integration/listener_lds_integration_test.cc index d72316ad2fcc..215dd438d70f 100644 --- a/test/integration/listener_lds_integration_test.cc +++ b/test/integration/listener_lds_integration_test.cc @@ -1652,8 +1652,9 @@ class RebalancerTest : public testing::TestWithParamset_value(true); // Note that the below original_dst is replaced by FakeOriginalDstListenerFilter at the // link time. - src_listener_config.add_listener_filters()->set_name( - "envoy.filters.listener.original_dst"); + auto& filter = *src_listener_config.add_listener_filters(); + filter.set_name("envoy.filters.listener.original_dst"); + filter.mutable_typed_config()->PackFrom(ProtobufWkt::Struct()); auto& virtual_listener_config = *bootstrap.mutable_static_resources()->add_listeners(); virtual_listener_config = src_listener_config; virtual_listener_config.mutable_use_original_dst()->set_value(false); diff --git a/test/integration/multiplexed_upstream_integration_test.cc b/test/integration/multiplexed_upstream_integration_test.cc index cd532484a67d..1c21629e5982 100644 --- a/test/integration/multiplexed_upstream_integration_test.cc +++ b/test/integration/multiplexed_upstream_integration_test.cc @@ -888,7 +888,6 @@ TEST_P(MultiplexedUpstreamIntegrationTest, UpstreamDisconnectDuringEarlyData) { if (upstreamProtocol() != Http::CodecType::HTTP3) { return; } - Runtime::maybeSetRuntimeGuard("envoy.reloadable_features.no_extension_lookup_by_name", false); // Register and config this factory to control upstream QUIC handshakes. QuicFailHandshakeCryptoServerStreamFactory crypto_stream_factory; @@ -897,8 +896,9 @@ TEST_P(MultiplexedUpstreamIntegrationTest, UpstreamDisconnectDuringEarlyData) { crypto_stream_factory.setFailHandshake(false); envoy::config::listener::v3::QuicProtocolOptions options; - options.mutable_crypto_stream_config()->set_name( - "envoy.quic.crypto_stream.server.fail_handshake"); + auto* crypto_stream_config = options.mutable_crypto_stream_config(); + crypto_stream_config->set_name("envoy.quic.crypto_stream.server.fail_handshake"); + crypto_stream_config->mutable_typed_config()->PackFrom(ProtobufWkt::Struct()); mergeOptions(options); initialize(); diff --git a/test/integration/socket_interface_integration_test.cc b/test/integration/socket_interface_integration_test.cc index 9c19b388bbd2..d3c6ebda926a 100644 --- a/test/integration/socket_interface_integration_test.cc +++ b/test/integration/socket_interface_integration_test.cc @@ -40,6 +40,8 @@ default_socket_interface: "envoy.extensions.network.socket_interface.default_soc descriptors: [{"key": "foo", "value": "bar"}] filters: name: envoy.filters.network.echo + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.echo.v3.Echo )EOF"); } }; diff --git a/test/integration/tcp_conn_pool_integration_test.cc b/test/integration/tcp_conn_pool_integration_test.cc index e353244f2203..dc1ee5ed0b86 100644 --- a/test/integration/tcp_conn_pool_integration_test.cc +++ b/test/integration/tcp_conn_pool_integration_test.cc @@ -122,6 +122,7 @@ class TcpConnPoolIntegrationTest : public testing::TestWithParam registered(factory); @@ -790,9 +787,6 @@ TEST_P(ServerStatsTest, FlushStats) { } TEST_P(ServerInstanceImplTest, FlushStatsOnAdmin) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - CustomStatsSinkFactory factory; Registry::InjectFactory registered(factory); auto server_thread = @@ -819,9 +813,6 @@ TEST_P(ServerInstanceImplTest, FlushStatsOnAdmin) { } TEST_P(ServerInstanceImplTest, ConcurrentFlushes) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - CustomStatsSinkFactory factory; Registry::InjectFactory registered(factory); @@ -1580,9 +1571,6 @@ class CallbacksStatsSinkFactory : public Server::Configuration::StatsSinkFactory // lifecycle callback is also used to ensure that the cluster update callback is freed during // Server::Instance's destruction. See issue #9292 for more details. TEST_P(ServerInstanceImplTest, CallbacksStatsSinkTest) { - TestScopedRuntime scoped_runtime; - scoped_runtime.mergeValues({{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); - CallbacksStatsSinkFactory factory; Registry::InjectFactory registered(factory); diff --git a/test/server/test_data/server/callbacks_stats_sink_bootstrap.yaml b/test/server/test_data/server/callbacks_stats_sink_bootstrap.yaml index 03fe2ae33da4..e11dcf8ea72a 100644 --- a/test/server/test_data/server/callbacks_stats_sink_bootstrap.yaml +++ b/test/server/test_data/server/callbacks_stats_sink_bootstrap.yaml @@ -16,4 +16,6 @@ admin: port_value: 0 stats_sinks: - name: envoy.callbacks_stats_sink + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct stats_flush_interval: 1s diff --git a/test/server/test_data/server/stats_sink_bootstrap.yaml b/test/server/test_data/server/stats_sink_bootstrap.yaml index 9e94fa854637..5ddf93b46e39 100644 --- a/test/server/test_data/server/stats_sink_bootstrap.yaml +++ b/test/server/test_data/server/stats_sink_bootstrap.yaml @@ -16,4 +16,6 @@ admin: port_value: 0 stats_sinks: - name: envoy.custom_stats_sink + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct stats_flush_interval: 1s diff --git a/test/server/test_data/server/stats_sink_manual_flush_bootstrap.yaml b/test/server/test_data/server/stats_sink_manual_flush_bootstrap.yaml index 47d41309d00f..517aeade1a61 100644 --- a/test/server/test_data/server/stats_sink_manual_flush_bootstrap.yaml +++ b/test/server/test_data/server/stats_sink_manual_flush_bootstrap.yaml @@ -16,5 +16,7 @@ admin: port_value: 0 stats_sinks: - name: envoy.custom_stats_sink + typed_config: + "@type": type.googleapis.com/google.protobuf.Struct stats_flush_on_admin: true enable_dispatcher_stats: true From c127fe34cba8f8228c7a3d21da628e02622db6c4 Mon Sep 17 00:00:00 2001 From: Joshua Marantz Date: Tue, 6 Jun 2023 17:03:51 -0400 Subject: [PATCH 190/228] admin: add histogram rendering for html mode. (#27468) Commit Message: Renders histograms in the stats HTML view. Screenshot: Screenshot 2023-05-29 at 11 39 15 PM This is the next phase in https://github.com/envoyproxy/envoy/pull/26472 -- remaining phases are further refactors, as well as sorting histograms by change-count for active-html mode, and make web navigation work better. This includes unit tests for the new histogram rendering, as well as a mechanism to render histograms.js on its own. Additional Description: Risk Level: low Testing: //test/..., test/integration/admin_html/web_test.sh for browser-based tests on FF, and manually ran on Chrome as well. Docs Changes: n/a -- the histograms were previously rendered as text with format=html; now they are rendered graphically, but detail about this is not in the docs currently. Release Notes: Platform Specific Features: Signed-off-by: Joshua Marantz --- source/server/admin/admin_html_util.cc | 4 +- source/server/admin/html/BUILD | 4 +- source/server/admin/html/active_stats.js | 18 +- source/server/admin/html/admin.css | 116 ++++ .../server/admin/html/generate_admin_html.sh | 16 + source/server/admin/html/histograms.js | 628 ++++++++++++++++++ source/server/admin/stats_handler.cc | 46 +- source/server/admin/stats_html_render.cc | 30 +- source/server/admin/stats_html_render.h | 15 +- test/integration/admin_html/BUILD | 1 + .../admin_html/active_stats_test.js | 4 +- .../admin_html/histograms_test.html | 9 + .../integration/admin_html/histograms_test.js | 154 +++++ test/integration/admin_html/test_server.cc | 13 +- .../admin_html/test_server_test.sh | 1 + test/integration/admin_html/web_test.html | 2 + test/integration/admin_html/web_test.js | 27 + test/server/admin/stats_html_render_test.cc | 6 +- 18 files changed, 1047 insertions(+), 47 deletions(-) create mode 100644 source/server/admin/html/histograms.js create mode 100644 test/integration/admin_html/histograms_test.html create mode 100644 test/integration/admin_html/histograms_test.js diff --git a/source/server/admin/admin_html_util.cc b/source/server/admin/admin_html_util.cc index a7ba82c11d13..410e429e6d74 100644 --- a/source/server/admin/admin_html_util.cc +++ b/source/server/admin/admin_html_util.cc @@ -54,10 +54,11 @@ namespace Server { namespace { class BuiltinResourceProvider : public AdminHtmlUtil::ResourceProvider { public: - BuiltinResourceProvider() { + BuiltinResourceProvider() : histogram_js_(absl::StrCat(HistogramsJs1, HistogramsJs2)) { map_["admin_head_start.html"] = AdminHtmlStart; map_["admin.css"] = AdminCss; map_["active_stats.js"] = AdminActiveStatsJs; + map_["histograms.js"] = histogram_js_; map_["active_params.html"] = AdminActiveParamsHtml; } @@ -66,6 +67,7 @@ class BuiltinResourceProvider : public AdminHtmlUtil::ResourceProvider { } private: + const std::string histogram_js_; absl::flat_hash_map map_; }; diff --git a/source/server/admin/html/BUILD b/source/server/admin/html/BUILD index ec58ce1775a0..1e8dc1521644 100644 --- a/source/server/admin/html/BUILD +++ b/source/server/admin/html/BUILD @@ -17,11 +17,12 @@ genrule( "admin.css", "active_params.html", "active_stats.js", + "histograms.js", ], outs = ["admin_html_gen.h"], cmd = "./$(location :generate_admin_html.sh) \ $(location admin_head_start.html) $(location admin.css) $(location active_stats.js) \ - $(location active_params.html) > $@", + $(location active_params.html) $(location histograms.js) > $@", tools = [":generate_admin_html.sh"], ) @@ -34,5 +35,6 @@ filegroup( "active_stats.js", "admin.css", "admin_head_start.html", + "histograms.js", ], ) diff --git a/source/server/admin/html/active_stats.js b/source/server/admin/html/active_stats.js index 0d02bb798b5e..ca6bf6723981 100644 --- a/source/server/admin/html/active_stats.js +++ b/source/server/admin/html/active_stats.js @@ -28,6 +28,11 @@ const nameStatsMap = new Map(); */ let activeStatsPreElement = null; +/** + * A div into which we render histograms. + */ +let activeStatsHistogramsDiv = null; + /** * A small div for displaying status and error messages. */ @@ -65,8 +70,10 @@ function initHook() { statusDiv.className = 'error-status-line'; activeStatsPreElement = document.createElement('pre'); activeStatsPreElement.id = 'active-content-pre'; + activeStatsHistogramsDiv = document.createElement('div'); document.body.appendChild(statusDiv); document.body.appendChild(activeStatsPreElement); + document.body.appendChild(activeStatsHistogramsDiv); loadStats(); } @@ -76,18 +83,18 @@ function initHook() { async function loadStats() { const makeQueryParam = (name) => name + '=' + encodeURIComponent( document.getElementById(paramIdPrefix + name).value); - const params = ['filter', 'type', 'histogram_buckets']; + const params = ['filter', 'type']; const href = window.location.href; // Compute the fetch URL prefix based on the current URL, so that the admin // site can be hosted underneath a site-specific URL structure. - const stats_pos = href.indexOf('/stats?'); - if (stats_pos == -1) { + const statsPos = href.indexOf('/stats?'); + if (statsPos == -1) { statusDiv.textContent = 'Cannot find /stats? in ' + href; return; } - const prefix = href.substring(0, stats_pos); - const url = prefix + '/stats?format=json&usedonly&' + + const prefix = href.substring(0, statsPos); + const url = prefix + '/stats?format=json&usedonly&histogram_buckets=detailed&' + params.map(makeQueryParam).join('&'); try { @@ -175,6 +182,7 @@ function renderStats(data) { } sortedStats.push(statRecord); } + renderHistograms(activeStatsHistogramsDiv, data); // Sorts all the stats. This is inefficient; we should just pick the top N // based on field "active-max-display-count" and sort those. The best diff --git a/source/server/admin/html/admin.css b/source/server/admin/html/admin.css index e8f99cc2cc5e..bb1af5f0cbd5 100644 --- a/source/server/admin/html/admin.css +++ b/source/server/admin/html/admin.css @@ -46,3 +46,119 @@ font-size: medium; color: #c00; } + +.histogram-graphics { + height: 40px; + position: relative; + margin-top: 15px; + /* + * TODO(jmarantz): enable resizing; to finish this we need to add a ResizeObserver + * to keep a map of the resized histograms for use when refreshing them. + * + * resize: vertical; + * overflow: auto; + */ +} + +.histogram-annotations { + height: 40px; + position: relative; + margin-bottom: 10px; +} + +.histogram-labels { + background-color: #ddd; + position: relative; + height: 15px; +} + +.histogram-name { + font-family: sans-serif; + font-size: 14px; + font-weight: bold; + margin-top: 10px; + margin-bottom: 8px; +} + +.histogram-no-data { + font-family: sans-serif; + font-size: 14px; + font-style: italic; + margin-top: 10px; + margin-bottom: 8px; + margin-left: 10px; +} + +.histogram-bucket { + bottom: 0; + background-color: #e6d7ff; + position: absolute; + border-color: purple; + border-width: 1px; + border-style: solid; + width: 2%; + z-index: 1; +} + +.histogram-popup { + position: absolute; + background-color: yellow; + border-width: 1px; + border-style: solid; + border-color: black; + visibility: hidden; + z-index: 3; + top: 70px; + padding: 3px; + /*Imargin-left: -1%;*/ +} + +.histogram-popup div { + font-family: sans-serif; + font-size: 14px; + overflow: hidden; + text-align: center; +} + +.histogram-percentile { + width: 5px; + background-color: #306844; + height: 30%; + width: 4px; + top: 0; + position: absolute; +} + +.histogram-interval { + width: 5px; + background-color: #e06844; + height: 30%; + width: 4px; + margin-left: 0.5%; + top: 0; + position: absolute; +} + +.bucket-label { + position: absolute; + bottom: 1%; + font-family: sans-serif; + font-size: 12px; + margin-bottom: 1px; + text-align: center; +} + +.percentile-label { + position: absolute; + font-family: sans-serif; + font-size: 12px; + z-index: 2; +} + +.histogram-labels span { + position: absolute; + bottom: 0; + font-family: sans-serif; + font-size: 12px; + overflow-x: visible; +} diff --git a/source/server/admin/html/generate_admin_html.sh b/source/server/admin/html/generate_admin_html.sh index 51352f0b8d0d..36041855afae 100755 --- a/source/server/admin/html/generate_admin_html.sh +++ b/source/server/admin/html/generate_admin_html.sh @@ -12,3 +12,19 @@ echo ')EOF";' echo 'constexpr absl::string_view AdminActiveParamsHtml = R"EOF(' cat "$4" echo ')EOF";' + +# The Windows compiler complains histograms.js is too big to fit into a string +# constant, so generate the histograms implementation in two chunks. These will +# be combined in source/server/admin/admin_html_util.cc when constructing +# BuiltinResourceProvider. We do this even when not on Windows for consistency. +lines=$(wc -l < "$5") +first_lines=$((lines / 2)) +next_lines=$((first_lines + 1)) + +echo 'constexpr absl::string_view HistogramsJs1 = R"EOF(' +head --lines="$first_lines" "$5" +echo ')EOF";' + +echo 'constexpr absl::string_view HistogramsJs2 = R"EOF(' +tail --lines=+"$next_lines" "$5" +echo ')EOF";' diff --git a/source/server/admin/html/histograms.js b/source/server/admin/html/histograms.js new file mode 100644 index 000000000000..f60357999204 --- /dev/null +++ b/source/server/admin/html/histograms.js @@ -0,0 +1,628 @@ +// Functions to render a JSON histogram representation into an HTML/CSS. +// There are several ways to do this: +// 1. lay out in CSS with flex-boxes +// 2. draw using SVG +// 3. render as `divs` with pixel positions +// 4. render as `divs` with percentage positions +// This implements option #4. There are pros/cons to each of these. The benefits of #4: +// 1. The user can get a clearer picture by making the window bigger, without having +// to re-layout the graphics. +// 2. The `divs` can be made sensitive to mouse enter/leave to pop up +// more detail +// There are also drawbacks: +// 1. Need to write graphics layout code, and think about coordinate systems, resulting +// in several hundred lines of JavaScript. +// 2. Some risk of having the text look garbled in some scenarios. This appears to +// to be mitigated with heuristics and use of popup elements when more than one +// percentile or interval-data falls within a bucket. + +const constants = { + // Horizontal spacing between buckets, expressed in `VPX` (Virtual Pixels) in a + // coordinate system invented to make arithmetic and debugging easier. + marginWidthVpx: 20, + + // Horizontal spacing between the edge of the window and the histogram buckets, + // expressed as a fraction. + outerMarginFraction: 0.01, + + // The minimum height of a bucket bar, expressed as a percentage of the + // configured height of a configured bar. By giving a histogram with count=1 + // a minimum height we make it easier for the mouse to hover over it, in + // order to pop up more detail. + baseHeightFraction: 0.03, + + // If there are too many buckets, per-bucket label text gets too dense and the + // text becomes illegible, so skip some if needed. We always put the range in + // the popup, and when skipped, we'll put the count in the popup as well, in + // addition to any percentiles or interval ranges. + maxBucketsWithText: 20, +}; + + +const globalState = { + // Holds a function to be called when the mouse leaves a popup. This is + // null when there is no visible popup. + pendingLeave: null, + + // Holds the timer object for the currently-visible popup. This is + // maintained so we can cancel the timeout if the user moves to a new + // bucket, in which case we'll immediately hide the popup so we can + // display the new one. + pendingTimeout: null, + + // Holds the histogram bucket object that is currently highlighted, + // which makes it possible to erase the highlight after the mouse moves + // out of it + highlightedBucket: null, +}; + + +/** + * Formula to compute bucket width based on number of buckets. This formula + * was derived from trial and error, to improve the appearance of the display. + * Consider this table of values: + * numBuckets `bucketWidthVpx` Ratio vs `marginWidthVpx` + * 1 2 1:10 + * 2 21 1:2 + * 3 27 2:3 + * 10 36 1.8:1 + * 20 38 1.9:1 + * These ratios appear to look good across a wide range of numBuckets. + * + * @param {number} numBuckets the number of buckets in the histogram. + * @return {number} The bucket width in virtual pixels. + */ +function computeBucketWidthVpx(numBuckets) { + return 40 - 38/numBuckets; +} + + +/** + * Top-level entry point to render all the detailed histograms found in a JSON + * stats response. + * + * @param {!Element} histogramDiv the element in which to render the histograms. + * @param {!Object} data the stats JSON structure obtained from the server /stats method. + */ +function renderHistograms(histogramDiv, data) { // eslint-disable-line no-unused-vars + histogramDiv.replaceChildren(); + for (stat of data.stats) { + const histograms = stat.histograms; + if (histograms) { + if (histograms.supported_percentiles && histograms.details) { + for (histogram of histograms.details) { + renderHistogram(histogramDiv, histograms.supported_percentiles, histogram); + } + } + } + } +} + + +/** + * Formats a number using up to 2 decimal places. See + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat + */ +const format = Intl.NumberFormat('en', { // eslint-disable-line new-cap + notation: 'compact', + maximumFractionDigits: 2, +}).format; + + +// Formats a percentage using up to 2 decimal places. These are +// used for writing CSS percents. +const formatPercent = Intl.NumberFormat('en', { // eslint-disable-line new-cap + style: 'percent', + maximumFractionDigits: 2, +}).format; + + +/** + * Formats a range for a histogram bucket, using inclusive/beginning and + * exclusive end, computed from the width. + * + * @param {number} lowerBound the lower bound of the range. + * @param {number} width the range. + * @return {string} A formatted string of the form "[lowerBound, upperBound)". + */ +function formatRange(lowerBound, width) { + return '[' + format(lowerBound) + ', ' + format(lowerBound + width) + ')'; +} + + +/** + * Generates a function to render histogram information, capturing the + * variables passed in. This is used to establish a mouse-enter list on + * the histogram bucket, but without pulling in the entire drawing context. + * + * @param {!Element} detailPopup the popup div for this histogram. + * @param {string} bucketPosPercent The bucket position, expressed as a string percentage. + * @param {!Object} bucket the bucket record from JSON, augmented with an annotations list + * @param {!Element} bucketSpan a span element for the bucket; used to color it yellow. + * @param {boolean} showingCount whether the the count is shown on the histogram itself, + * which dictates whether we will also show it in the popup. + * @return {!Function} a function to call when the mouse enters the span. + */ + function showPopupFn(detailPopup, bucketPosPercent, bucket, bucketSpan, showingCount) { + return (event) => { + if (globalState.pendingTimeout) { + window.clearTimeout(globalState.pendingTimeout); + globalState.pendingLeave(); + } + detailPopup.style.left = bucketPosPercent; + detailPopup.style.visibility = 'visible'; + bucketSpan.style.backgroundColor = 'yellow'; + highlightedBucket = bucketSpan; + + detailPopup.replaceChildren(); + appendNewElement(detailPopup, 'div').textContent = formatRange(bucket.lower_bound, bucket.width); + if (!showingCount) { + appendNewElement(detailPopup, 'div').textContent = 'count=' + bucket.count; + } + if (bucket.annotations) { + for (annotation of bucket.annotations) { + const span = appendNewElement(detailPopup, 'div'); + span.textContent = annotation.detail(); + } + } + }; +} + + +/** + * Generates a timeout function for the provided popup div. + * + * @param {!Element} detailPopup the popup div. + * @return {!Function} a function to be called when the mouse leaves the span. + */ +function timeoutFn(detailPopup) { + return (event) => { + globalState.pendingLeave = leaveHandlerFn(detailPopup); + globalState.pendingTimeout = window.setTimeout(globalState.pendingLeave, 2000); + }; +} + + +/** + * Generates a handler function to be called when the mouse leaves + * a popup. + * + * @param {!Element} detailPopup the popup div. + * @return {!Function} a function to hide the popup. + */ +function leaveHandlerFn(detailPopup) { + return (event) => { + globalState.pendingTimeout = null; + globalState.pendingLeave = null; + detailPopup.style.visibility = 'hidden'; + if (highlightedBucket) { + highlightedBucket.style.backgroundColor = '#e6d7ff'; + highlightedBucket = null; + } + }; +} + + +/** + * When the user moves the mouse into the popup, we cancel the timer + * to hide the popup, held in globalState.pendingTimeout. However the + * globalState.pendingLeave function is left in place so a timeout can + * be re-established when the mouse leaves the popup. + */ +function enterPopup() { + // If the mouse enters the popup then cancel the timer that would + // erase it. This should make it easier to cut&paste the contents + // of the popup. + if (globalState.pendingTimeout) { + window.clearTimeout(globalState.pendingTimeout); + globalState.pendingTimeout = null; + // The 'leave' handler needs to remain -- we'll call that 2 seconds + // after the mouse leaves the popup. + } +} + + +/** + * When the user moves the mouse out of the popup, we re-enable the + * timeout that was (a) previously established when the mouse entered + * the bucket span, and (b) disabled when the mouse entered the popup. + */ +function leavePopup() { + globalState.pendingTimeout = window.setTimeout(globalState.pendingLeave, 2000); +} + + +/** + * Helper function to create an element, append it to a parent, and optionally + * install a CSS class. + * + * @param {!Element} parent the parent element. + * @param {string} type the HTML element type, e.g. 'div'. + * @param {?string} className optional CSS class name. + * @return {!Element} the new element. + */ +function appendNewElement(parent, type, className) { + const element = document.createElement(type); + if (className) { + element.className = className; + } + parent.appendChild(element); + return element; +} + + +/** + * Assigns percentiles and intervals to buckets. We do not expect percentiles or + * intervals. If any occur, they will be assigned to the first or last bucket. + * + * We will only consider the lower_bound of interval-buckets and will ignore the + * width of those buckets. + * + * We will assign intervals and percentiles to the bucket with the highest + * lower-bound that is not greater than the interval lower_bound or percentile + * value. + * + * @param {!Object} histogram JSON structure for a histogram. + * @param {!Array} supportedPercentiles Array of supported histograms. + * @return {number} the maximum count across all buckets. + */ +function assignPercentilesAndIntervalsToBuckets(histogram, supportedPercentiles) { + let maxCount = 0; + let percentileIndex = 0; + let intervalIndex = 0; + const percentileValues = histogram.percentiles; + let nextBucket = histogram.totals[0]; + + for (let i = 0; i < histogram.totals.length; ++i) { + const bucket = nextBucket; + if (i < histogram.totals.length - 1) { + nextBucket = histogram.totals[i + 1]; + } else { + nextBucket = null; + } + maxCount = Math.max(maxCount, bucket.count); + bucket.annotations = []; + + // Attach percentile records with values between the previous bucket and + // this one. We will drop percentiles before the first bucket. Thus each + // bucket starting with the second one will have a 'percentiles' property + // with pairs of [percentile, value], which can then be used while + // rendering the bucket. + for (; percentileIndex < percentileValues.length; ++percentileIndex) { + const percentileValue = percentileValues[percentileIndex].cumulative; + if (nextBucket && percentileValue >= nextBucket.lower_bound) { + break; // do not increment index; re-consider percentile for next bucket. + } + bucket.annotations.push(new Percentile( + percentileValue, supportedPercentiles[percentileIndex])); + } + + for (; intervalIndex < histogram.intervals.length; ++intervalIndex) { + const interval = histogram.intervals[intervalIndex]; + if (nextBucket && interval.lower_bound >= nextBucket.lower_bound) { + break; // do not increment index; re-consider interval for next bucket. + } + bucket.annotations.push(new Interval(interval.lower_bound, interval.width, interval.count)); + + // It's unlikely that an interval bucket value will increase the overall maxCount + // but just to be sure we'll scan through them. + maxCount = Math.max(maxCount, interval.count); + } + + if (bucket.annotations.length > 0) { + bucket.annotations.sort((a, b) => { + if (a.value == b.value) { + if (a.cssClass() == b.cssClass()) { + return 0; + } + if (a.cssClass() == 'histogram-percentile') { + return -1; + } + return 1; + } + return a.value - b.value; + }); + let aa = 0; + for (a of bucket.annotations) { + console.log('[' + aa++ + ']: ' + a.value + ' (' + a.cssClass() + ')'); + } + } + } + return maxCount; +} + +/** + * Represents an annotation, which can be a percentile or interval-bucket. + */ +class Annotation { + /** + * @param {number} value The numeric value of the annotation. + */ + constructor(value) { + this.value = value; + } + + /** + * Returns the CSS class name used for rendering this annotation + */ + cssClass() { + throw new Error('pure virtual function cssClass'); + } + + /** + * Returns formats the annotation as an abbreviated string. + */ + toString() { + throw new Error('pure virtual function toString'); + } + + /** + * Returns formats the annotation with greater detail, suitable for a popup. + */ + detail() { + throw new Error('pure virtual function detail'); + } +} + +/** + * Represents a percentile. + */ +class Percentile extends Annotation { + /** + * @param {number} value The numeric value of the annotation. + * @param {number} percentile The percentile number. + */ + constructor(value, percentile) { + super(value); + this.percentile = percentile; + } + + /** + * @return {string} the css class name. + */ + cssClass() { + return 'histogram-percentile'; + } + + /** + * @return {string} brief format for graphical annotation. + */ + toString() { + return 'P' + this.percentile; + } + + /** + * @return {string} detailed for popup. + */ + detail() { + return `P${this.percentile}: ${format(this.value)}`; + } +} + +/** + * Represents a interval bucket. + */ +class Interval extends Annotation { + /** + * @param {number} value The lower bound of the bucket. + * @param {number} width The width of the bucket. + * @param {number} count The height of the bucket. + */ + constructor(value, width, count) { + super(value); + this.width = width; + this.count = count; + } + + /** + * @return {string} the css class name. + */ + cssClass() { + return 'histogram-interval'; + } + + /** + * @return {string} brief format for graphical annotation. + */ + toString() { + return 'i:' + this.count; + } + + /** + * @return {string} detailed for popup. + */ + detail() { + return 'Interval ' + formatRange(this.value, this.width) + ': ' + this.count; + } +} + +/** + * Captures context needed to lay out the histogram graphically. + */ +class Painter { + /** + * @param {!Element} div the HTML element into which to draw the histogram + * @param {number} numBuckets the number of buckets. + * @param {number} maxCount the maximum count for all buckets. + */ + constructor(div, numBuckets, maxCount) { + this.numBuckets = numBuckets; + this.maxCount = maxCount; + this.leftVpx = constants.marginWidthVpx; + this.bucketWidthVpx = computeBucketWidthVpx(numBuckets); + this.widthVpx = (numBuckets * this.bucketWidthVpx + + ((numBuckets + 1) * constants.marginWidthVpx) * + (1 + 2*constants.outerMarginFraction)); + this.textIntervalIndex = 0; + this.bucketWidthPercent = formatPercent(this.vpxToWidth(this.bucketWidthVpx)); + + this.graphics = appendNewElement(div, 'div', 'histogram-graphics'); + this.labels = appendNewElement(div, 'div', 'histogram-labels'); + this.annotationsDiv = appendNewElement(div, 'div', 'histogram-annotations'); + + // We have business logic to ensure only be one popup div is visible at a + // time. However, we need a separate popup div for each histogram + // so that they can be positioned relative to the histogram's graphics. + this.detailPopup = appendNewElement(this.graphics, 'div', 'histogram-popup'); + this.detailPopup.addEventListener('mouseenter', enterPopup); + this.detailPopup.addEventListener('mouseleave', leavePopup); + + this.textInterval = Math.ceil(numBuckets / constants.maxBucketsWithText); + } + + /** + * @param {!Object} bucket the JSON info for the current bucket. + * @param {?Object} nextBucket the JSON info for next bucket, or null if + * bucket is the last one. + * @param {!Annotation} annotation an annotation to draw. + */ + drawAnnotation(bucket, nextBucket, annotation) { + // Find the ideal place to draw the percentile bar, by linearly + // interpolating between the current bucket and the previous bucket. + // We know that the next bucket does not come into play because + // the percentiles held underneath a bucket are based on a value that + // is at most as large as the current bucket. + let percentileVpx = this.leftVpx; + const bucketDelta = nextBucket ? (nextBucket.lower_bound - bucket.lower_bound) : bucket.width; + if (bucketDelta > 0) { + let widthVpx = this.bucketWidthVpx; + if (nextBucket) { + widthVpx += constants.marginWidthVpx; + } + const nextVpx = this.leftVpx + widthVpx; + const weight = (bucket.lower_bound + bucketDelta - annotation.value) / bucketDelta; + percentileVpx = weight * this.leftVpx + (1 - weight) * nextVpx; + } + + // We always put the marker proportionally between this bucket and + // the next one. + const span = appendNewElement(this.annotationsDiv, 'span', annotation.cssClass()); + const percentilePercent = formatPercent(this.vpxToPosition(percentileVpx)); + span.style.left = percentilePercent; + + // Don't draw textual labels for the percentiles and intervals if there are + // more than one: they'll just get garbled. The user can over over the + // bucket to see the detail. + if (bucket.annotations.length == 1) { + const percentilePLabel = appendNewElement(this.annotationsDiv, 'span', 'percentile-label'); + percentilePLabel.style.bottom = 0; + percentilePLabel.textContent = annotation.toString(); + percentilePLabel.style.left = percentilePercent; + + const percentileVLabel = appendNewElement(this.annotationsDiv, 'span', 'percentile-label'); + percentileVLabel.style.bottom = '30%'; + percentileVLabel.textContent = format(annotation.value); + percentileVLabel.style.left = percentilePercent; + } + } + + /** + * Draws a bucket. + * + * @param {!Object} bucket the bucket to draw. + */ + drawBucket(bucket) { + this.leftPercent = formatPercent(this.vpxToPosition(this.leftVpx)); + + const bucketSpan = appendNewElement(this.graphics, 'span', 'histogram-bucket'); + const heightPercent = this.maxCount == 0 ? 0 : + formatPercent(constants.baseHeightFraction + (bucket.count / this.maxCount) * + (1 - constants.baseHeightFraction)); + bucketSpan.style.height = heightPercent; + bucketSpan.style.width = this.bucketWidthPercent; + bucketSpan.style.left = this.leftPercent; + + let showingCount = false; + if (++this.textIntervalIndex == this.textInterval) { + showingCount = true; + this.textIntervalIndex = 0; + this.drawBucketLabels(bucket, heightPercent); + } + + bucketSpan.addEventListener('mouseenter', showPopupFn( + this.detailPopup, formatPercent(this.vpxToPosition(this.leftVpx)), bucket, + bucketSpan, showingCount)); + + bucketSpan.addEventListener('mouseleave', timeoutFn(this.detailPopup)); + + this.leftVpx += this.bucketWidthVpx + constants.marginWidthVpx; + } + + /** + * Draws the labels for a bucket. + * + * @param {!Object} bucket the bucket to draw. + * @param {string} heightPercent The height of the bucket, expressed as a percent. + */ + drawBucketLabels(bucket, heightPercent) { + const lowerLabel = appendNewElement(this.labels, 'span'); + lowerLabel.textContent = format(bucket.lower_bound); + lowerLabel.style.left = this.leftPercent; + lowerLabel.style.width = this.bucketWidthPercent; + + const bucketLabel = appendNewElement(this.graphics, 'span', 'bucket-label'); + bucketLabel.textContent = format(bucket.count); + bucketLabel.style.left = this.leftPercent; + bucketLabel.style.width = this.bucketWidthPercent; + bucketLabel.style.bottom = heightPercent; + } + + /** + * @param {number} virtualPixels the number of virtual pixels. + * @return {number} the x-position as a percent, including an offset. + */ + vpxToPosition(virtualPixels) { + return this.vpxToWidth(virtualPixels) + constants.outerMarginFraction; + } + + /** + * @param {number} virtualPixels the number of virtual pixels. + * @return {number} the x-position as a numeric percent. + */ + vpxToWidth(virtualPixels) { + return virtualPixels / this.widthVpx; + } +} + +/** + * @param {!Element} histogramDiv the element in which to render the histograms. + * @param {!Array} supportedPercentiles Array of supported histograms. + * @param {!Object} histogram the stats JSON structure obtained from the server /stats method. + * @param {?number} changeCount the number of times this histogram has changed value. + */ +function renderHistogram(histogramDiv, supportedPercentiles, histogram, changeCount) { + const div = appendNewElement(histogramDiv, 'div'); + const label = appendNewElement(div, 'span', 'histogram-name'); + label.textContent = histogram.name + (changeCount == null ? '' : ' (' + changeCount + ')'); + + const numBuckets = histogram.totals.length; + if (numBuckets == 0) { + appendNewElement(div, 'span', 'histogram-no-data').textContent = 'No recorded values'; + return; + } + + const maxCount = assignPercentilesAndIntervalsToBuckets(histogram, supportedPercentiles); + + // Lay out the buckets evenly, independent of the bucket values. It's up + // to the `circlhist` library to space out the buckets in a shape tuned to + // the data. + // + // We will not draw percentile lines outside of the bucket values. E.g. we + // may skip drawing outer percentiles like P0 and P100 etc. + // + // We lay out horizontally based on CSS percentage so users can see the + // graphics better if they make the window wider. We do this by inventing + // arbitrary "virtual pixels" (variables with `Vpx` suffix) during the + // computation in JS and converting them to percentages for writing element + // style. + const painter = new Painter(div, numBuckets, maxCount); + + for (let i = 0; i < numBuckets; ++i) { + const bucket = histogram.totals[i]; + const nextBucket = (i < histogram.totals.length - 1) ? histogram.totals[i + 1] : null; + for (annotation of bucket.annotations) { + painter.drawAnnotation(bucket, nextBucket, annotation); + } + painter.drawBucket(bucket); + } +} diff --git a/source/server/admin/stats_handler.cc b/source/server/admin/stats_handler.cc index fb8dc1801f93..662e6a59c7f1 100644 --- a/source/server/admin/stats_handler.cc +++ b/source/server/admin/stats_handler.cc @@ -171,29 +171,33 @@ Http::Code StatsHandler::handlerContention(Http::ResponseHeaderMap& response_hea } Admin::UrlHandler StatsHandler::statsHandler(bool active_mode) { - const Admin::ParamDescriptorVec common_params{ - {Admin::ParamDescriptor::Type::String, "filter", - "Regular expression (Google re2) for filtering stats"}, - {Admin::ParamDescriptor::Type::Enum, - "format", - "Format to use", - {"html", "active-html", "text", "json"}}, - {Admin::ParamDescriptor::Type::Enum, - "type", - "Stat types to include.", - {StatLabels::All, StatLabels::Counters, StatLabels::Histograms, StatLabels::Gauges, - StatLabels::TextReadouts}}, - {Admin::ParamDescriptor::Type::Enum, - "histogram_buckets", - "Histogram bucket display mode", - {"cumulative", "disjoint", "detailed", "none"}}}; - - Admin::ParamDescriptorVec params; + Admin::ParamDescriptor usedonly{ + Admin::ParamDescriptor::Type::Boolean, "usedonly", + "Only include stats that have been written by system since restart"}; + Admin::ParamDescriptor histogram_buckets{Admin::ParamDescriptor::Type::Enum, + "histogram_buckets", + "Histogram bucket display mode", + {"cumulative", "disjoint", "detailed", "none"}}; + Admin::ParamDescriptor format{Admin::ParamDescriptor::Type::Enum, + "format", + "Format to use", + {"html", "active-html", "text", "json"}}; + Admin::ParamDescriptor filter{Admin::ParamDescriptor::Type::String, "filter", + "Regular expression (Google re2) for filtering stats"}; + Admin::ParamDescriptor type{Admin::ParamDescriptor::Type::Enum, + "type", + "Stat types to include.", + {StatLabels::All, StatLabels::Counters, StatLabels::Histograms, + StatLabels::Gauges, StatLabels::TextReadouts}}; + + Admin::ParamDescriptorVec params{usedonly, filter}; if (!active_mode) { - params.push_back({Admin::ParamDescriptor::Type::Boolean, "usedonly", - "Only include stats that have been written by system since restart"}); + params.push_back(format); + } + params.push_back(type); + if (!active_mode) { + params.push_back(histogram_buckets); } - params.insert(params.end(), common_params.begin(), common_params.end()); return { "/stats", diff --git a/source/server/admin/stats_html_render.cc b/source/server/admin/stats_html_render.cc index d170843e7003..52bbbbfa1108 100644 --- a/source/server/admin/stats_html_render.cc +++ b/source/server/admin/stats_html_render.cc @@ -23,9 +23,27 @@ StatsHtmlRender::StatsHtmlRender(Http::ResponseHeaderMap& response_headers, Buffer::Instance& response, const StatsParams& params) : StatsTextRender(params), active_(params.format_ == StatsFormat::ActiveHtml) { AdminHtmlUtil::renderHead(response_headers, response); + if (!active_) { + StatsParams json_params(params); + json_params.histogram_buckets_mode_ = Utility::HistogramBucketsMode::Detailed; + json_response_headers_ = Http::ResponseHeaderMapImpl::create(); + histogram_json_render_ = + std::make_unique(*json_response_headers_, json_data_, json_params); + } } -void StatsHtmlRender::finalize(Buffer::Instance& response) { AdminHtmlUtil::finalize(response); } +void StatsHtmlRender::finalize(Buffer::Instance& response) { + // Render all the histograms here using the JSON data we've accumulated + // for them. + if (!active_) { + histogram_json_render_->finalize(json_data_); + response.add("\n
\n\n"}); + std::string buf2; + response.addFragments({"\n"}); } else { - response.add("
\n");
+    response.addFragments(
+        {"\n
\n"});
   }
 }
 
diff --git a/source/server/admin/stats_html_render.h b/source/server/admin/stats_html_render.h
index 229e004a17cb..c86c105a88d6 100644
--- a/source/server/admin/stats_html_render.h
+++ b/source/server/admin/stats_html_render.h
@@ -35,16 +35,23 @@ class StatsHtmlRender : public StatsTextRender {
     StatsTextRender::generate(response, name, value);
   }
 
-  // generate() call directly calls parent method, which is needed to allow gcc
-  // to compile, otherwise it warns about hidden overrides.
-  void generate(Buffer::Instance& response, const std::string& name,
+  // We override the generate method for HTML to trigger some JS that will
+  // render the histogram graphically. We will render that from JavaScript
+  // and convey the histogram data to the JS via JSON, so we can delegate
+  // to an instantiated JSON `sub-renderer` that will write into json_data_.
+  void generate(Buffer::Instance&, const std::string& name,
                 const Stats::ParentHistogram& histogram) override {
-    StatsTextRender::generate(response, name, histogram);
+    histogram_json_render_->generate(json_data_, name, histogram);
   }
+
   void finalize(Buffer::Instance&) override;
 
 private:
   const bool active_{false};
+  Buffer::OwnedImpl json_data_;
+  std::unique_ptr histogram_json_render_;
+  Http::ResponseHeaderMapPtr json_response_headers_; // ignored.
+  std::unique_ptr json_headers_;
 };
 
 } // namespace Server
diff --git a/test/integration/admin_html/BUILD b/test/integration/admin_html/BUILD
index ed7e028cbc82..1215673070f8 100644
--- a/test/integration/admin_html/BUILD
+++ b/test/integration/admin_html/BUILD
@@ -52,6 +52,7 @@ filegroup(
     name = "test_server_files",
     srcs = [
         "active_stats_test.js",
+        "histograms_test.js",
         "web_test.html",
         "web_test.js",
         "web_test.yaml",
diff --git a/test/integration/admin_html/active_stats_test.js b/test/integration/admin_html/active_stats_test.js
index 0b83006dd779..25de79d3ba9b 100644
--- a/test/integration/admin_html/active_stats_test.js
+++ b/test/integration/admin_html/active_stats_test.js
@@ -1,6 +1,4 @@
-// This file contains helper functions for writing JavaScript unit tests, in the
-// style of Google's Closure Compiler, but without taking on a large dependency
-// or build infrastructure.
+// This file uses unit-test helper functions defined in web_test.js.
 //
 // See source/server/admin/javascript.md for background info.
 
diff --git a/test/integration/admin_html/histograms_test.html b/test/integration/admin_html/histograms_test.html
new file mode 100644
index 000000000000..e10ca5b79799
--- /dev/null
+++ b/test/integration/admin_html/histograms_test.html
@@ -0,0 +1,9 @@
+
+  
+    
+    
+  
+  
+    

+  
+
diff --git a/test/integration/admin_html/histograms_test.js b/test/integration/admin_html/histograms_test.js
new file mode 100644
index 000000000000..c9df555e0db7
--- /dev/null
+++ b/test/integration/admin_html/histograms_test.js
@@ -0,0 +1,154 @@
+/**
+ * Makes a histogram with the specified values so we can test that all the
+ * features of this are rendered graphically.
+ *
+ * @param {!Array} totals pre-populated json 'totals' field.
+ * @return {!Object} json stats object containing one histogram.
+ */
+function makeHistogramJson(totals) {
+  return {'stats': [{
+    'histograms': {
+      'supported_percentiles': [0, 25, 50, 75, 90, 95, 99, 99.5, 99.9, 100],
+      'details': [{
+        'name': 'h1',
+        'percentiles': [
+          {'cumulative': 200, 'interval': 200},
+          {'cumulative': 207.5, 'interval': 207.5},
+          {'cumulative': 302.5, 'interval': 302.5},
+          {'cumulative': 306.25, 'interval': 306.25},
+          {'cumulative': 308.5, 'interval': 308.5},
+          {'cumulative': 309.25, 'interval': 309.25},
+          {'cumulative': 309.85, 'interval': 309.85},
+          {'cumulative': 309.925, 'interval': 309.925},
+          {'cumulative': 309.985, 'interval': 309.985},
+          {'cumulative': 310, 'interval': 310},
+        ],
+        'totals': totals,
+        'intervals': [
+          {'lower_bound': 200, 'width': 10, 'count': 1},
+          {'lower_bound': 300, 'width': 10, 'count': 2}]}]}}]};
+}
+
+/**
+ * Tests the rendering of histograms.
+ *
+ * @param {!Element} iframe the iframe we can use for rendering.
+ */
+async function testRenderHistogram(iframe) {
+  const idoc = iframe.contentWindow.document;
+  renderHistograms(idoc.body, makeHistogramJson([
+    {'lower_bound': 200, 'width': 10, 'count': 1},
+    {'lower_bound': 300, 'width': 10, 'count': 2}]));
+  const buckets = idoc.getElementsByClassName('histogram-bucket');
+  assertEq(2, buckets.length);
+
+  // The first bucket is to the left of the second bucket;
+  assertLt(parseFloat(buckets[0].style.left), parseFloat(buckets[1].style.left));
+
+  // The first bucket has a height between 25% and 75%.
+  assertLt(25, parseFloat(buckets[0].style.height));
+  assertLt(parseFloat(buckets[0].style.height), 75);
+
+  // The second bucket as a 100% height.
+  assertEq('100%', buckets[1].style.height);
+
+  // There is one popup div and it is not visible initially.
+  const popups = idoc.getElementsByClassName('histogram-popup');
+  assertEq(1, popups.length);
+  const popup = popups[0];
+  assertEq('hidden', getComputedStyle(popup).visibility);
+
+  // When the mouse enters the first bucket it renders a visible popup with
+  // associated annotations.
+  buckets[0].dispatchEvent(new Event('mouseenter'));
+  assertEq('visible', getComputedStyle(popup).visibility);
+  assertEq(4, popup.children.length);
+  assertEq('[200, 210)', popup.children[0].textContent);
+  assertEq('P0: 200', popup.children[1].textContent);
+  assertEq('Interval [200, 210): 1', popup.children[2].textContent);
+  assertEq('P25: 207.5', popup.children[3].textContent);
+
+  // 2 seconds after the mouse leaves, that area, the popup will be made invisible.
+  buckets[0].dispatchEvent(new Event('mouseleave'));
+  await asyncTimeout(3000);
+  assertEq('hidden', getComputedStyle(popup).visibility);
+
+  // Now enter the other bucket. Just check the 1st 2 of 10 buckets.
+  buckets[1].dispatchEvent(new Event('mouseenter'));
+  assertEq('visible', getComputedStyle(popup).visibility);
+  assertEq(10, popup.children.length);
+  assertEq('[300, 310)', popup.children[0].textContent);
+  assertEq('Interval [300, 310): 2', popup.children[1].textContent);
+  buckets[1].dispatchEvent(new Event('mouseleave'));
+
+  // Re-enter the first bucket. The popup will immediately move to that with no delay.
+  buckets[0].dispatchEvent(new Event('mouseenter'));
+  assertEq('visible', getComputedStyle(popup).visibility);
+  assertEq(4, popup.children.length);
+  assertEq('[200, 210)', popup.children[0].textContent);
+  buckets[1].dispatchEvent(new Event('mouseleave'));
+
+  // There's exactly one annotations bucket.
+  assertEq(1, idoc.getElementsByClassName('histogram-annotations').length);
+
+  // There are 10 percentiles rendered each one to the right of the previous one.
+  const percentiles = idoc.getElementsByClassName('histogram-percentile');
+  assertEq(10, percentiles.length);
+  let prevPercent = 0;
+  for (percentile of percentiles) {
+    const left = parseFloat(percentile.style.left);
+    assertLt(prevPercent, left);
+    prevPercent = left;
+  }
+
+  // There are 2 intervals rendered each one to the right of the previous one.
+  const intervals = idoc.getElementsByClassName('histogram-interval');
+  assertEq(2, intervals.length);
+  assertLt(parseFloat(intervals[0].style.left), parseFloat(intervals[1].style.left));
+}
+
+
+/**
+ * Renders a histogram, returning the number of text entries.
+ *
+ * @param {!Element} iframe the iframe we can use for rendering.
+ * @param {number} numBuckets the number of histogram buckets to render.
+ * @return {number} the number of text entries found.
+ */
+async function renderManyBucketsCountingLabels(iframe, numBuckets) {
+  const idoc = iframe.contentWindow.document;
+  idoc.body.replaceChildren();
+
+  let totals = [];
+  for (let i = 0; i < numBuckets; ++i) {
+    totals.push({'lower_bound': i*100, 'width': 10, 'count': 1});
+  }
+
+  renderHistograms(idoc.body, makeHistogramJson(totals));
+  await asyncTimeout(200);
+  const labels = idoc.getElementsByClassName('histogram-labels')[0];
+  return labels.children.length;
+}
+
+
+/**
+ * Tests the rendering of histograms with a large number of buckets.
+ *
+ * @param {!Element} iframe the iframe we can use for rendering.
+ */
+async function testManyBuckets(iframe) {
+  assertEq(15, await renderManyBucketsCountingLabels(iframe, 15));
+  assertEq(16, await renderManyBucketsCountingLabels(iframe, 16));
+  assertEq(17, await renderManyBucketsCountingLabels(iframe, 17));
+  assertEq(18, await renderManyBucketsCountingLabels(iframe, 18));
+  assertEq(19, await renderManyBucketsCountingLabels(iframe, 19));
+  assertEq(20, await renderManyBucketsCountingLabels(iframe, 100));
+  assertEq(20, await renderManyBucketsCountingLabels(iframe, 200));
+  assertEq(19, await renderManyBucketsCountingLabels(iframe, 250));
+  assertEq(20, await renderManyBucketsCountingLabels(iframe, 400));
+  assertEq(20, await renderManyBucketsCountingLabels(iframe, 500));
+  assertEq(20, await renderManyBucketsCountingLabels(iframe, 1000));
+}
+
+addTest('?file=histograms_test.html', 'renderHistogram', testRenderHistogram);
+addTest('?file=histograms_test.html', 'manyBuckets', testManyBuckets);
diff --git a/test/integration/admin_html/test_server.cc b/test/integration/admin_html/test_server.cc
index 944cdc04a62b..2a9b2107d0fc 100644
--- a/test/integration/admin_html/test_server.cc
+++ b/test/integration/admin_html/test_server.cc
@@ -20,8 +20,13 @@ Http::Code testCallback(Http::ResponseHeaderMap& response_headers, Buffer::Insta
                         Server::AdminStream& admin_stream) {
   Http::Utility::QueryParams query_params = admin_stream.queryParams();
   auto iter = query_params.find("file");
-  if (iter == query_params.end()) {
-    response.add("query param 'file' missing");
+  std::string prefix;
+  if (iter != query_params.end()) {
+    prefix = "test/integration/admin_html/";
+  } else if (iter = query_params.find("src"); iter != query_params.end()) {
+    prefix = "source/server/admin/html/";
+  } else {
+    response.add("query param 'file' or 'src' missing");
     return Http::Code::BadRequest;
   }
   absl::string_view leaf = iter->second;
@@ -33,7 +38,7 @@ Http::Code testCallback(Http::ResponseHeaderMap& response_headers, Buffer::Insta
   }
 
   Filesystem::InstanceImpl file_system;
-  std::string path = absl::StrCat("test/integration/admin_html/", iter->second);
+  std::string path = absl::StrCat(prefix, leaf);
   TRY_ASSERT_MAIN_THREAD { response.add(file_system.fileReadToEnd(path)); }
   END_TRY
   catch (EnvoyException& e) {
@@ -44,6 +49,8 @@ Http::Code testCallback(Http::ResponseHeaderMap& response_headers, Buffer::Insta
     response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Html);
   } else if (absl::EndsWith(path, ".js")) {
     response_headers.setReferenceContentType("text/javascript");
+  } else if (absl::EndsWith(path, ".css")) {
+    response_headers.setReferenceContentType("text/css");
   }
   return Http::Code::OK;
 }
diff --git a/test/integration/admin_html/test_server_test.sh b/test/integration/admin_html/test_server_test.sh
index cd6d4cb8b81d..6e284a5bd025 100755
--- a/test/integration/admin_html/test_server_test.sh
+++ b/test/integration/admin_html/test_server_test.sh
@@ -90,4 +90,5 @@ check_debug_log() {
 check_debug_log active_stats.js
 check_debug_log admin_head_start.html
 check_debug_log admin.css
+check_debug_log histograms.js
 
diff --git a/test/integration/admin_html/web_test.html b/test/integration/admin_html/web_test.html
index a96b0aa15603..e03a5f4474a3 100644
--- a/test/integration/admin_html/web_test.html
+++ b/test/integration/admin_html/web_test.html
@@ -2,6 +2,8 @@
 
   
   
+  
+  
 
 
   

diff --git a/test/integration/admin_html/web_test.js b/test/integration/admin_html/web_test.js
index abd667757fcf..ed720ce0d91d 100644
--- a/test/integration/admin_html/web_test.js
+++ b/test/integration/admin_html/web_test.js
@@ -6,6 +6,8 @@
 //
 // Linted with https://validatejavascript.com/, 'Google' settings, long-line
 // checking disabled, indent-checking disabled.
+//
+// See source/server/admin/javascript.md for background info.
 
 
 /**
@@ -28,6 +30,7 @@ function addTest(url, name, testFunction) { // eslint-disable-line no-unused-var
   testList.push({'url': url, 'name': name, 'testFunction': testFunction});
 }
 
+
 /**
  * Provides an async version of the `onload` event.
  *
@@ -42,6 +45,7 @@ function waitForOnload(iframe) {
   });
 }
 
+
 /**
  * Renders a URL, and after 3 seconds delay, runs the 'tester' function.
  * Log whether that function failed (threw exception) or passed. Either
@@ -96,6 +100,28 @@ function assertEq(expected, actual) { // eslint-disable-line no-unused-vars
 }
 
 
+/**
+ * Checks for less-than, throwing an exception with a comment if it fails.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ */
+function assertLt(a, b) { // eslint-disable-line no-unused-vars
+  assertTrue(a < b, 'assertLt mismatch: ' + a + ' < ' + b);
+}
+
+
+/**
+ * Async version of windows.setTimeout.
+ *
+ * @param {!number} timeoutMs Timeout in milliseconds.
+ * @return {!Promise} a promise that will be resolved when the timeout follows.
+ */
+function asyncTimeout(timeoutMs) { // eslint-disable-line no-unused-vars
+  return new Promise((resolve) => window.setTimeout(resolve, timeoutMs));
+}
+
+
 /**
  * Runs all tests added via addTest() above.
  */
@@ -113,5 +139,6 @@ function runAllTests() {
   next(0);
 }
 
+
 // Trigger the tests once all JS is loaded.
 window.addEventListener('DOMContentLoaded', runAllTests);
diff --git a/test/server/admin/stats_html_render_test.cc b/test/server/admin/stats_html_render_test.cc
index 4dfaf94f4eb6..81b0a8c8ce06 100644
--- a/test/server/admin/stats_html_render_test.cc
+++ b/test/server/admin/stats_html_render_test.cc
@@ -37,10 +37,8 @@ TEST_F(StatsHtmlRenderTest, String) {
 }
 
 TEST_F(StatsHtmlRenderTest, HistogramNoBuckets) {
-  constexpr absl::string_view expected =
-      "h1: P0(200,200) P25(207.5,207.5) P50(302.5,302.5) P75(306.25,306.25) "
-      "P90(308.5,308.5) P95(309.25,309.25) P99(309.85,309.85) P99.5(309.925,309.925) "
-      "P99.9(309.985,309.985) P100(310,310)\n";
+  // The goal of this test is to show that we have embedded the histogram as a json fragment.
+  constexpr absl::string_view expected = "const json = \n{\"stats\":[{\"histograms\":";
   EXPECT_THAT(render<>(renderer_, "h1", populateHistogram("h1", {200, 300, 300})),
               HasSubstr(expected));
 }

From 5858232fe38ca71aaefbe026c3e1ff7ccd4f8e91 Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Tue, 6 Jun 2023 17:15:23 -0400
Subject: [PATCH 191/228] coverate: ratcheting (#27822)

Signed-off-by: Alyssa Wilk 
---
 test/per_file_coverage.sh | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh
index 76f798634a85..c96fc8feb579 100755
--- a/test/per_file_coverage.sh
+++ b/test/per_file_coverage.sh
@@ -4,9 +4,8 @@
 # for existing directories with low coverage.
 declare -a KNOWN_LOW_COVERAGE=(
 "source/common:96.2"
-"source/common/api:82.6"
+"source/common/api:84.5"
 "source/common/api/posix:81.3"
-"source/common/common/posix:92.7"
 "source/common/config:94.8"
 "source/common/crypto:88.1"
 "source/common/event:95.1" # Emulated edge events guards don't report LCOV
@@ -33,7 +32,6 @@ declare -a KNOWN_LOW_COVERAGE=(
 "source/extensions/common/tap:94.2"
 "source/extensions/common/wasm:87.5" # flaky: be careful adjusting
 "source/extensions/common/wasm/ext:92.0"
-"source/extensions/filters/common:96.5"
 "source/extensions/filters/common/fault:94.5"
 "source/extensions/filters/common/rbac:90.5"
 "source/extensions/filters/http/cache:93.4"
@@ -58,12 +56,12 @@ declare -a KNOWN_LOW_COVERAGE=(
 "source/extensions/stat_sinks/statsd:84.6"
 "source/extensions/tracers:95.8"
 "source/extensions/tracers/common:73.8"
-"source/extensions/tracers/common/ot:71.7"
+"source/extensions/tracers/common/ot:71.8"
 "source/extensions/tracers/opencensus:93.2"
 "source/extensions/tracers/zipkin:95.8"
-"source/extensions/transport_sockets:95.6"
-"source/extensions/transport_sockets/tls:94.9"
-"source/extensions/transport_sockets/tls/cert_validator:95.1"
+"source/extensions/transport_sockets:95.8"
+"source/extensions/transport_sockets/tls:95.0"
+"source/extensions/transport_sockets/tls/cert_validator:95.2"
 "source/extensions/transport_sockets/tls/private_key:88.9"
 "source/extensions/wasm_runtime/wamr:0.0" # Not enabled in coverage build
 "source/extensions/wasm_runtime/wasmtime:0.0" # Not enabled in coverage build
@@ -73,16 +71,14 @@ declare -a KNOWN_LOW_COVERAGE=(
 "source/extensions/watchdog/profile_action:83.3"
 "source/server:93.8" # flaky: be careful adjusting. See https://github.com/envoyproxy/envoy/issues/15239
 "source/server/admin:profiler-lib:83"
-"source/extensions/load_balancing_policies/common:94" # Death tests don't report LCOV
-"source/server/config_validation:88.2"
+"source/extensions/load_balancing_policies/common:94.1" # Death tests don't report LCOV
+"source/server/config_validation:88.4"
 "source/extensions/health_checkers:95.9"
 "source/extensions/health_checkers/http:93.8"
 "source/extensions/health_checkers/grpc:92.0"
 "source/extensions/load_balancing_policies:95.5"
 "source/extensions/load_balancing_policies/subset:94.3"
 "source/extensions/config_subscription/rest:94.3"
-"source/extensions/config_subscription:94.8"
-"source/extensions/config_subscription/grpc:94.0"
 "source/extensions/matching/input_matchers/cel_matcher:90.7" #Death tests don't report LCOV
 )
 

From d6727d1a1fa43ff7250929786906529d19d1c4c7 Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Tue, 6 Jun 2023 17:34:12 -0400
Subject: [PATCH 192/228] tls: making CertificateValidationContextConfigImpl
 exception free (#27754)

Risk Level: low
Testing: existing tests
Docs Changes: n/a
Release Notes: n/a
Part of envoyproxy/envoy-mobile#176

Signed-off-by: Alyssa Wilk 
---
 ...tificate_validation_context_config_impl.cc | 29 ++++++++++---
 ...rtificate_validation_context_config_impl.h | 16 ++++++--
 .../tls/context_config_impl.cc                | 37 ++++++++++-------
 test/common/secret/sds_api_test.cc            | 29 ++++++-------
 .../common/secret/secret_manager_impl_test.cc | 41 +++++++++++--------
 tools/code_format/config.yaml                 |  1 -
 6 files changed, 97 insertions(+), 56 deletions(-)

diff --git a/source/common/ssl/certificate_validation_context_config_impl.cc b/source/common/ssl/certificate_validation_context_config_impl.cc
index 034409ad38f5..b1249969f8cf 100644
--- a/source/common/ssl/certificate_validation_context_config_impl.cc
+++ b/source/common/ssl/certificate_validation_context_config_impl.cc
@@ -42,20 +42,37 @@ CertificateValidationContextConfigImpl::CertificateValidationContextConfigImpl(
       api_(api), only_verify_leaf_cert_crl_(config.only_verify_leaf_cert_crl()),
       max_verify_depth_(config.has_max_verify_depth()
                             ? absl::optional(config.max_verify_depth().value())
-                            : absl::nullopt) {
+                            : absl::nullopt) {}
+
+absl::StatusOr>
+CertificateValidationContextConfigImpl::create(
+    const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext& context,
+    Api::Api& api) {
+  auto config = std::unique_ptr(
+      new CertificateValidationContextConfigImpl(context, api));
+  absl::Status status = config->initialize();
+  if (status.ok()) {
+    return config;
+  }
+  return status;
+}
+
+absl::Status CertificateValidationContextConfigImpl::initialize() {
   if (ca_cert_.empty() && custom_validator_config_ == absl::nullopt) {
     if (!certificate_revocation_list_.empty()) {
-      throw EnvoyException(fmt::format("Failed to load CRL from {} without trusted CA",
-                                       certificateRevocationListPath()));
+      return absl::InvalidArgumentError(fmt::format("Failed to load CRL from {} without trusted CA",
+                                                    certificateRevocationListPath()));
     }
     if (!subject_alt_name_matchers_.empty()) {
-      throw EnvoyException("SAN-based verification of peer certificates without "
-                           "trusted CA is insecure and not allowed");
+      return absl::InvalidArgumentError("SAN-based verification of peer certificates without "
+                                        "trusted CA is insecure and not allowed");
     }
     if (allow_expired_certificate_) {
-      throw EnvoyException("Certificate validity period is always ignored without trusted CA");
+      return absl::InvalidArgumentError(
+          "Certificate validity period is always ignored without trusted CA");
     }
   }
+  return absl::OkStatus();
 }
 
 std::vector
diff --git a/source/common/ssl/certificate_validation_context_config_impl.h b/source/common/ssl/certificate_validation_context_config_impl.h
index b93d67fe6d3b..b8386f13d366 100644
--- a/source/common/ssl/certificate_validation_context_config_impl.h
+++ b/source/common/ssl/certificate_validation_context_config_impl.h
@@ -8,14 +8,19 @@
 #include "envoy/ssl/certificate_validation_context_config.h"
 #include "envoy/type/matcher/v3/string.pb.h"
 
+#include "absl/status/statusor.h"
+
 namespace Envoy {
 namespace Ssl {
 
 class CertificateValidationContextConfigImpl : public CertificateValidationContextConfig {
 public:
-  CertificateValidationContextConfigImpl(
-      const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext& config,
-      Api::Api& api);
+  // Create a CertificateValidationContextConfigImpl or return an error status.
+  static absl::StatusOr>
+  create(const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext& context,
+         Api::Api& api);
+
+  absl::Status initialize();
 
   const std::string& caCert() const override { return ca_cert_; }
   const std::string& caCertPath() const override { return ca_cert_path_; }
@@ -53,6 +58,11 @@ class CertificateValidationContextConfigImpl : public CertificateValidationConte
 
   absl::optional maxVerifyDepth() const override { return max_verify_depth_; }
 
+protected:
+  CertificateValidationContextConfigImpl(
+      const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext& config,
+      Api::Api& api);
+
 private:
   static std::vector
   getSubjectAltNameMatchers(
diff --git a/source/extensions/transport_sockets/tls/context_config_impl.cc b/source/extensions/transport_sockets/tls/context_config_impl.cc
index 021c1d881fea..e19dc26c9d3d 100644
--- a/source/extensions/transport_sockets/tls/context_config_impl.cc
+++ b/source/extensions/transport_sockets/tls/context_config_impl.cc
@@ -90,17 +90,12 @@ getCertificateValidationContextConfigProvider(
         default_cvc) {
   switch (config.validation_context_type_case()) {
   case envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::ValidationContextTypeCase::
-      kValidationContext: {
-    auto secret_provider =
-        factory_context.secretManager().createInlineCertificateValidationContextProvider(
-            config.validation_context());
-    return secret_provider;
-  }
+      kValidationContext:
+    return factory_context.secretManager().createInlineCertificateValidationContextProvider(
+        config.validation_context());
   case envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::ValidationContextTypeCase::
-      kValidationContextSdsSecretConfig: {
-    const auto& sds_secret_config = config.validation_context_sds_secret_config();
-    return getProviderFromSds(factory_context, sds_secret_config);
-  }
+      kValidationContextSdsSecretConfig:
+    return getProviderFromSds(factory_context, config.validation_context_sds_secret_config());
   case envoy::extensions::transport_sockets::tls::v3::CommonTlsContext::ValidationContextTypeCase::
       kCombinedValidationContext: {
     *default_cvc = std::make_unique<
@@ -213,8 +208,12 @@ ContextConfigImpl::ContextConfigImpl(
         validation_context_config_ =
             getCombinedValidationContextConfig(*certificate_validation_context_provider_->secret());
       } else {
-        validation_context_config_ = std::make_unique(
+        auto config_or_status = Envoy::Ssl::CertificateValidationContextConfigImpl::create(
             *certificate_validation_context_provider_->secret(), api_);
+        if (!config_or_status.status().ok()) {
+          throw EnvoyException(std::string(config_or_status.status().message()));
+        }
+        validation_context_config_ = std::move(config_or_status.value());
       }
     }
   }
@@ -255,7 +254,12 @@ Ssl::CertificateValidationContextConfigPtr ContextConfigImpl::getCombinedValidat
   envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext combined_cvc =
       *default_cvc_;
   combined_cvc.MergeFrom(dynamic_cvc);
-  return std::make_unique(combined_cvc, api_);
+  auto config_or_status =
+      Envoy::Ssl::CertificateValidationContextConfigImpl::create(combined_cvc, api_);
+  if (!config_or_status.status().ok()) {
+    throw EnvoyException(std::string(config_or_status.status().message()));
+  }
+  return std::move(config_or_status.value());
 }
 
 void ContextConfigImpl::setSecretUpdateCallback(std::function callback) {
@@ -291,9 +295,12 @@ void ContextConfigImpl::setSecretUpdateCallback(std::function callback)
       // ContextConfigImpl::validation_context_config_ with new secret.
       cvc_update_callback_handle_ =
           certificate_validation_context_provider_->addUpdateCallback([this, callback]() {
-            validation_context_config_ =
-                std::make_unique(
-                    *certificate_validation_context_provider_->secret(), api_);
+            auto config_or_status = Envoy::Ssl::CertificateValidationContextConfigImpl::create(
+                *certificate_validation_context_provider_->secret(), api_);
+            if (!config_or_status.status().ok()) {
+              throw EnvoyException(std::string(config_or_status.status().message()));
+            }
+            validation_context_config_ = std::move(config_or_status.value());
             callback();
           });
     }
diff --git a/test/common/secret/sds_api_test.cc b/test/common/secret/sds_api_test.cc
index 6cb640f23464..e0fb476c3155 100644
--- a/test/common/secret/sds_api_test.cc
+++ b/test/common/secret/sds_api_test.cc
@@ -629,11 +629,12 @@ TEST_F(SdsApiTest, DynamicCertificateValidationContextUpdateSuccess) {
   initialize();
   subscription_factory_.callbacks_->onConfigUpdate(decoded_resources.refvec_, "");
 
-  Ssl::CertificateValidationContextConfigImpl cvc_config(*sds_api.secret(), *api_);
+  auto cvc_config =
+      Ssl::CertificateValidationContextConfigImpl::create(*sds_api.secret(), *api_).value();
   const std::string ca_cert =
       "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ca_cert.pem";
   EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(ca_cert)),
-            cvc_config.caCert());
+            cvc_config->caCert());
 }
 
 class CvcValidationCallback {
@@ -705,31 +706,31 @@ TEST_F(SdsApiTest, DefaultCertificateValidationContextTest) {
   envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext merged_cvc =
       default_cvc;
   merged_cvc.MergeFrom(*sds_api.secret());
-  Ssl::CertificateValidationContextConfigImpl cvc_config(merged_cvc, *api_);
+  auto cvc_config = Ssl::CertificateValidationContextConfigImpl::create(merged_cvc, *api_).value();
   // Verify that merging CertificateValidationContext applies logical OR to bool
   // field.
-  EXPECT_TRUE(cvc_config.allowExpiredCertificate());
+  EXPECT_TRUE(cvc_config->allowExpiredCertificate());
   // Verify that singular fields are overwritten.
   const std::string ca_cert =
       "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ca_cert.pem";
   EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(ca_cert)),
-            cvc_config.caCert());
+            cvc_config->caCert());
   // Verify that repeated fields are concatenated.
-  EXPECT_EQ(2, cvc_config.subjectAltNameMatchers().size());
-  EXPECT_EQ("first san", cvc_config.subjectAltNameMatchers()[0].matcher().exact());
+  EXPECT_EQ(2, cvc_config->subjectAltNameMatchers().size());
+  EXPECT_EQ("first san", cvc_config->subjectAltNameMatchers()[0].matcher().exact());
   EXPECT_EQ(envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::DNS,
-            cvc_config.subjectAltNameMatchers()[0].san_type());
-  EXPECT_EQ("second san", cvc_config.subjectAltNameMatchers()[1].matcher().exact());
+            cvc_config->subjectAltNameMatchers()[0].san_type());
+  EXPECT_EQ("second san", cvc_config->subjectAltNameMatchers()[1].matcher().exact());
   EXPECT_EQ(envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::DNS,
-            cvc_config.subjectAltNameMatchers()[1].san_type());
+            cvc_config->subjectAltNameMatchers()[1].san_type());
   // Verify that if dynamic CertificateValidationContext does not set certificate hash list, the new
   // secret contains hash list from default CertificateValidationContext.
-  EXPECT_EQ(1, cvc_config.verifyCertificateHashList().size());
-  EXPECT_EQ(default_verify_certificate_hash, cvc_config.verifyCertificateHashList()[0]);
+  EXPECT_EQ(1, cvc_config->verifyCertificateHashList().size());
+  EXPECT_EQ(default_verify_certificate_hash, cvc_config->verifyCertificateHashList()[0]);
   // Verify that if default CertificateValidationContext does not set certificate SPKI list, the new
   // secret contains SPKI list from dynamic CertificateValidationContext.
-  EXPECT_EQ(1, cvc_config.verifyCertificateSpkiList().size());
-  EXPECT_EQ(dynamic_verify_certificate_spki, cvc_config.verifyCertificateSpkiList()[0]);
+  EXPECT_EQ(1, cvc_config->verifyCertificateSpkiList().size());
+  EXPECT_EQ(dynamic_verify_certificate_spki, cvc_config->verifyCertificateSpkiList()[0]);
 }
 
 class GenericSecretValidationCallback {
diff --git a/test/common/secret/secret_manager_impl_test.cc b/test/common/secret/secret_manager_impl_test.cc
index ead2895c984b..87a706c9ec4b 100644
--- a/test/common/secret/secret_manager_impl_test.cc
+++ b/test/common/secret/secret_manager_impl_test.cc
@@ -134,12 +134,15 @@ TEST_F(SecretManagerImplTest, CertificateValidationContextSecretLoadSuccess) {
 
   ASSERT_EQ(secret_manager->findStaticCertificateValidationContextProvider("undefined"), nullptr);
   ASSERT_NE(secret_manager->findStaticCertificateValidationContextProvider("abc.com"), nullptr);
-  Ssl::CertificateValidationContextConfigImpl cvc_config(
-      *secret_manager->findStaticCertificateValidationContextProvider("abc.com")->secret(), *api_);
+  auto cvc_config =
+      Ssl::CertificateValidationContextConfigImpl::create(
+          *secret_manager->findStaticCertificateValidationContextProvider("abc.com")->secret(),
+          *api_)
+          .value();
   const std::string cert_pem =
       "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ca_cert.pem";
   EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(cert_pem)),
-            cvc_config.caCert());
+            cvc_config->caCert());
 }
 
 // Validate that secret manager throws an exception when adding duplicated static certificate
@@ -526,9 +529,10 @@ name: "abc.com.validation"
   init_target_handle->initialize(init_watcher);
   secret_context.cluster_manager_.subscription_factory_.callbacks_->onConfigUpdate(
       decoded_resources_2.refvec_, "validation-context-v1");
-  Ssl::CertificateValidationContextConfigImpl cert_validation_context(
-      *context_secret_provider->secret(), *api_);
-  EXPECT_EQ("DUMMY_INLINE_STRING_TRUSTED_CA", cert_validation_context.caCert());
+  auto cert_validation_context =
+      Ssl::CertificateValidationContextConfigImpl::create(*context_secret_provider->secret(), *api_)
+          .value();
+  EXPECT_EQ("DUMMY_INLINE_STRING_TRUSTED_CA", cert_validation_context->caCert());
   const std::string updated_config_dump = R"EOF(
 dynamic_active_secrets:
 - name: "abc.com"
@@ -1140,21 +1144,24 @@ TEST_F(SecretManagerImplTest, DeprecatedSanMatcher) {
 
   ASSERT_EQ(secret_manager->findStaticCertificateValidationContextProvider("undefined"), nullptr);
   ASSERT_NE(secret_manager->findStaticCertificateValidationContextProvider("abc.com"), nullptr);
-  Ssl::CertificateValidationContextConfigImpl cvc_config(
-      *secret_manager->findStaticCertificateValidationContextProvider("abc.com")->secret(), *api_);
-  EXPECT_EQ(cvc_config.subjectAltNameMatchers().size(), 4);
-  EXPECT_EQ("example.foo", cvc_config.subjectAltNameMatchers()[0].matcher().exact());
+  auto cvc_config =
+      Ssl::CertificateValidationContextConfigImpl::create(
+          *secret_manager->findStaticCertificateValidationContextProvider("abc.com")->secret(),
+          *api_)
+          .value();
+  EXPECT_EQ(cvc_config->subjectAltNameMatchers().size(), 4);
+  EXPECT_EQ("example.foo", cvc_config->subjectAltNameMatchers()[0].matcher().exact());
   EXPECT_EQ(envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::DNS,
-            cvc_config.subjectAltNameMatchers()[0].san_type());
-  EXPECT_EQ("example.foo", cvc_config.subjectAltNameMatchers()[1].matcher().exact());
+            cvc_config->subjectAltNameMatchers()[0].san_type());
+  EXPECT_EQ("example.foo", cvc_config->subjectAltNameMatchers()[1].matcher().exact());
   EXPECT_EQ(envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::URI,
-            cvc_config.subjectAltNameMatchers()[1].san_type());
-  EXPECT_EQ("example.foo", cvc_config.subjectAltNameMatchers()[2].matcher().exact());
+            cvc_config->subjectAltNameMatchers()[1].san_type());
+  EXPECT_EQ("example.foo", cvc_config->subjectAltNameMatchers()[2].matcher().exact());
   EXPECT_EQ(envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::EMAIL,
-            cvc_config.subjectAltNameMatchers()[2].san_type());
-  EXPECT_EQ("example.foo", cvc_config.subjectAltNameMatchers()[3].matcher().exact());
+            cvc_config->subjectAltNameMatchers()[2].san_type());
+  EXPECT_EQ("example.foo", cvc_config->subjectAltNameMatchers()[3].matcher().exact());
   EXPECT_EQ(envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::IP_ADDRESS,
-            cvc_config.subjectAltNameMatchers()[3].san_type());
+            cvc_config->subjectAltNameMatchers()[3].san_type());
 }
 
 } // namespace
diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml
index f9c7f231773c..c189b2c994c1 100644
--- a/tools/code_format/config.yaml
+++ b/tools/code_format/config.yaml
@@ -117,7 +117,6 @@ paths:
     - source/common/network/lc_trie.h
     - source/common/network/socket_impl.cc
     - source/common/ssl/tls_certificate_config_impl.cc
-    - source/common/ssl/certificate_validation_context_config_impl.cc
     - source/common/formatter/substitution_formatter.cc
     - source/common/formatter/substitution_format_string.cc
     - source/common/stats/tag_extractor_impl.cc

From 6b99feb17872146adeb4fc3d5a9c26b9ab4ef996 Mon Sep 17 00:00:00 2001
From: Rama Chavali 
Date: Wed, 7 Jun 2023 06:22:37 +0530
Subject: [PATCH 193/228] add support for additional cookie attributes (#27529)

Signed-off-by: Rama Chavali 
---
 .../config/route/v3/route_components.proto    | 15 ++++++
 changelogs/current.yaml                       |  5 +-
 envoy/http/hash_policy.h                      | 20 +++++++-
 source/common/http/hash_policy.cc             | 18 +++++--
 source/common/http/utility.cc                 | 12 ++++-
 source/common/http/utility.h                  |  2 +-
 source/common/router/router.h                 | 11 ++--
 .../http/stateful_session/cookie/BUILD        |  1 +
 .../http/stateful_session/cookie/cookie.h     |  4 +-
 test/common/http/utility_fuzz_test.cc         |  3 +-
 test/common/http/utility_test.cc              | 37 +++++++++++---
 test/common/router/config_impl_test.cc        | 51 +++++++++++--------
 test/common/router/router_test.cc             | 12 +++--
 .../stateful_session_integration_test.cc      | 16 +++---
 .../stateful_session/cookie/cookie_test.cc    |  7 +--
 15 files changed, 156 insertions(+), 58 deletions(-)

diff --git a/api/envoy/config/route/v3/route_components.proto b/api/envoy/config/route/v3/route_components.proto
index 56686a096050..7153a100772a 100644
--- a/api/envoy/config/route/v3/route_components.proto
+++ b/api/envoy/config/route/v3/route_components.proto
@@ -833,6 +833,18 @@ message RouteAction {
       type.matcher.v3.RegexMatchAndSubstitute regex_rewrite = 2;
     }
 
+    // CookieAttribute defines an API for adding additional attributes for a HTTP cookie.
+    message CookieAttribute {
+      // The name of the cookie attribute.
+      string name = 1
+          [(validate.rules).string =
+               {min_len: 1 max_bytes: 16384 well_known_regex: HTTP_HEADER_NAME strict: false}];
+
+      // The optional value of the cookie attribute.
+      string value = 2 [(validate.rules).string =
+                            {max_bytes: 16384 well_known_regex: HTTP_HEADER_VALUE strict: false}];
+    }
+
     // Envoy supports two types of cookie affinity:
     //
     // 1. Passive. Envoy takes a cookie that's present in the cookies header and
@@ -864,6 +876,9 @@ message RouteAction {
       // The name of the path for the cookie. If no path is specified here, no path
       // will be set for the cookie.
       string path = 3;
+
+      // Additional attributes for the cookie. They will be used when generating a new cookie.
+      repeated CookieAttribute attributes = 4;
     }
 
     message ConnectionProperties {
diff --git a/changelogs/current.yaml b/changelogs/current.yaml
index 39444ae95ea7..841fea503761 100644
--- a/changelogs/current.yaml
+++ b/changelogs/current.yaml
@@ -309,7 +309,7 @@ new_features:
 - area: ext_proc
   change: |
     added new field ``filter_metadata `
@@ -320,6 +320,9 @@ new_features:
     This works with dynamic secrets when
     :ref:`CertificateValidationContext `
     is delivered via SDS.
+- area: http
+  change: |
+    added support for configuring additional :ref:`cookie attributes `.
 
 deprecated:
 - area: access_log
diff --git a/envoy/http/hash_policy.h b/envoy/http/hash_policy.h
index de04a8eecfa2..3a8e17ffc80c 100644
--- a/envoy/http/hash_policy.h
+++ b/envoy/http/hash_policy.h
@@ -9,6 +9,23 @@
 namespace Envoy {
 namespace Http {
 
+/**
+ * CookieAttribute that stores the name and value of a cookie.
+ */
+class CookieAttribute {
+public:
+  CookieAttribute(const std::string& name, const std::string& value) : name_(name), value_(value) {}
+
+  std::string name() const { return name_; }
+  std::string value() const { return value_; }
+
+private:
+  std::string name_;
+  std::string value_;
+};
+
+using CookieAttributeRefVector = std::vector>;
+
 /**
  * Request hash policy. I.e., if using a hashing load balancer, how a request should be hashed onto
  * an upstream host.
@@ -25,7 +42,8 @@ class HashPolicy {
    * @return std::string the opaque value of the cookie that will be set
    */
   using AddCookieCallback = std::function;
+      const std::string& key, const std::string& path, std::chrono::seconds ttl,
+      const CookieAttributeRefVector attributes)>;
 
   /**
    * @param downstream_address is the address of the connected client host, or nullptr if the
diff --git a/source/common/http/hash_policy.cc b/source/common/http/hash_policy.cc
index a12d5730a085..ca97775f318e 100644
--- a/source/common/http/hash_policy.cc
+++ b/source/common/http/hash_policy.cc
@@ -80,8 +80,9 @@ class HeaderHashMethod : public HashMethodImplBase {
 class CookieHashMethod : public HashMethodImplBase {
 public:
   CookieHashMethod(const std::string& key, const std::string& path,
-                   const absl::optional& ttl, bool terminal)
-      : HashMethodImplBase(terminal), key_(key), path_(path), ttl_(ttl) {}
+                   const absl::optional& ttl, bool terminal,
+                   const CookieAttributeRefVector attributes)
+      : HashMethodImplBase(terminal), key_(key), path_(path), ttl_(ttl), attributes_(attributes) {}
 
   absl::optional evaluate(const Network::Address::Instance*,
                                     const RequestHeaderMap& headers,
@@ -90,7 +91,7 @@ class CookieHashMethod : public HashMethodImplBase {
     absl::optional hash;
     std::string value = Utility::parseCookieValue(headers, key_);
     if (value.empty() && ttl_.has_value()) {
-      value = add_cookie(key_, path_, ttl_.value());
+      value = add_cookie(key_, path_, ttl_.value(), attributes_);
       hash = HashUtil::xxHash64(value);
 
     } else if (!value.empty()) {
@@ -103,6 +104,7 @@ class CookieHashMethod : public HashMethodImplBase {
   const std::string key_;
   const std::string path_;
   const absl::optional ttl_;
+  const CookieAttributeRefVector attributes_;
 };
 
 class IpHashMethod : public HashMethodImplBase {
@@ -188,9 +190,17 @@ HashPolicyImpl::HashPolicyImpl(
       if (hash_policy->cookie().has_ttl()) {
         ttl = std::chrono::seconds(hash_policy->cookie().ttl().seconds());
       }
+      std::vector attributes;
+      for (const auto& attribute : hash_policy->cookie().attributes()) {
+        attributes.push_back({attribute.name(), attribute.value()});
+      }
+      CookieAttributeRefVector ref_attributes;
+      for (const auto& attribute : attributes) {
+        ref_attributes.push_back(attribute);
+      }
       hash_impls_.emplace_back(new CookieHashMethod(hash_policy->cookie().name(),
                                                     hash_policy->cookie().path(), ttl,
-                                                    hash_policy->terminal()));
+                                                    hash_policy->terminal(), ref_attributes));
       break;
     }
     case envoy::config::route::v3::RouteAction::HashPolicy::PolicySpecifierCase::
diff --git a/source/common/http/utility.cc b/source/common/http/utility.cc
index b805297d5e14..cfc300b18d22 100644
--- a/source/common/http/utility.cc
+++ b/source/common/http/utility.cc
@@ -588,7 +588,8 @@ std::string Utility::parseSetCookieValue(const Http::HeaderMap& headers, const s
 
 std::string Utility::makeSetCookieValue(const std::string& key, const std::string& value,
                                         const std::string& path, const std::chrono::seconds max_age,
-                                        bool httponly) {
+                                        bool httponly,
+                                        const Http::CookieAttributeRefVector attributes) {
   std::string cookie_value;
   // Best effort attempt to avoid numerous string copies.
   cookie_value.reserve(value.size() + path.size() + 30);
@@ -600,6 +601,15 @@ std::string Utility::makeSetCookieValue(const std::string& key, const std::strin
   if (!path.empty()) {
     absl::StrAppend(&cookie_value, "; Path=", path);
   }
+
+  for (auto const& attribute : attributes) {
+    if (attribute.get().value().empty()) {
+      absl::StrAppend(&cookie_value, "; ", attribute.get().name());
+    } else {
+      absl::StrAppend(&cookie_value, "; ", attribute.get().name(), "=", attribute.get().value());
+    }
+  }
+
   if (httponly) {
     absl::StrAppend(&cookie_value, "; HttpOnly");
   }
diff --git a/source/common/http/utility.h b/source/common/http/utility.h
index 76a708b773ca..87ec1cd02398 100644
--- a/source/common/http/utility.h
+++ b/source/common/http/utility.h
@@ -364,7 +364,7 @@ std::string parseSetCookieValue(const HeaderMap& headers, const std::string& key
  */
 std::string makeSetCookieValue(const std::string& key, const std::string& value,
                                const std::string& path, const std::chrono::seconds max_age,
-                               bool httponly);
+                               bool httponly, const Http::CookieAttributeRefVector attributes);
 
 /**
  * Get the response status from the response headers.
diff --git a/source/common/router/router.h b/source/common/router/router.h
index c3c3b61c8180..ad75603b1740 100644
--- a/source/common/router/router.h
+++ b/source/common/router/router.h
@@ -13,6 +13,7 @@
 #include "envoy/http/codes.h"
 #include "envoy/http/filter.h"
 #include "envoy/http/filter_factory.h"
+#include "envoy/http/hash_policy.h"
 #include "envoy/http/stateful_session.h"
 #include "envoy/local_info/local_info.h"
 #include "envoy/router/shadow_writer.h"
@@ -408,8 +409,9 @@ class Filter : Logger::Loggable,
         return hash_policy->generateHash(
             callbacks_->streamInfo().downstreamAddressProvider().remoteAddress().get(),
             *downstream_headers_,
-            [this](const std::string& key, const std::string& path, std::chrono::seconds max_age) {
-              return addDownstreamSetCookie(key, path, max_age);
+            [this](const std::string& key, const std::string& path, std::chrono::seconds max_age,
+                   Http::CookieAttributeRefVector attributes) {
+              return addDownstreamSetCookie(key, path, max_age, attributes);
             },
             callbacks_->streamInfo().filterState());
       }
@@ -500,7 +502,8 @@ class Filter : Logger::Loggable,
    * @return std::string the value of the new cookie
    */
   std::string addDownstreamSetCookie(const std::string& key, const std::string& path,
-                                     std::chrono::seconds max_age) {
+                                     std::chrono::seconds max_age,
+                                     Http::CookieAttributeRefVector attributes) {
     // The cookie value should be the same per connection so that if multiple
     // streams race on the same path, they all receive the same cookie.
     // Since the downstream port is part of the hashed value, multiple HTTP1
@@ -513,7 +516,7 @@ class Filter : Logger::Loggable,
 
     const std::string cookie_value = Hex::uint64ToHex(HashUtil::xxHash64(value));
     downstream_set_cookies_.emplace_back(
-        Http::Utility::makeSetCookieValue(key, cookie_value, path, max_age, true));
+        Http::Utility::makeSetCookieValue(key, cookie_value, path, max_age, true, attributes));
     return cookie_value;
   }
 
diff --git a/source/extensions/http/stateful_session/cookie/BUILD b/source/extensions/http/stateful_session/cookie/BUILD
index 0f267e7cc74c..12229ff205a3 100644
--- a/source/extensions/http/stateful_session/cookie/BUILD
+++ b/source/extensions/http/stateful_session/cookie/BUILD
@@ -16,6 +16,7 @@ envoy_cc_library(
     hdrs = ["cookie.h"],
     deps = [
         ":cookie_encoding_cc_proto",
+        "//envoy/http:hash_policy_interface",
         "//envoy/http:stateful_session_interface",
         "//source/common/common:base64_lib",
         "//source/common/http:headers_lib",
diff --git a/source/extensions/http/stateful_session/cookie/cookie.h b/source/extensions/http/stateful_session/cookie/cookie.h
index a03223c5bc8d..dc580395ae00 100644
--- a/source/extensions/http/stateful_session/cookie/cookie.h
+++ b/source/extensions/http/stateful_session/cookie/cookie.h
@@ -5,6 +5,7 @@
 #include 
 
 #include "envoy/extensions/http/stateful_session/cookie/v3/cookie.pb.h"
+#include "envoy/http/hash_policy.h"
 #include "envoy/http/stateful_session.h"
 
 #include "source/common/common/base64.h"
@@ -90,12 +91,13 @@ class CookieBasedSessionStateFactory : public Envoy::Http::SessionStateFactory {
   }
 
   std::string makeSetCookie(const std::string& address) const {
-    return Envoy::Http::Utility::makeSetCookieValue(name_, address, path_, ttl_, true);
+    return Envoy::Http::Utility::makeSetCookieValue(name_, address, path_, ttl_, true, attributes_);
   }
 
   const std::string name_;
   const std::chrono::seconds ttl_;
   const std::string path_;
+  const Envoy::Http::CookieAttributeRefVector attributes_;
   TimeSource& time_source_;
 
   std::function path_matcher_;
diff --git a/test/common/http/utility_fuzz_test.cc b/test/common/http/utility_fuzz_test.cc
index ca362680fb9f..dc311df0bf07 100644
--- a/test/common/http/utility_fuzz_test.cc
+++ b/test/common/http/utility_fuzz_test.cc
@@ -71,8 +71,9 @@ DEFINE_PROTO_FUZZER(const test::common::http::UtilityTestCase& input) {
   case test::common::http::UtilityTestCase::kMakeSetCookieValue: {
     const auto& cookie_value = input.make_set_cookie_value();
     std::chrono::seconds max_age(cookie_value.max_age());
+    Http::CookieAttributeRefVector cookie_attributes;
     Http::Utility::makeSetCookieValue(cookie_value.key(), cookie_value.value(), cookie_value.path(),
-                                      max_age, cookie_value.httponly());
+                                      max_age, cookie_value.httponly(), cookie_attributes);
     break;
   }
   case test::common::http::UtilityTestCase::kParseAuthorityString: {
diff --git a/test/common/http/utility_test.cc b/test/common/http/utility_test.cc
index 43f8bb41e6af..63beeea63e0e 100644
--- a/test/common/http/utility_test.cc
+++ b/test/common/http/utility_test.cc
@@ -912,23 +912,44 @@ TEST(HttpUtility, TestParseSetCookieWithQuotes) {
 }
 
 TEST(HttpUtility, TestMakeSetCookieValue) {
+  CookieAttributeRefVector ref_attributes;
   EXPECT_EQ("name=\"value\"; Max-Age=10",
-            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds(10), false));
+            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds(10), false,
+                                        ref_attributes));
   EXPECT_EQ("name=\"value\"",
-            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds::zero(), false));
+            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds::zero(), false,
+                                        ref_attributes));
   EXPECT_EQ("name=\"value\"; Max-Age=10; HttpOnly",
-            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds(10), true));
+            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds(10), true,
+                                        ref_attributes));
   EXPECT_EQ("name=\"value\"; HttpOnly",
-            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds::zero(), true));
+            Utility::makeSetCookieValue("name", "value", "", std::chrono::seconds::zero(), true,
+                                        ref_attributes));
 
   EXPECT_EQ("name=\"value\"; Max-Age=10; Path=/",
-            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds(10), false));
+            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds(10), false,
+                                        ref_attributes));
   EXPECT_EQ("name=\"value\"; Path=/",
-            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds::zero(), false));
+            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds::zero(), false,
+                                        ref_attributes));
   EXPECT_EQ("name=\"value\"; Max-Age=10; Path=/; HttpOnly",
-            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds(10), true));
+            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds(10), true,
+                                        ref_attributes));
   EXPECT_EQ("name=\"value\"; Path=/; HttpOnly",
-            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds::zero(), true));
+            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds::zero(), true,
+                                        ref_attributes));
+
+  std::vector attributes;
+  attributes.push_back({"SameSite", "None"});
+  attributes.push_back({"Secure", ""});
+  attributes.push_back({"Partitioned", ""});
+  for (const auto& attribute : attributes) {
+    ref_attributes.push_back(attribute);
+  }
+
+  EXPECT_EQ("name=\"value\"; Path=/; SameSite=None; Secure; Partitioned; HttpOnly",
+            Utility::makeSetCookieValue("name", "value", "/", std::chrono::seconds::zero(), true,
+                                        ref_attributes));
 }
 
 TEST(HttpUtility, SendLocalReply) {
diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc
index dae94a11bb91..1ad203edca0b 100644
--- a/test/common/router/config_impl_test.cc
+++ b/test/common/router/config_impl_test.cc
@@ -2814,8 +2814,8 @@ TEST_F(RouteMatcherTest, DynamicMetadataMatchedRouting) {
 class RouterMatcherHashPolicyTest : public testing::Test, public ConfigImplTestBase {
 protected:
   RouterMatcherHashPolicyTest()
-      : add_cookie_nop_(
-            [](const std::string&, const std::string&, std::chrono::seconds) { return ""; }) {
+      : add_cookie_nop_([](const std::string&, const std::string&, std::chrono::seconds,
+                           const Http::CookieAttributeRefVector) { return ""; }) {
     const std::string yaml = R"EOF(
 virtual_hosts:
 - name: local_service
@@ -2977,16 +2977,19 @@ TEST_F(RouterMatcherCookieHashPolicyTest, DifferentCookies) {
 TEST_F(RouterMatcherCookieHashPolicyTest, TtlSet) {
   firstRouteHashPolicy()->mutable_cookie()->mutable_ttl()->set_seconds(42);
 
-  MockFunction mock_cookie_cb;
-  auto add_cookie = [&mock_cookie_cb](const std::string& name, const std::string& path,
-                                      std::chrono::seconds ttl) -> std::string {
-    return mock_cookie_cb.Call(name, path, ttl.count());
+  MockFunction
+      mock_cookie_cb;
+  auto add_cookie =
+      [&mock_cookie_cb](const std::string& name, const std::string& path, std::chrono::seconds ttl,
+                        const Http::CookieAttributeRefVector& attributes) -> std::string {
+    return mock_cookie_cb.Call(name, path, ttl.count(), attributes);
   };
 
   {
     Http::TestRequestHeaderMapImpl headers = genHeaders("www.lyft.com", "/foo", "GET");
     Router::RouteConstSharedPtr route = config().route(headers, 0);
-    EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42));
+    EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42, _));
     EXPECT_TRUE(
         route->routeEntry()->hashPolicy()->generateHash(nullptr, headers, add_cookie, nullptr));
   }
@@ -2994,7 +2997,7 @@ TEST_F(RouterMatcherCookieHashPolicyTest, TtlSet) {
     Http::TestRequestHeaderMapImpl headers = genHeaders("www.lyft.com", "/foo", "GET");
     headers.addCopy("Cookie", "choco=late; su=gar");
     Router::RouteConstSharedPtr route = config().route(headers, 0);
-    EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42));
+    EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42, _));
     EXPECT_TRUE(
         route->routeEntry()->hashPolicy()->generateHash(nullptr, headers, add_cookie, nullptr));
   }
@@ -3010,7 +3013,7 @@ TEST_F(RouterMatcherCookieHashPolicyTest, TtlSet) {
     {
       Http::TestRequestHeaderMapImpl headers = genHeaders("www.lyft.com", "/foo", "GET");
       Router::RouteConstSharedPtr route = config().route(headers, 0);
-      EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42)).WillOnce(Return("AAAAAAA"));
+      EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42, _)).WillOnce(Return("AAAAAAA"));
       hash_1 = route->routeEntry()
                    ->hashPolicy()
                    ->generateHash(nullptr, headers, add_cookie, nullptr)
@@ -3019,7 +3022,7 @@ TEST_F(RouterMatcherCookieHashPolicyTest, TtlSet) {
     {
       Http::TestRequestHeaderMapImpl headers = genHeaders("www.lyft.com", "/foo", "GET");
       Router::RouteConstSharedPtr route = config().route(headers, 0);
-      EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42)).WillOnce(Return("BBBBBBB"));
+      EXPECT_CALL(mock_cookie_cb, Call("hash", "", 42, _)).WillOnce(Return("BBBBBBB"));
       hash_2 = route->routeEntry()
                    ->hashPolicy()
                    ->generateHash(nullptr, headers, add_cookie, nullptr)
@@ -3036,17 +3039,19 @@ TEST_F(RouterMatcherCookieHashPolicyTest, TtlSet) {
 
 TEST_F(RouterMatcherCookieHashPolicyTest, SetSessionCookie) {
   firstRouteHashPolicy()->mutable_cookie()->mutable_ttl()->set_seconds(0);
-
-  MockFunction mock_cookie_cb;
-  auto add_cookie = [&mock_cookie_cb](const std::string& name, const std::string& path,
-                                      std::chrono::seconds ttl) -> std::string {
-    return mock_cookie_cb.Call(name, path, ttl.count());
+  MockFunction
+      mock_cookie_cb;
+  auto add_cookie =
+      [&mock_cookie_cb](const std::string& name, const std::string& path, std::chrono::seconds ttl,
+                        const Http::CookieAttributeRefVector attributes) -> std::string {
+    return mock_cookie_cb.Call(name, path, ttl.count(), attributes);
   };
 
   {
     Http::TestRequestHeaderMapImpl headers = genHeaders("www.lyft.com", "/foo", "GET");
     Router::RouteConstSharedPtr route = config().route(headers, 0);
-    EXPECT_CALL(mock_cookie_cb, Call("hash", "", 0));
+    EXPECT_CALL(mock_cookie_cb, Call("hash", "", 0, _));
     EXPECT_TRUE(
         route->routeEntry()->hashPolicy()->generateHash(nullptr, headers, add_cookie, nullptr));
   }
@@ -3055,17 +3060,19 @@ TEST_F(RouterMatcherCookieHashPolicyTest, SetSessionCookie) {
 TEST_F(RouterMatcherCookieHashPolicyTest, SetCookiePath) {
   firstRouteHashPolicy()->mutable_cookie()->mutable_ttl()->set_seconds(0);
   firstRouteHashPolicy()->mutable_cookie()->set_path("/");
-
-  MockFunction mock_cookie_cb;
-  auto add_cookie = [&mock_cookie_cb](const std::string& name, const std::string& path,
-                                      std::chrono::seconds ttl) -> std::string {
-    return mock_cookie_cb.Call(name, path, ttl.count());
+  MockFunction
+      mock_cookie_cb;
+  auto add_cookie =
+      [&mock_cookie_cb](const std::string& name, const std::string& path, std::chrono::seconds ttl,
+                        const Http::CookieAttributeRefVector attributes) -> std::string {
+    return mock_cookie_cb.Call(name, path, ttl.count(), attributes);
   };
 
   {
     Http::TestRequestHeaderMapImpl headers = genHeaders("www.lyft.com", "/foo", "GET");
     Router::RouteConstSharedPtr route = config().route(headers, 0);
-    EXPECT_CALL(mock_cookie_cb, Call("hash", "/", 0));
+    EXPECT_CALL(mock_cookie_cb, Call("hash", "/", 0, _));
     EXPECT_TRUE(
         route->routeEntry()->hashPolicy()->generateHash(nullptr, headers, add_cookie, nullptr));
   }
diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc
index 82f7711cb50c..bada575c09e5 100644
--- a/test/common/router/router_test.cc
+++ b/test/common/router/router_test.cc
@@ -549,11 +549,12 @@ TEST_F(RouterTest, AddCookie) {
       }));
 
   std::string cookie_value;
+  Http::CookieAttributeRefVector cookie_attributes;
   EXPECT_CALL(callbacks_.route_->route_entry_.hash_policy_, generateHash(_, _, _, _))
       .WillOnce(Invoke([&](const Network::Address::Instance*, const Http::HeaderMap&,
                            const Http::HashPolicy::AddCookieCallback add_cookie,
                            const StreamInfo::FilterStateSharedPtr) {
-        cookie_value = add_cookie("foo", "", std::chrono::seconds(1337));
+        cookie_value = add_cookie("foo", "", std::chrono::seconds(1337), cookie_attributes);
         return absl::optional(10);
       }));
 
@@ -590,13 +591,13 @@ TEST_F(RouterTest, AddCookieNoDuplicate) {
         EXPECT_EQ(10UL, context->computeHashKey().value());
         return Upstream::HttpPoolData([]() {}, &cm_.thread_local_cluster_.conn_pool_);
       }));
-
+  Http::CookieAttributeRefVector cookie_attributes;
   EXPECT_CALL(callbacks_.route_->route_entry_.hash_policy_, generateHash(_, _, _, _))
       .WillOnce(Invoke([&](const Network::Address::Instance*, const Http::HeaderMap&,
                            const Http::HashPolicy::AddCookieCallback add_cookie,
                            const StreamInfo::FilterStateSharedPtr) {
         // this should be ignored
-        add_cookie("foo", "", std::chrono::seconds(1337));
+        add_cookie("foo", "", std::chrono::seconds(1337), cookie_attributes);
         return absl::optional(10);
       }));
 
@@ -634,12 +635,13 @@ TEST_F(RouterTest, AddMultipleCookies) {
       }));
 
   std::string choco_c, foo_c;
+  Http::CookieAttributeRefVector cookie_attributes;
   EXPECT_CALL(callbacks_.route_->route_entry_.hash_policy_, generateHash(_, _, _, _))
       .WillOnce(Invoke([&](const Network::Address::Instance*, const Http::HeaderMap&,
                            const Http::HashPolicy::AddCookieCallback add_cookie,
                            const StreamInfo::FilterStateSharedPtr) {
-        choco_c = add_cookie("choco", "", std::chrono::seconds(15));
-        foo_c = add_cookie("foo", "/path", std::chrono::seconds(1337));
+        choco_c = add_cookie("choco", "", std::chrono::seconds(15), cookie_attributes);
+        foo_c = add_cookie("foo", "/path", std::chrono::seconds(1337), cookie_attributes);
         return absl::optional(10);
       }));
 
diff --git a/test/extensions/filters/http/stateful_session/stateful_session_integration_test.cc b/test/extensions/filters/http/stateful_session/stateful_session_integration_test.cc
index 6aed8fffc6f3..a35a9a59d642 100644
--- a/test/extensions/filters/http/stateful_session/stateful_session_integration_test.cc
+++ b/test/extensions/filters/http/stateful_session/stateful_session_integration_test.cc
@@ -222,9 +222,11 @@ TEST_F(StatefulSessionIntegrationTest, NormalStatefulSession) {
     } else {
       const std::string encoded_address =
           Envoy::Base64::encode(address_string.data(), address_string.size());
+      Http::CookieAttributeRefVector cookie_attributes;
       EXPECT_EQ(
           Envoy::Http::Utility::makeSetCookieValue("global-session-cookie", encoded_address,
-                                                   "/test", std::chrono::seconds(120), true),
+                                                   "/test", std::chrono::seconds(120), true,
+                                                   cookie_attributes),
           response->headers().get(Http::LowerCaseString("set-cookie"))[0]->value().getStringView());
     }
     cleanupUpstreamAndDownstream();
@@ -421,10 +423,11 @@ TEST_F(StatefulSessionIntegrationTest, DownstreamRequestWithStatefulSessionCooki
                   ProtoCookieObject(address_string, 120, "/test", "HttpOnly"));
       } else {
         encoded_address = Envoy::Base64::encode(address_string.data(), address_string.size());
+        Http::CookieAttributeRefVector cookie_attributes;
         // The selected upstream server address would be selected to the response headers.
         EXPECT_EQ(Envoy::Http::Utility::makeSetCookieValue("global-session-cookie", encoded_address,
-                                                           "/test", std::chrono::seconds(120),
-                                                           true),
+                                                           "/test", std::chrono::seconds(120), true,
+                                                           cookie_attributes),
                   response->headers()
                       .get(Http::LowerCaseString("set-cookie"))[0]
                       ->value()
@@ -761,9 +764,10 @@ TEST_F(StatefulSessionIntegrationTest, CookieStatefulSessionOverriddenByRoute) {
       } else {
         const std::string route_encoded_address =
             Envoy::Base64::encode(route_address_string.data(), route_address_string.size());
-        EXPECT_EQ(Envoy::Http::Utility::makeSetCookieValue("route-session-cookie",
-                                                           route_encoded_address, "/test",
-                                                           std::chrono::seconds(120), true),
+        Http::CookieAttributeRefVector cookie_attributes;
+        EXPECT_EQ(Envoy::Http::Utility::makeSetCookieValue(
+                      "route-session-cookie", route_encoded_address, "/test",
+                      std::chrono::seconds(120), true, cookie_attributes),
                   response->headers()
                       .get(Http::LowerCaseString("set-cookie"))[0]
                       ->value()
diff --git a/test/extensions/http/stateful_session/cookie/cookie_test.cc b/test/extensions/http/stateful_session/cookie/cookie_test.cc
index 4420b98bb856..866edd4fd84a 100644
--- a/test/extensions/http/stateful_session/cookie/cookie_test.cc
+++ b/test/extensions/http/stateful_session/cookie/cookie_test.cc
@@ -63,12 +63,12 @@ TEST(CookieBasedSessionStateFactoryTest, SessionStateTest) {
       Envoy::Http::TestResponseHeaderMapImpl response_headers;
       // Check the format of the cookie sent back to client.
       session_state->onUpdate(mock_host, response_headers);
-
+      Envoy::Http::CookieAttributeRefVector cookie_attributes;
       EXPECT_EQ(response_headers.get_("set-cookie"),
                 Envoy::Http::Utility::makeSetCookieValue(
                     "override_host",
                     Envoy::Base64::encode(cookie_content.c_str(), cookie_content.length()), "",
-                    std::chrono::seconds(0), true));
+                    std::chrono::seconds(0), true, cookie_attributes));
     }
   }
 
@@ -128,11 +128,12 @@ TEST(CookieBasedSessionStateFactoryTest, SessionStateTest) {
       } else {
         cookie_content = "2.3.4.5:80";
       }
+      Envoy::Http::CookieAttributeRefVector cookie_attributes;
       EXPECT_EQ(response_headers.get_("set-cookie"),
                 Envoy::Http::Utility::makeSetCookieValue(
                     "override_host",
                     Envoy::Base64::encode(cookie_content.c_str(), cookie_content.length()), "/path",
-                    std::chrono::seconds(5), true));
+                    std::chrono::seconds(5), true, cookie_attributes));
     }
   }
   {

From 91a95cf1651bbac8c629b0903313e924e6ec6b03 Mon Sep 17 00:00:00 2001
From: code 
Date: Wed, 7 Jun 2023 09:39:54 +0800
Subject: [PATCH 194/228] upstream: the subset load balancing policy could be
 configured as extension (#27593)

* upstream: update interface of TypedLoadBalancerFactory to support hierarchical lb

Signed-off-by: wbpcode 

* subset lb: split child lb creation out to separated creator

Signed-off-by: wbpcode 

* subset lb: complete the development of lb

Signed-off-by: wbpcode 

* complete test of subset

Signed-off-by: wbpcode 

* fix docs

Signed-off-by: wbpcode 

* resolve conflict after merge main

Signed-off-by: wbpcode 

* fix type url in extension file

Signed-off-by: wbpcode 

* remove unnecessary comment

Signed-off-by: wbpcode 

* add more test for coverage

Signed-off-by: wbpcode 

---------

Signed-off-by: wbpcode 
---
 .../subset/v3/subset.proto                    |  17 +-
 .../upstream/load_balancing/subsets.rst       |   1 -
 envoy/upstream/load_balancer.h                |  30 ++-
 envoy/upstream/upstream.h                     |   7 +-
 .../common/upstream/cluster_manager_impl.cc   |  11 +-
 source/common/upstream/cluster_manager_impl.h |   7 +-
 .../upstream/load_balancer_factory_base.h     |  22 +-
 source/common/upstream/upstream_impl.cc       |   8 +-
 source/common/upstream/upstream_impl.h        |   6 +-
 source/extensions/extensions_metadata.yaml    |   2 +
 .../cluster_provided/config.cc                |   3 +-
 .../cluster_provided/config.h                 |   3 +-
 .../load_balancing_policies/common/BUILD      |   1 +
 .../common/factory_base.h                     |  38 ++--
 .../least_request/config.cc                   |  18 +-
 .../least_request/config.h                    |  16 +-
 .../load_balancing_policies/maglev/config.cc  |  23 ++-
 .../load_balancing_policies/maglev/config.h   |   8 +-
 .../load_balancing_policies/random/config.cc  |  18 +-
 .../load_balancing_policies/random/config.h   |  13 +-
 .../ring_hash/config.cc                       |  23 ++-
 .../ring_hash/config.h                        |   8 +-
 .../round_robin/config.cc                     |  18 +-
 .../round_robin/config.h                      |  15 +-
 .../load_balancing_policies/subset/BUILD      |   2 +
 .../load_balancing_policies/subset/config.cc  | 161 ++++++++++++++-
 .../load_balancing_policies/subset/config.h   |  17 ++
 .../subset/subset_lb.cc                       | 151 +++++++-------
 .../subset/subset_lb.h                        | 189 +++++++++++++-----
 .../upstream/cluster_manager_impl_test.cc     |   2 +-
 .../upstream/load_balancer_benchmark.cc       |  10 +-
 test/common/upstream/subset_lb_test.cc        | 111 ++++++----
 test/common/upstream/upstream_impl_test.cc    |   2 +-
 .../cluster_provided/config_test.cc           |   2 +-
 .../least_request/config_test.cc              |   7 +-
 .../maglev/config_test.cc                     |  17 +-
 .../random/config_test.cc                     |   7 +-
 .../ring_hash/config_test.cc                  |  13 +-
 .../round_robin/config_test.cc                |   6 +-
 .../load_balancing_policies/subset/BUILD      |  59 ++++++
 .../subset/config_test.cc                     | 114 +++++++++++
 .../subset/integration_test.cc                | 151 ++++++++++++++
 .../subset/subset_test.cc                     |  58 ++++++
 .../load_balancers/custom_lb_policy.h         |   3 +-
 test/mocks/upstream/BUILD                     |   1 +
 test/mocks/upstream/cluster_info.cc           |   3 +-
 test/mocks/upstream/cluster_info.h            |   3 +-
 .../upstream/typed_load_balancer_factory.h    |  12 +-
 48 files changed, 1085 insertions(+), 332 deletions(-)
 create mode 100644 test/extensions/load_balancing_policies/subset/BUILD
 create mode 100644 test/extensions/load_balancing_policies/subset/config_test.cc
 create mode 100644 test/extensions/load_balancing_policies/subset/integration_test.cc
 create mode 100644 test/extensions/load_balancing_policies/subset/subset_test.cc

diff --git a/api/envoy/extensions/load_balancing_policies/subset/v3/subset.proto b/api/envoy/extensions/load_balancing_policies/subset/v3/subset.proto
index 27610c053e13..9e24a6f1d476 100644
--- a/api/envoy/extensions/load_balancing_policies/subset/v3/subset.proto
+++ b/api/envoy/extensions/load_balancing_policies/subset/v3/subset.proto
@@ -18,7 +18,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
 
 // [#protodoc-title: Subset Load Balancing Policy]
 // [#extension: envoy.load_balancing_policies.subset]
-// [#not-implemented-hide:]
 
 // Optionally divide the endpoints in this cluster into subsets defined by
 // endpoint metadata and selected by route and weighted cluster metadata.
@@ -104,7 +103,7 @@ message Subset {
 
       // If KEYS_SUBSET is selected, subset selector matching is performed again with metadata
       // keys reduced to
-      // :ref:`fallback_keys_subset`.
+      // :ref:`fallback_keys_subset`.
       // It allows for a fallback to a different, less specific selector if some of the keys of
       // the selector are considered optional.
       KEYS_SUBSET = 4;
@@ -130,30 +129,30 @@ message Subset {
         [(validate.rules).enum = {defined_only: true}];
 
     // Subset of
-    // :ref:`keys` used by
-    // :ref:`KEYS_SUBSET`
+    // :ref:`keys` used by
+    // :ref:`KEYS_SUBSET`
     // fallback policy.
     // It has to be a non empty list if KEYS_SUBSET fallback policy is selected.
     // For any other fallback policy the parameter is not used and should not be set.
     // Only values also present in
-    // :ref:`keys` are allowed, but
+    // :ref:`keys` are allowed, but
     // ``fallback_keys_subset`` cannot be equal to ``keys``.
     repeated string fallback_keys_subset = 3;
   }
 
   // The behavior used when no endpoint subset matches the selected route's
   // metadata. The value defaults to
-  // :ref:`NO_FALLBACK`.
+  // :ref:`NO_FALLBACK`.
   LbSubsetFallbackPolicy fallback_policy = 1 [(validate.rules).enum = {defined_only: true}];
 
   // Specifies the default subset of endpoints used during fallback if
   // fallback_policy is
-  // :ref:`DEFAULT_SUBSET`.
+  // :ref:`DEFAULT_SUBSET`.
   // Each field in default_subset is
   // compared to the matching LbEndpoint.Metadata under the ``envoy.lb``
   // namespace. It is valid for no hosts to match, in which case the behavior
   // is the same as a fallback_policy of
-  // :ref:`NO_FALLBACK`.
+  // :ref:`NO_FALLBACK`.
   google.protobuf.Struct default_subset = 2;
 
   // For each entry, LbEndpoint.Metadata's
@@ -210,7 +209,7 @@ message Subset {
   //
   // The value defaults to
   // :ref:`METADATA_NO_FALLBACK
-  // `.
+  // `.
   LbSubsetMetadataFallbackPolicy metadata_fallback_policy = 8
       [(validate.rules).enum = {defined_only: true}];
 
diff --git a/docs/root/intro/arch_overview/upstream/load_balancing/subsets.rst b/docs/root/intro/arch_overview/upstream/load_balancing/subsets.rst
index f30ebf03c051..fdef94da57d6 100644
--- a/docs/root/intro/arch_overview/upstream/load_balancing/subsets.rst
+++ b/docs/root/intro/arch_overview/upstream/load_balancing/subsets.rst
@@ -1,5 +1,4 @@
 .. _arch_overview_load_balancer_subsets:
-.. _extension_envoy.load_balancing_policies.subset:
 
 Load Balancer Subsets
 ---------------------
diff --git a/envoy/upstream/load_balancer.h b/envoy/upstream/load_balancer.h
index 0d18614c8e46..c1e4cd48cefe 100644
--- a/envoy/upstream/load_balancer.h
+++ b/envoy/upstream/load_balancer.h
@@ -228,6 +228,15 @@ class ThreadAwareLoadBalancer {
 
 using ThreadAwareLoadBalancerPtr = std::unique_ptr;
 
+/*
+ * Parsed load balancer configuration that will be used to create load balancer.
+ */
+class LoadBalancerConfig {
+public:
+  virtual ~LoadBalancerConfig() = default;
+};
+using LoadBalancerConfigPtr = std::unique_ptr;
+
 /**
  * Factory config for load balancers. To support a load balancing policy of
  * LOAD_BALANCING_POLICY_CONFIG, at least one load balancer factory corresponding to a policy in
@@ -241,15 +250,30 @@ class TypedLoadBalancerFactory : public Config::TypedFactory {
   /**
    * @return ThreadAwareLoadBalancerPtr a new thread-aware load balancer.
    *
+   * @param lb_config supplies the parsed config of the load balancer.
    * @param cluster_info supplies the cluster info.
-   * @param priority_set supplies the priority set.
+   * @param priority_set supplies the priority set on the main thread.
    * @param runtime supplies the runtime loader.
    * @param random supplies the random generator.
    * @param time_source supplies the time source.
    */
   virtual ThreadAwareLoadBalancerPtr
-  create(const ClusterInfo& cluster_info, const PrioritySet& priority_set, Runtime::Loader& runtime,
-         Random::RandomGenerator& random, TimeSource& time_source) PURE;
+  create(OptRef lb_config, const ClusterInfo& cluster_info,
+         const PrioritySet& priority_set, Runtime::Loader& runtime, Random::RandomGenerator& random,
+         TimeSource& time_source) PURE;
+
+  /**
+   * This method is used to validate and create load balancer config from typed proto config.
+   *
+   * @return LoadBalancerConfigPtr a new load balancer config.
+   *
+   * @param config supplies the typed proto config of the load balancer. A dynamic_cast could
+   *        be performed on the config to the expected proto type.
+   * @param visitor supplies the validation visitor that will be used to validate the embedded
+   *        Any proto message.
+   */
+  virtual LoadBalancerConfigPtr loadConfig(ProtobufTypes::MessagePtr config,
+                                           ProtobufMessage::ValidationVisitor& visitor) PURE;
 
   std::string category() const override { return "envoy.load_balancing_policies"; }
 };
diff --git a/envoy/upstream/upstream.h b/envoy/upstream/upstream.h
index 18460c6b6083..32bd2bddda55 100644
--- a/envoy/upstream/upstream.h
+++ b/envoy/upstream/upstream.h
@@ -823,6 +823,7 @@ using ProtocolOptionsConfigConstSharedPtr = std::shared_ptr the validated load balancing policy configuration to
+   * use for this cluster.
    */
-  virtual const ProtobufTypes::MessagePtr& loadBalancingPolicy() const PURE;
+  virtual OptRef loadBalancerConfig() const PURE;
 
   /**
    * @return the load balancer factory for this cluster if the load balancing type is
diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc
index a273a397b791..3a892ed69db1 100644
--- a/source/common/upstream/cluster_manager_impl.cc
+++ b/source/common/upstream/cluster_manager_impl.cc
@@ -909,22 +909,23 @@ ClusterManagerImpl::loadCluster(const envoy::config::cluster::v3::Cluster& clust
       auto& factory = Config::Utility::getAndCheckFactoryByName(
           "envoy.load_balancing_policies.ring_hash");
       cluster_entry_it->second->thread_aware_lb_ = factory.create(
-          *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_);
+          {}, *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_);
     }
   } else if (cluster_info->lbType() == LoadBalancerType::Maglev) {
     if (!cluster_info->lbSubsetInfo().isEnabled()) {
       auto& factory = Config::Utility::getAndCheckFactoryByName(
           "envoy.load_balancing_policies.maglev");
       cluster_entry_it->second->thread_aware_lb_ = factory.create(
-          *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_);
+          {}, *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_);
     }
   } else if (cluster_provided_lb) {
     cluster_entry_it->second->thread_aware_lb_ = std::move(lb);
   } else if (cluster_info->lbType() == LoadBalancerType::LoadBalancingPolicyConfig) {
     TypedLoadBalancerFactory* typed_lb_factory = cluster_info->loadBalancerFactory();
     RELEASE_ASSERT(typed_lb_factory != nullptr, "ClusterInfo should contain a valid factory");
-    cluster_entry_it->second->thread_aware_lb_ = typed_lb_factory->create(
-        *cluster_info, cluster_reference.prioritySet(), runtime_, random_, time_source_);
+    cluster_entry_it->second->thread_aware_lb_ =
+        typed_lb_factory->create(cluster_info->loadBalancerConfig(), *cluster_info,
+                                 cluster_reference.prioritySet(), runtime_, random_, time_source_);
   }
 
   updateClusterCounts();
@@ -1543,7 +1544,7 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::addClusterUpdateCallbacks(
 ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::ClusterEntry(
     ThreadLocalClusterManagerImpl& parent, ClusterInfoConstSharedPtr cluster,
     const LoadBalancerFactorySharedPtr& lb_factory)
-    : parent_(parent), lb_factory_(lb_factory), cluster_info_(cluster),
+    : parent_(parent), cluster_info_(cluster), lb_factory_(lb_factory),
       override_host_statuses_(HostUtility::createOverrideHostStatus(cluster_info_->lbConfig())) {
   priority_set_.getOrCreateHostSet(0);
 
diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h
index 11c44a7365b1..440554a7ea7f 100644
--- a/source/common/upstream/cluster_manager_impl.h
+++ b/source/common/upstream/cluster_manager_impl.h
@@ -560,13 +560,16 @@ class ClusterManagerImpl : public ClusterManager,
 
       ThreadLocalClusterManagerImpl& parent_;
       PrioritySetImpl priority_set_;
+
+      // Don't change the order of cluster_info_ and lb_factory_/lb_ as the the lb_factory_/lb_
+      // may keep a reference to the cluster_info_.
+      ClusterInfoConstSharedPtr cluster_info_;
       // LB factory if applicable. Not all load balancer types have a factory. LB types that have
       // a factory will create a new LB on every membership update. LB types that don't have a
       // factory will create an LB on construction and use it forever.
       LoadBalancerFactorySharedPtr lb_factory_;
       // Current active LB.
       LoadBalancerPtr lb_;
-      ClusterInfoConstSharedPtr cluster_info_;
       Http::AsyncClientPtr lazy_http_async_client_;
       // Stores QUICHE specific objects which live through out the life time of the cluster and can
       // be shared across its hosts.
@@ -677,6 +680,8 @@ class ClusterManagerImpl : public ClusterManager,
     const envoy::config::cluster::v3::Cluster cluster_config_;
     const uint64_t config_hash_;
     const std::string version_info_;
+    // Don't change the order of cluster_ and thread_aware_lb_ as the thread_aware_lb_ may
+    // keep a reference to the cluster_.
     ClusterSharedPtr cluster_;
     // Optional thread aware LB depending on the LB type. Not all clusters have one.
     ThreadAwareLoadBalancerPtr thread_aware_lb_;
diff --git a/source/common/upstream/load_balancer_factory_base.h b/source/common/upstream/load_balancer_factory_base.h
index 6eaa658db555..ae9c066a550b 100644
--- a/source/common/upstream/load_balancer_factory_base.h
+++ b/source/common/upstream/load_balancer_factory_base.h
@@ -5,6 +5,19 @@
 namespace Envoy {
 namespace Upstream {
 
+class LoadBalancerConfigWrapper : public LoadBalancerConfig {
+public:
+  LoadBalancerConfigWrapper(ProtobufTypes::MessagePtr config) : config_(std::move(config)) {}
+
+  template  OptRef typedProtoConfig() const {
+    auto* typed_config = dynamic_cast(config_.get());
+    return makeOptRefFromPtr(typed_config);
+  }
+
+private:
+  ProtobufTypes::MessagePtr config_;
+};
+
 /**
  * Base class for cluster provided load balancers and load balancers specified by load balancing
  * policy config. This class should be extended directly if the load balancing policy specifies a
@@ -18,7 +31,14 @@ template  class TypedLoadBalancerFactoryBase : public TypedLoadBala
   // Upstream::TypedLoadBalancerFactory
   std::string name() const override { return name_; }
 
-  ProtobufTypes::MessagePtr createEmptyConfigProto() override { return std::make_unique(); }
+  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
+    return ProtobufTypes::MessagePtr{new Proto()};
+  }
+
+  LoadBalancerConfigPtr loadConfig(ProtobufTypes::MessagePtr config,
+                                   ProtobufMessage::ValidationVisitor&) override {
+    return std::make_unique(std::move(config));
+  }
 
 protected:
   TypedLoadBalancerFactoryBase(const std::string& name) : name_(name) {}
diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc
index 5bda8581a491..0a36b908f407 100644
--- a/source/common/upstream/upstream_impl.cc
+++ b/source/common/upstream/upstream_impl.cc
@@ -1274,10 +1274,12 @@ void ClusterInfoImpl::configureLbPolicies(const envoy::config::cluster::v3::Clus
             policy.typed_extension_config(), /*is_optional=*/true);
     if (factory != nullptr) {
       // Load and validate the configuration.
-      load_balancing_policy_ = factory->createEmptyConfigProto();
+      auto proto_message = factory->createEmptyConfigProto();
       Config::Utility::translateOpaqueConfig(policy.typed_extension_config().typed_config(),
-                                             context.messageValidationVisitor(),
-                                             *load_balancing_policy_);
+                                             context.messageValidationVisitor(), *proto_message);
+
+      load_balancer_config_ =
+          factory->loadConfig(std::move(proto_message), context.messageValidationVisitor());
 
       load_balancer_factory_ = factory;
       break;
diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h
index ad6f069c86c5..e030299da786 100644
--- a/source/common/upstream/upstream_impl.h
+++ b/source/common/upstream/upstream_impl.h
@@ -790,8 +790,8 @@ class ClusterInfoImpl : public ClusterInfo,
 
   // Upstream::ClusterInfo
   bool addedViaApi() const override { return added_via_api_; }
-  const ProtobufTypes::MessagePtr& loadBalancingPolicy() const override {
-    return load_balancing_policy_;
+  OptRef loadBalancerConfig() const override {
+    return makeOptRefFromPtr(load_balancer_config_.get());
   }
   TypedLoadBalancerFactory* loadBalancerFactory() const override { return load_balancer_factory_; }
   const envoy::config::cluster::v3::Cluster::CommonLbConfig& lbConfig() const override {
@@ -1057,7 +1057,7 @@ class ClusterInfoImpl : public ClusterInfo,
   std::unique_ptr lb_subset_;
   std::unique_ptr metadata_;
   std::unique_ptr typed_metadata_;
-  ProtobufTypes::MessagePtr load_balancing_policy_;
+  LoadBalancerConfigPtr load_balancer_config_;
   TypedLoadBalancerFactory* load_balancer_factory_ = nullptr;
   const std::shared_ptr
       common_lb_config_;
diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml
index 0d8f55d9fe26..9dc8d4f64040 100644
--- a/source/extensions/extensions_metadata.yaml
+++ b/source/extensions/extensions_metadata.yaml
@@ -1512,6 +1512,8 @@ envoy.load_balancing_policies.subset:
   - envoy.load_balancing_policies
   security_posture: robust_to_untrusted_downstream_and_upstream
   status: stable
+  type_urls:
+  - envoy.extensions.load_balancing_policies.subset.v3.Subset
 envoy.load_balancing_policies.cluster_provided:
   categories:
   - envoy.load_balancing_policies
diff --git a/source/extensions/load_balancing_policies/cluster_provided/config.cc b/source/extensions/load_balancing_policies/cluster_provided/config.cc
index 33245f9b7907..a1154fcb7344 100644
--- a/source/extensions/load_balancing_policies/cluster_provided/config.cc
+++ b/source/extensions/load_balancing_policies/cluster_provided/config.cc
@@ -5,7 +5,8 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace ClusterProvided {
 
-Upstream::ThreadAwareLoadBalancerPtr Factory::create(const Upstream::ClusterInfo&,
+Upstream::ThreadAwareLoadBalancerPtr Factory::create(OptRef,
+                                                     const Upstream::ClusterInfo&,
                                                      const Upstream::PrioritySet&, Runtime::Loader&,
                                                      Random::RandomGenerator&, TimeSource&) {
   // Cluster provided load balancer has empty implementation. Because it is a special case to
diff --git a/source/extensions/load_balancing_policies/cluster_provided/config.h b/source/extensions/load_balancing_policies/cluster_provided/config.h
index ef1d73da6969..df59f760498f 100644
--- a/source/extensions/load_balancing_policies/cluster_provided/config.h
+++ b/source/extensions/load_balancing_policies/cluster_provided/config.h
@@ -18,7 +18,8 @@ class Factory
 public:
   Factory() : TypedLoadBalancerFactoryBase("envoy.load_balancing_policies.cluster_provided") {}
 
-  Upstream::ThreadAwareLoadBalancerPtr create(const Upstream::ClusterInfo& cluster_info,
+  Upstream::ThreadAwareLoadBalancerPtr create(OptRef lb_config,
+                                              const Upstream::ClusterInfo& cluster_info,
                                               const Upstream::PrioritySet& priority_set,
                                               Runtime::Loader& runtime,
                                               Random::RandomGenerator& random,
diff --git a/source/extensions/load_balancing_policies/common/BUILD b/source/extensions/load_balancing_policies/common/BUILD
index 4c045e2ec9de..7eaecf268345 100644
--- a/source/extensions/load_balancing_policies/common/BUILD
+++ b/source/extensions/load_balancing_policies/common/BUILD
@@ -13,5 +13,6 @@ envoy_cc_library(
     hdrs = ["factory_base.h"],
     deps = [
         "//envoy/upstream:load_balancer_interface",
+        "//source/common/upstream:load_balancer_factory_base_lib",
     ],
 )
diff --git a/source/extensions/load_balancing_policies/common/factory_base.h b/source/extensions/load_balancing_policies/common/factory_base.h
index d532ec3d439f..c8d46e4481c2 100644
--- a/source/extensions/load_balancing_policies/common/factory_base.h
+++ b/source/extensions/load_balancing_policies/common/factory_base.h
@@ -4,46 +4,52 @@
 
 #include "envoy/upstream/load_balancer.h"
 
+#include "source/common/upstream/load_balancer_factory_base.h"
+
 namespace Envoy {
 namespace Extensions {
 namespace LoadBalancingPolices {
 namespace Common {
 
 template 
-class FactoryBase : public Upstream::TypedLoadBalancerFactory {
+class FactoryBase : public Upstream::TypedLoadBalancerFactoryBase {
 public:
-  FactoryBase(absl::string_view name) : name_(name) {}
+  FactoryBase(const std::string& name) : Upstream::TypedLoadBalancerFactoryBase(name) {}
 
-  Upstream::ThreadAwareLoadBalancerPtr create(const Upstream::ClusterInfo& cluster_info,
+  Upstream::ThreadAwareLoadBalancerPtr create(OptRef lb_config,
+                                              const Upstream::ClusterInfo& cluster_info,
                                               const Upstream::PrioritySet& priority_set,
                                               Runtime::Loader& runtime,
                                               Envoy::Random::RandomGenerator& random,
                                               TimeSource& time_source) override {
-    return std::make_unique(
-        std::make_shared(cluster_info, priority_set, runtime, random, time_source));
-  }
 
-  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
-    return std::make_unique();
-  }
+    const auto* typed_lb_config =
+        dynamic_cast(lb_config.ptr());
+    auto typed_proto_config = typed_lb_config == nullptr
+                                  ? OptRef{}
+                                  : typed_lb_config->typedProtoConfig();
 
-  std::string name() const override { return name_; }
+    return std::make_unique(std::make_shared(
+        typed_proto_config, cluster_info, priority_set, runtime, random, time_source));
+  }
 
 private:
   class LbFactory : public Upstream::LoadBalancerFactory {
   public:
-    LbFactory(const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet& priority_set,
-              Runtime::Loader& runtime, Envoy::Random::RandomGenerator& random,
-              TimeSource& time_source)
-        : cluster_info_(cluster_info), priority_set_(priority_set), runtime_(runtime),
-          random_(random), time_source_(time_source) {}
+    LbFactory(OptRef proto_config, const Upstream::ClusterInfo& cluster_info,
+              const Upstream::PrioritySet& priority_set, Runtime::Loader& runtime,
+              Envoy::Random::RandomGenerator& random, TimeSource& time_source)
+        : proto_config_(proto_config), cluster_info_(cluster_info), priority_set_(priority_set),
+          runtime_(runtime), random_(random), time_source_(time_source) {}
 
     Upstream::LoadBalancerPtr create() override { PANIC("not implemented"); }
     Upstream::LoadBalancerPtr create(Upstream::LoadBalancerParams params) override {
-      return Impl()(params, cluster_info_, priority_set_, runtime_, random_, time_source_);
+      return Impl()(params, proto_config_, cluster_info_, priority_set_, runtime_, random_,
+                    time_source_);
     }
 
   public:
+    OptRef proto_config_;
     const Upstream::ClusterInfo& cluster_info_;
     const Upstream::PrioritySet& priority_set_;
     Runtime::Loader& runtime_;
diff --git a/source/extensions/load_balancing_policies/least_request/config.cc b/source/extensions/load_balancing_policies/least_request/config.cc
index d2dab339ec1f..224aae7e2f6d 100644
--- a/source/extensions/load_balancing_policies/least_request/config.cc
+++ b/source/extensions/load_balancing_policies/least_request/config.cc
@@ -9,27 +9,21 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace LeastRequest {
 
-Upstream::LoadBalancerPtr LeastRequestCreator::operator()(Upstream::LoadBalancerParams params,
-                                                          const Upstream::ClusterInfo& cluster_info,
-                                                          const Upstream::PrioritySet&,
-                                                          Runtime::Loader& runtime,
-                                                          Random::RandomGenerator& random,
-                                                          TimeSource& time_source) {
-
-  const auto* typed_config = dynamic_cast<
-      const envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest*>(
-      cluster_info.loadBalancingPolicy().get());
+Upstream::LoadBalancerPtr LeastRequestCreator::operator()(
+    Upstream::LoadBalancerParams params, OptRef lb_config,
+    const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet&,
+    Runtime::Loader& runtime, Random::RandomGenerator& random, TimeSource& time_source) {
 
   // The load balancing policy configuration will be loaded and validated in the main thread when we
   // load the cluster configuration. So we can assume the configuration is valid here.
-  ASSERT(typed_config != nullptr,
+  ASSERT(lb_config.has_value(),
          "Invalid load balancing policy configuration for least request load balancer");
 
   return std::make_unique(
       params.priority_set, params.local_priority_set, cluster_info.lbStats(), runtime, random,
       PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(cluster_info.lbConfig(),
                                                      healthy_panic_threshold, 100, 50),
-      *typed_config, time_source);
+      lb_config.value(), time_source);
 }
 
 /**
diff --git a/source/extensions/load_balancing_policies/least_request/config.h b/source/extensions/load_balancing_policies/least_request/config.h
index e2e787936c28..ffd9456d2d87 100644
--- a/source/extensions/load_balancing_policies/least_request/config.h
+++ b/source/extensions/load_balancing_policies/least_request/config.h
@@ -12,17 +12,17 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace LeastRequest {
 
+using LeastRequestLbProto =
+    envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest;
+
 struct LeastRequestCreator : public Logger::Loggable {
-  Upstream::LoadBalancerPtr operator()(Upstream::LoadBalancerParams params,
-                                       const Upstream::ClusterInfo& cluster_info,
-                                       const Upstream::PrioritySet& priority_set,
-                                       Runtime::Loader& runtime, Random::RandomGenerator& random,
-                                       TimeSource& time_source);
+  Upstream::LoadBalancerPtr
+  operator()(Upstream::LoadBalancerParams params, OptRef lb_config,
+             const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet& priority_set,
+             Runtime::Loader& runtime, Random::RandomGenerator& random, TimeSource& time_source);
 };
 
-class Factory : public Common::FactoryBase<
-                    envoy::extensions::load_balancing_policies::least_request::v3::LeastRequest,
-                    LeastRequestCreator> {
+class Factory : public Common::FactoryBase {
 public:
   Factory() : FactoryBase("envoy.load_balancing_policies.least_request") {}
 };
diff --git a/source/extensions/load_balancing_policies/maglev/config.cc b/source/extensions/load_balancing_policies/maglev/config.cc
index 0b1a4e89105f..76db3e002227 100644
--- a/source/extensions/load_balancing_policies/maglev/config.cc
+++ b/source/extensions/load_balancing_policies/maglev/config.cc
@@ -9,17 +9,20 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace Maglev {
 
-Upstream::ThreadAwareLoadBalancerPtr Factory::create(const Upstream::ClusterInfo& cluster_info,
-                                                     const Upstream::PrioritySet& priority_set,
-                                                     Runtime::Loader& runtime,
-                                                     Random::RandomGenerator& random, TimeSource&) {
-
-  const auto* typed_config =
-      dynamic_cast(
-          cluster_info.loadBalancingPolicy().get());
+Upstream::ThreadAwareLoadBalancerPtr
+Factory::create(OptRef lb_config,
+                const Upstream::ClusterInfo& cluster_info,
+                const Upstream::PrioritySet& priority_set, Runtime::Loader& runtime,
+                Random::RandomGenerator& random, TimeSource&) {
+
+  const auto* typed_lb_config =
+      dynamic_cast(lb_config.ptr());
+  auto typed_proto_config = typed_lb_config == nullptr
+                                ? OptRef{}
+                                : typed_lb_config->typedProtoConfig();
 
   // Assume legacy config.
-  if (!typed_config) {
+  if (!typed_proto_config.has_value()) {
     return std::make_unique(
         priority_set, cluster_info.lbStats(), cluster_info.statsScope(), runtime, random,
         cluster_info.lbMaglevConfig(), cluster_info.lbConfig());
@@ -29,7 +32,7 @@ Upstream::ThreadAwareLoadBalancerPtr Factory::create(const Upstream::ClusterInfo
       priority_set, cluster_info.lbStats(), cluster_info.statsScope(), runtime, random,
       static_cast(PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(
           cluster_info.lbConfig(), healthy_panic_threshold, 100, 50)),
-      *typed_config);
+      typed_proto_config.value());
 }
 
 /**
diff --git a/source/extensions/load_balancing_policies/maglev/config.h b/source/extensions/load_balancing_policies/maglev/config.h
index 2c072367f31e..c4eb711f2c4d 100644
--- a/source/extensions/load_balancing_policies/maglev/config.h
+++ b/source/extensions/load_balancing_policies/maglev/config.h
@@ -13,12 +13,14 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace Maglev {
 
-class Factory : public Upstream::TypedLoadBalancerFactoryBase<
-                    envoy::extensions::load_balancing_policies::maglev::v3::Maglev> {
+using MaglevLbProto = envoy::extensions::load_balancing_policies::maglev::v3::Maglev;
+
+class Factory : public Upstream::TypedLoadBalancerFactoryBase {
 public:
   Factory() : TypedLoadBalancerFactoryBase("envoy.load_balancing_policies.maglev") {}
 
-  Upstream::ThreadAwareLoadBalancerPtr create(const Upstream::ClusterInfo& cluster_info,
+  Upstream::ThreadAwareLoadBalancerPtr create(OptRef lb_config,
+                                              const Upstream::ClusterInfo& cluster_info,
                                               const Upstream::PrioritySet& priority_set,
                                               Runtime::Loader& runtime,
                                               Random::RandomGenerator& random,
diff --git a/source/extensions/load_balancing_policies/random/config.cc b/source/extensions/load_balancing_policies/random/config.cc
index 86d8394f32f7..0bad06c2bea7 100644
--- a/source/extensions/load_balancing_policies/random/config.cc
+++ b/source/extensions/load_balancing_policies/random/config.cc
@@ -9,27 +9,21 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace Random {
 
-Upstream::LoadBalancerPtr RandomCreator::operator()(Upstream::LoadBalancerParams params,
-                                                    const Upstream::ClusterInfo& cluster_info,
-                                                    const Upstream::PrioritySet&,
-                                                    Runtime::Loader& runtime,
-                                                    Envoy::Random::RandomGenerator& random,
-                                                    TimeSource&) {
-
-  const auto* typed_config =
-      dynamic_cast(
-          cluster_info.loadBalancingPolicy().get());
+Upstream::LoadBalancerPtr RandomCreator::operator()(
+    Upstream::LoadBalancerParams params, OptRef lb_config,
+    const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet&,
+    Runtime::Loader& runtime, Envoy::Random::RandomGenerator& random, TimeSource&) {
 
   // The load balancing policy configuration will be loaded and validated in the main thread when we
   // load the cluster configuration. So we can assume the configuration is valid here.
-  ASSERT(typed_config != nullptr,
+  ASSERT(lb_config.has_value(),
          "Invalid load balancing policy configuration for random load balancer");
 
   return std::make_unique(
       params.priority_set, params.local_priority_set, cluster_info.lbStats(), runtime, random,
       PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(cluster_info.lbConfig(),
                                                      healthy_panic_threshold, 100, 50),
-      *typed_config);
+      lb_config.value());
 }
 
 /**
diff --git a/source/extensions/load_balancing_policies/random/config.h b/source/extensions/load_balancing_policies/random/config.h
index b40754536a67..0d637262dfc3 100644
--- a/source/extensions/load_balancing_policies/random/config.h
+++ b/source/extensions/load_balancing_policies/random/config.h
@@ -12,16 +12,17 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace Random {
 
+using RandomLbProto = envoy::extensions::load_balancing_policies::random::v3::Random;
+
 struct RandomCreator : public Logger::Loggable {
   Upstream::LoadBalancerPtr
-  operator()(Upstream::LoadBalancerParams params, const Upstream::ClusterInfo& cluster_info,
-             const Upstream::PrioritySet& priority_set, Runtime::Loader& runtime,
-             Envoy::Random::RandomGenerator& random, TimeSource& time_source);
+  operator()(Upstream::LoadBalancerParams params, OptRef lb_config,
+             const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet& priority_set,
+             Runtime::Loader& runtime, Envoy::Random::RandomGenerator& random,
+             TimeSource& time_source);
 };
 
-class Factory
-    : public Common::FactoryBase {
+class Factory : public Common::FactoryBase {
 public:
   Factory() : FactoryBase("envoy.load_balancing_policies.random") {}
 };
diff --git a/source/extensions/load_balancing_policies/ring_hash/config.cc b/source/extensions/load_balancing_policies/ring_hash/config.cc
index 41972d1d5252..05dc3ab98099 100644
--- a/source/extensions/load_balancing_policies/ring_hash/config.cc
+++ b/source/extensions/load_balancing_policies/ring_hash/config.cc
@@ -7,17 +7,20 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace RingHash {
 
-Upstream::ThreadAwareLoadBalancerPtr Factory::create(const Upstream::ClusterInfo& cluster_info,
-                                                     const Upstream::PrioritySet& priority_set,
-                                                     Runtime::Loader& runtime,
-                                                     Random::RandomGenerator& random, TimeSource&) {
-
-  const auto* typed_config =
-      dynamic_cast(
-          cluster_info.loadBalancingPolicy().get());
+Upstream::ThreadAwareLoadBalancerPtr
+Factory::create(OptRef lb_config,
+                const Upstream::ClusterInfo& cluster_info,
+                const Upstream::PrioritySet& priority_set, Runtime::Loader& runtime,
+                Random::RandomGenerator& random, TimeSource&) {
+
+  const auto* typed_lb_config =
+      dynamic_cast(lb_config.ptr());
+  auto typed_proto_config = typed_lb_config == nullptr
+                                ? OptRef{}
+                                : typed_lb_config->typedProtoConfig();
 
   // Assume legacy config.
-  if (!typed_config) {
+  if (!typed_proto_config.has_value()) {
     return std::make_unique(
         priority_set, cluster_info.lbStats(), cluster_info.statsScope(), runtime, random,
         cluster_info.lbRingHashConfig(), cluster_info.lbConfig());
@@ -27,7 +30,7 @@ Upstream::ThreadAwareLoadBalancerPtr Factory::create(const Upstream::ClusterInfo
       priority_set, cluster_info.lbStats(), cluster_info.statsScope(), runtime, random,
       PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(cluster_info.lbConfig(),
                                                      healthy_panic_threshold, 100, 50),
-      *typed_config);
+      typed_proto_config.value());
 }
 
 /**
diff --git a/source/extensions/load_balancing_policies/ring_hash/config.h b/source/extensions/load_balancing_policies/ring_hash/config.h
index 4e4a8c0e61cd..fdbac8d590cc 100644
--- a/source/extensions/load_balancing_policies/ring_hash/config.h
+++ b/source/extensions/load_balancing_policies/ring_hash/config.h
@@ -13,12 +13,14 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace RingHash {
 
-class Factory : public Upstream::TypedLoadBalancerFactoryBase<
-                    envoy::extensions::load_balancing_policies::ring_hash::v3::RingHash> {
+using RingHashLbProto = envoy::extensions::load_balancing_policies::ring_hash::v3::RingHash;
+
+class Factory : public Upstream::TypedLoadBalancerFactoryBase {
 public:
   Factory() : TypedLoadBalancerFactoryBase("envoy.load_balancing_policies.ring_hash") {}
 
-  Upstream::ThreadAwareLoadBalancerPtr create(const Upstream::ClusterInfo& cluster_info,
+  Upstream::ThreadAwareLoadBalancerPtr create(OptRef lb_config,
+                                              const Upstream::ClusterInfo& cluster_info,
                                               const Upstream::PrioritySet& priority_set,
                                               Runtime::Loader& runtime,
                                               Random::RandomGenerator& random,
diff --git a/source/extensions/load_balancing_policies/round_robin/config.cc b/source/extensions/load_balancing_policies/round_robin/config.cc
index a55d47fa9c68..fff5fb6483bc 100644
--- a/source/extensions/load_balancing_policies/round_robin/config.cc
+++ b/source/extensions/load_balancing_policies/round_robin/config.cc
@@ -9,27 +9,21 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace RoundRobin {
 
-Upstream::LoadBalancerPtr RoundRobinCreator::operator()(Upstream::LoadBalancerParams params,
-                                                        const Upstream::ClusterInfo& cluster_info,
-                                                        const Upstream::PrioritySet&,
-                                                        Runtime::Loader& runtime,
-                                                        Random::RandomGenerator& random,
-                                                        TimeSource& time_source) {
-
-  const auto* typed_config =
-      dynamic_cast(
-          cluster_info.loadBalancingPolicy().get());
+Upstream::LoadBalancerPtr RoundRobinCreator::operator()(
+    Upstream::LoadBalancerParams params, OptRef lb_config,
+    const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet&,
+    Runtime::Loader& runtime, Random::RandomGenerator& random, TimeSource& time_source) {
 
   // The load balancing policy configuration will be loaded and validated in the main thread when we
   // load the cluster configuration. So we can assume the configuration is valid here.
-  ASSERT(typed_config != nullptr,
+  ASSERT(lb_config.has_value(),
          "Invalid load balancing policy configuration for least request load balancer");
 
   return std::make_unique(
       params.priority_set, params.local_priority_set, cluster_info.lbStats(), runtime, random,
       PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(cluster_info.lbConfig(),
                                                      healthy_panic_threshold, 100, 50),
-      *typed_config, time_source);
+      lb_config.value(), time_source);
 }
 
 /**
diff --git a/source/extensions/load_balancing_policies/round_robin/config.h b/source/extensions/load_balancing_policies/round_robin/config.h
index b0138b86dc01..4e06b5b48de1 100644
--- a/source/extensions/load_balancing_policies/round_robin/config.h
+++ b/source/extensions/load_balancing_policies/round_robin/config.h
@@ -12,17 +12,16 @@ namespace Extensions {
 namespace LoadBalancingPolices {
 namespace RoundRobin {
 
+using RoundRobinLbProto = envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin;
+
 struct RoundRobinCreator : public Logger::Loggable {
-  Upstream::LoadBalancerPtr operator()(Upstream::LoadBalancerParams params,
-                                       const Upstream::ClusterInfo& cluster_info,
-                                       const Upstream::PrioritySet& priority_set,
-                                       Runtime::Loader& runtime, Random::RandomGenerator& random,
-                                       TimeSource& time_source);
+  Upstream::LoadBalancerPtr
+  operator()(Upstream::LoadBalancerParams params, OptRef lb_config,
+             const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet& priority_set,
+             Runtime::Loader& runtime, Random::RandomGenerator& random, TimeSource& time_source);
 };
 
-class Factory : public Common::FactoryBase<
-                    envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin,
-                    RoundRobinCreator> {
+class Factory : public Common::FactoryBase {
 public:
   Factory() : FactoryBase("envoy.load_balancing_policies.round_robin") {}
 };
diff --git a/source/extensions/load_balancing_policies/subset/BUILD b/source/extensions/load_balancing_policies/subset/BUILD
index ec66a84e18a7..7e001486b3a8 100644
--- a/source/extensions/load_balancing_policies/subset/BUILD
+++ b/source/extensions/load_balancing_policies/subset/BUILD
@@ -23,10 +23,12 @@ envoy_cc_library(
         "//source/common/protobuf:utility_lib",
         "//source/common/upstream:load_balancer_lib",
         "//source/common/upstream:upstream_lib",
+        "//source/extensions/load_balancing_policies/common:factory_base",
         "//source/extensions/load_balancing_policies/maglev:maglev_lb_lib",
         "//source/extensions/load_balancing_policies/ring_hash:ring_hash_lb_lib",
         "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto",
         "@envoy_api//envoy/config/core/v3:pkg_cc_proto",
+        "@envoy_api//envoy/extensions/load_balancing_policies/subset/v3:pkg_cc_proto",
     ],
 )
 
diff --git a/source/extensions/load_balancing_policies/subset/config.cc b/source/extensions/load_balancing_policies/subset/config.cc
index 8944814252d8..486d3c77b733 100644
--- a/source/extensions/load_balancing_policies/subset/config.cc
+++ b/source/extensions/load_balancing_policies/subset/config.cc
@@ -12,11 +12,13 @@ Upstream::LoadBalancerPtr Factory::create(const Upstream::ClusterInfo& cluster,
                                           const Upstream::PrioritySet* local_priority_set,
                                           Runtime::Loader& runtime, Random::RandomGenerator& random,
                                           TimeSource& time_source) {
+  auto child_lb_creator = std::make_unique(
+      cluster.lbType(), cluster.lbRingHashConfig(), cluster.lbMaglevConfig(),
+      cluster.lbRoundRobinConfig(), cluster.lbLeastRequestConfig(), cluster.lbConfig());
+
   return std::make_unique(
-      cluster.lbType(), priority_set, local_priority_set, cluster.lbStats(), cluster.statsScope(),
-      runtime, random, cluster.lbSubsetInfo(), cluster.lbRingHashConfig(), cluster.lbMaglevConfig(),
-      cluster.lbRoundRobinConfig(), cluster.lbLeastRequestConfig(), cluster.lbConfig(),
-      time_source);
+      cluster.lbSubsetInfo(), std::move(child_lb_creator), priority_set, local_priority_set,
+      cluster.lbStats(), cluster.statsScope(), runtime, random, time_source);
 }
 
 /**
@@ -24,6 +26,157 @@ Upstream::LoadBalancerPtr Factory::create(const Upstream::ClusterInfo& cluster,
  */
 REGISTER_FACTORY(Factory, Upstream::NonThreadAwareLoadBalancerFactory);
 
+using LoadBalancerSubsetInfoImpl =
+    Upstream::LoadBalancerSubsetInfoImplBase;
+
+class SubsetLoadBalancerConfig : public Upstream::LoadBalancerConfig {
+public:
+  SubsetLoadBalancerConfig(const Upstream::SubsetLoadbalancingPolicyProto& subset_config,
+                           ProtobufMessage::ValidationVisitor& visitor)
+      : subset_info_(subset_config) {
+
+    absl::InlinedVector missing_policies;
+
+    for (const auto& policy : subset_config.subset_lb_policy().policies()) {
+      auto* factory = Config::Utility::getAndCheckFactory(
+          policy.typed_extension_config(), /*is_optional=*/true);
+
+      if (factory != nullptr) {
+        // Load and validate the configuration.
+        auto sub_lb_proto_message = factory->createEmptyConfigProto();
+        Config::Utility::translateOpaqueConfig(policy.typed_extension_config().typed_config(),
+                                               visitor, *sub_lb_proto_message);
+
+        sub_load_balancer_config_ = factory->loadConfig(std::move(sub_lb_proto_message), visitor);
+        sub_load_balancer_factory_ = factory;
+        break;
+      }
+
+      missing_policies.push_back(policy.typed_extension_config().name());
+    }
+
+    if (sub_load_balancer_factory_ == nullptr) {
+      throw EnvoyException(fmt::format("cluster: didn't find a registered load balancer factory "
+                                       "implementation for subset lb with names from [{}]",
+                                       absl::StrJoin(missing_policies, ", ")));
+    }
+  }
+
+  Upstream::ThreadAwareLoadBalancerPtr
+  createLoadBalancer(const Upstream::ClusterInfo& cluster_info,
+                     const Upstream::PrioritySet& child_priority_set, Runtime::Loader& runtime,
+                     Random::RandomGenerator& random, TimeSource& time_source) const {
+    return sub_load_balancer_factory_->create(*sub_load_balancer_config_, cluster_info,
+                                              child_priority_set, runtime, random, time_source);
+  }
+
+  const Upstream::LoadBalancerSubsetInfo& subsetInfo() const { return subset_info_; }
+
+private:
+  LoadBalancerSubsetInfoImpl subset_info_;
+
+  Upstream::LoadBalancerConfigPtr sub_load_balancer_config_;
+  Upstream::TypedLoadBalancerFactory* sub_load_balancer_factory_{};
+};
+
+class ChildLoadBalancerCreatorImpl : public Upstream::ChildLoadBalancerCreator {
+public:
+  ChildLoadBalancerCreatorImpl(const SubsetLoadBalancerConfig& subset_config,
+                               const Upstream::ClusterInfo& cluster_info)
+      : subset_config_(subset_config), cluster_info_(cluster_info) {}
+
+  std::pair
+  createLoadBalancer(const Upstream::PrioritySet& child_priority_set, const Upstream::PrioritySet*,
+                     Upstream::ClusterLbStats&, Stats::Scope&, Runtime::Loader& runtime,
+                     Random::RandomGenerator& random, TimeSource& time_source) override {
+    return {subset_config_.createLoadBalancer(cluster_info_, child_priority_set, runtime, random,
+                                              time_source),
+            nullptr};
+  }
+
+private:
+  const SubsetLoadBalancerConfig& subset_config_;
+  const Upstream::ClusterInfo& cluster_info_;
+};
+
+class LbFactory : public Upstream::LoadBalancerFactory {
+public:
+  LbFactory(const SubsetLoadBalancerConfig& subset_config,
+            const Upstream::ClusterInfo& cluster_info, Runtime::Loader& runtime,
+            Random::RandomGenerator& random, TimeSource& time_source)
+      : subset_config_(subset_config), cluster_info_(cluster_info), runtime_(runtime),
+        random_(random), time_source_(time_source) {}
+
+  Upstream::LoadBalancerPtr create() override { PANIC("not implemented"); };
+
+  Upstream::LoadBalancerPtr create(Upstream::LoadBalancerParams params) override {
+    auto child_lb_creator =
+        std::make_unique(subset_config_, cluster_info_);
+
+    return std::make_unique(
+        subset_config_.subsetInfo(), std::move(child_lb_creator), params.priority_set,
+        params.local_priority_set, cluster_info_.lbStats(), cluster_info_.statsScope(), runtime_,
+        random_, time_source_);
+  }
+
+private:
+  const SubsetLoadBalancerConfig& subset_config_;
+  const Upstream::ClusterInfo& cluster_info_;
+
+  Runtime::Loader& runtime_;
+  Random::RandomGenerator& random_;
+  TimeSource& time_source_;
+};
+
+class ThreadAwareLb : public Upstream::ThreadAwareLoadBalancer {
+public:
+  ThreadAwareLb(Upstream::LoadBalancerFactorySharedPtr factory) : factory_(std::move(factory)) {}
+
+  Upstream::LoadBalancerFactorySharedPtr factory() override { return factory_; }
+  void initialize() override {}
+
+private:
+  Upstream::LoadBalancerFactorySharedPtr factory_;
+};
+
+Upstream::ThreadAwareLoadBalancerPtr
+SubsetLbFactory::create(OptRef lb_config,
+                        const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet&,
+                        Runtime::Loader& runtime, Random::RandomGenerator& random,
+                        TimeSource& time_source) {
+
+  const auto* typed_config = dynamic_cast(lb_config.ptr());
+  // The load balancing policy configuration will be loaded and validated in the main thread when we
+  // load the cluster configuration. So we can assume the configuration is valid here.
+  ASSERT(typed_config != nullptr,
+         "Invalid load balancing policy configuration for subset load balancer");
+
+  // Create the load balancer factory that will be used to create the load balancer in the workers.
+  auto lb_factory =
+      std::make_shared(*typed_config, cluster_info, runtime, random, time_source);
+
+  // Move and store the load balancer factory in the thread aware load balancer. This thread aware
+  // load balancer is simply a wrapper of the load balancer factory for subset lb and no actual
+  // logic is implemented.
+  return std::make_unique(std::move(lb_factory));
+}
+
+Upstream::LoadBalancerConfigPtr
+SubsetLbFactory::loadConfig(ProtobufTypes::MessagePtr config,
+                            ProtobufMessage::ValidationVisitor& visitor) {
+  ASSERT(config != nullptr);
+  auto* proto_config = dynamic_cast(config.get());
+
+  // Load the subset load balancer configuration. This will contains child load balancer
+  // config and child load balancer factory.
+  return std::make_unique(*proto_config, visitor);
+}
+
+/**
+ * Static registration for the Factory. @see RegisterFactory.
+ */
+REGISTER_FACTORY(SubsetLbFactory, Upstream::TypedLoadBalancerFactory);
+
 } // namespace Subset
 } // namespace LoadBalancingPolices
 } // namespace Extensions
diff --git a/source/extensions/load_balancing_policies/subset/config.h b/source/extensions/load_balancing_policies/subset/config.h
index d3ed76b688d5..8476062ab0b5 100644
--- a/source/extensions/load_balancing_policies/subset/config.h
+++ b/source/extensions/load_balancing_policies/subset/config.h
@@ -5,6 +5,7 @@
 #include "envoy/upstream/load_balancer.h"
 
 #include "source/common/upstream/load_balancer_factory_base.h"
+#include "source/extensions/load_balancing_policies/subset/subset_lb.h"
 
 namespace Envoy {
 namespace Extensions {
@@ -22,6 +23,22 @@ class Factory : public Upstream::NonThreadAwareLoadBalancerFactory {
                                    TimeSource& time_source) override;
 };
 
+class SubsetLbFactory
+    : public Upstream::TypedLoadBalancerFactoryBase {
+public:
+  SubsetLbFactory() : TypedLoadBalancerFactoryBase("envoy.load_balancing_policies.subset") {}
+
+  Upstream::ThreadAwareLoadBalancerPtr create(OptRef lb_config,
+                                              const Upstream::ClusterInfo& cluster_info,
+                                              const Upstream::PrioritySet& priority_set,
+                                              Runtime::Loader& runtime,
+                                              Random::RandomGenerator& random,
+                                              TimeSource& time_source) override;
+
+  Upstream::LoadBalancerConfigPtr loadConfig(ProtobufTypes::MessagePtr config,
+                                             ProtobufMessage::ValidationVisitor& visitor) override;
+};
+
 } // namespace Subset
 } // namespace LoadBalancingPolices
 } // namespace Extensions
diff --git a/source/extensions/load_balancing_policies/subset/subset_lb.cc b/source/extensions/load_balancing_policies/subset/subset_lb.cc
index 532f56693af2..f9e6e8d863c3 100644
--- a/source/extensions/load_balancing_policies/subset/subset_lb.cc
+++ b/source/extensions/load_balancing_policies/subset/subset_lb.cc
@@ -22,18 +22,15 @@ namespace Upstream {
 
 using HostPredicate = std::function;
 
-SubsetLoadBalancer::SubsetLoadBalancer(
-    LoadBalancerType lb_type, const PrioritySet& priority_set,
-    const PrioritySet* local_priority_set, ClusterLbStats& stats, Stats::Scope& scope,
-    Runtime::Loader& runtime, Random::RandomGenerator& random,
-    const LoadBalancerSubsetInfo& subsets,
+LegacyChildLoadBalancerCreatorImpl::LegacyChildLoadBalancerCreatorImpl(
+    LoadBalancerType lb_type,
     OptRef lb_ring_hash_config,
     OptRef lb_maglev_config,
     OptRef round_robin_config,
     OptRef least_request_config,
-    const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config,
-    TimeSource& time_source)
-    : lb_ring_hash_config_(
+    const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config)
+    : lb_type_(lb_type),
+      lb_ring_hash_config_(
           lb_ring_hash_config.has_value()
               ? std::make_unique(
                     lb_ring_hash_config.ref())
@@ -53,14 +50,71 @@ SubsetLoadBalancer::SubsetLoadBalancer(
               ? std::make_unique(
                     least_request_config.ref())
               : nullptr),
-      common_config_(common_config), stats_(stats), scope_(scope), runtime_(runtime),
-      random_(random), fallback_policy_(subsets.fallbackPolicy()),
+      common_config_(common_config) {}
+
+std::pair
+LegacyChildLoadBalancerCreatorImpl::createLoadBalancer(
+    const Upstream::PrioritySet& child_priority_set,
+    const Upstream::PrioritySet* local_priority_set, ClusterLbStats& stats, Stats::Scope& scope,
+    Runtime::Loader& runtime, Random::RandomGenerator& random, TimeSource& time_source) {
+  switch (lb_type_) {
+  case Upstream::LoadBalancerType::LeastRequest: {
+    Upstream::LoadBalancerPtr lb = std::make_unique(
+        child_priority_set, local_priority_set, stats, runtime, random, common_config_,
+        lbLeastRequestConfig(), time_source);
+    return {nullptr, std::move(lb)};
+  }
+  case Upstream::LoadBalancerType::Random: {
+    Upstream::LoadBalancerPtr lb = std::make_unique(
+        child_priority_set, local_priority_set, stats, runtime, random, common_config_);
+    return {nullptr, std::move(lb)};
+  }
+  case Upstream::LoadBalancerType::RoundRobin: {
+    Upstream::LoadBalancerPtr lb = std::make_unique(
+        child_priority_set, local_priority_set, stats, runtime, random, common_config_,
+        lbRoundRobinConfig(), time_source);
+    return {nullptr, std::move(lb)};
+  }
+  case Upstream::LoadBalancerType::RingHash: {
+    // TODO(mattklein123): The ring hash LB is thread aware, but currently the subset LB is not.
+    // We should make the subset LB thread aware since the calculations are costly, and then we
+    // can also use a thread aware sub-LB properly. The following works fine but is not optimal.
+    Upstream::ThreadAwareLoadBalancerPtr lb = std::make_unique(
+        child_priority_set, stats, scope, runtime, random, lbRingHashConfig(), common_config_);
+    return {std::move(lb), nullptr};
+  }
+  case Upstream::LoadBalancerType::Maglev: {
+    // TODO(mattklein123): The Maglev LB is thread aware, but currently the subset LB is not.
+    // We should make the subset LB thread aware since the calculations are costly, and then we
+    // can also use a thread aware sub-LB properly. The following works fine but is not optimal.
+
+    Upstream::ThreadAwareLoadBalancerPtr lb = std::make_unique(
+        child_priority_set, stats, scope, runtime, random, lbMaglevConfig(), common_config_);
+    return {std::move(lb), nullptr};
+  }
+  case Upstream::LoadBalancerType::OriginalDst:
+  case Upstream::LoadBalancerType::ClusterProvided:
+  case Upstream::LoadBalancerType::LoadBalancingPolicyConfig:
+    // These load balancer types can only be created when there is no subset configuration.
+    PANIC("not implemented");
+  }
+  return {nullptr, nullptr};
+}
+
+SubsetLoadBalancer::SubsetLoadBalancer(const LoadBalancerSubsetInfo& subsets,
+                                       ChildLoadBalancerCreatorPtr child_lb,
+                                       const PrioritySet& priority_set,
+                                       const PrioritySet* local_priority_set, ClusterLbStats& stats,
+                                       Stats::Scope& scope, Runtime::Loader& runtime,
+                                       Random::RandomGenerator& random, TimeSource& time_source)
+    : stats_(stats), scope_(scope), runtime_(runtime), random_(random), time_source_(time_source),
+      fallback_policy_(subsets.fallbackPolicy()),
       metadata_fallback_policy_(subsets.metadataFallbackPolicy()),
       default_subset_metadata_(subsets.defaultSubset().fields().begin(),
                                subsets.defaultSubset().fields().end()),
       subset_selectors_(subsets.subsetSelectors()), original_priority_set_(priority_set),
-      original_local_priority_set_(local_priority_set), time_source_(time_source),
-      lb_type_(lb_type), locality_weight_aware_(subsets.localityWeightAware()),
+      original_local_priority_set_(local_priority_set), child_lb_creator_(std::move(child_lb)),
+      locality_weight_aware_(subsets.localityWeightAware()),
       scale_locality_weight_(subsets.scaleLocalityWeight()), list_as_any_(subsets.listAsAny()) {
   ASSERT(subsets.isEnabled());
 
@@ -342,8 +396,8 @@ HostConstSharedPtr SubsetLoadBalancer::chooseHostForSelectorFallbackPolicy(
 
 // Find a host from the subsets. Sets host_chosen to false and returns nullptr if the context has
 // no metadata match criteria, if there is no matching subset, or if the matching subset contains
-// no hosts (ignoring health). Otherwise, host_chosen is true and the returns HostConstSharedPtr is
-// from the subset's load balancer (technically, it may still be nullptr).
+// no hosts (ignoring health). Otherwise, host_chosen is true and the returns HostConstSharedPtr
+// is from the subset's load balancer (technically, it may still be nullptr).
 HostConstSharedPtr SubsetLoadBalancer::tryChooseHostFromContext(LoadBalancerContext* context,
                                                                 bool& host_chosen) {
   host_chosen = false;
@@ -364,8 +418,8 @@ HostConstSharedPtr SubsetLoadBalancer::tryChooseHostFromContext(LoadBalancerCont
   return entry->lb_subset_->chooseHost(context);
 }
 
-// Iterates over the given metadata match criteria (which must be lexically sorted by key) and find
-// a matching LbSubsetEntryPtr, if any.
+// Iterates over the given metadata match criteria (which must be lexically sorted by key) and
+// find a matching LbSubsetEntryPtr, if any.
 SubsetLoadBalancer::LbSubsetEntryPtr SubsetLoadBalancer::findSubset(
     const std::vector& match_criteria) {
   const LbSubsetMap* subsets = &subsets_;
@@ -374,8 +428,8 @@ SubsetLoadBalancer::LbSubsetEntryPtr SubsetLoadBalancer::findSubset(
   // same order, we can iterate over the criteria and perform a lookup for each key and value,
   // starting with the root LbSubsetMap and using the previous iteration's LbSubsetMap thereafter
   // (tracked in subsets). If ever a criterion's key or value is not found, there is no subset for
-  // this criteria. If we reach the last criterion, we've found the LbSubsetEntry for the criteria,
-  // which may or may not have a subset attached to it.
+  // this criteria. If we reach the last criterion, we've found the LbSubsetEntry for the
+  // criteria, which may or may not have a subset attached to it.
   for (uint32_t i = 0; i < match_criteria.size(); i++) {
     const Router::MetadataMatchCriterion& match_criterion = *match_criteria[i];
     const auto& subset_it = subsets->find(match_criterion.name());
@@ -483,8 +537,8 @@ void SubsetLoadBalancer::processSubsets(uint32_t priority, const HostVector& all
   }
 
   // This stat isn't added to `ClusterTrafficStats` because it wouldn't be used for nearly all
-  // clusters, and is only set during configuration updates, not in the data path, so performance of
-  // looking up the stat isn't critical.
+  // clusters, and is only set during configuration updates, not in the data path, so performance
+  // of looking up the stat isn't critical.
   if (single_duplicate_stat_ == nullptr) {
     Stats::StatNameManagedStorage name_storage("lb_subsets_single_host_per_subset_duplicate",
                                                scope_.symbolTable());
@@ -692,58 +746,21 @@ SubsetLoadBalancer::PrioritySubsetImpl::PrioritySubsetImpl(const SubsetLoadBalan
                                                            bool locality_weight_aware,
                                                            bool scale_locality_weight)
     : original_priority_set_(subset_lb.original_priority_set_),
+      original_local_priority_set_(subset_lb.original_local_priority_set_),
       locality_weight_aware_(locality_weight_aware), scale_locality_weight_(scale_locality_weight) {
   // Create at least one host set.
   getOrCreateHostSet(0);
 
-  switch (subset_lb.lb_type_) {
-  case LoadBalancerType::LeastRequest:
-    lb_ = std::make_unique(
-        *this, subset_lb.original_local_priority_set_, subset_lb.stats_, subset_lb.runtime_,
-        subset_lb.random_, subset_lb.common_config_, subset_lb.lbLeastRequestConfig(),
-        subset_lb.time_source_);
-    break;
-
-  case LoadBalancerType::Random:
-    lb_ = std::make_unique(*this, subset_lb.original_local_priority_set_,
-                                               subset_lb.stats_, subset_lb.runtime_,
-                                               subset_lb.random_, subset_lb.common_config_);
-    break;
-
-  case LoadBalancerType::RoundRobin:
-    lb_ = std::make_unique(
-        *this, subset_lb.original_local_priority_set_, subset_lb.stats_, subset_lb.runtime_,
-        subset_lb.random_, subset_lb.common_config_, subset_lb.lbRoundRobinConfig(),
-        subset_lb.time_source_);
-    break;
-
-  case LoadBalancerType::RingHash:
-    // TODO(mattklein123): The ring hash LB is thread aware, but currently the subset LB is not.
-    // We should make the subset LB thread aware since the calculations are costly, and then we
-    // can also use a thread aware sub-LB properly. The following works fine but is not optimal.
-    thread_aware_lb_ = std::make_unique(
-        *this, subset_lb.stats_, subset_lb.scope_, subset_lb.runtime_, subset_lb.random_,
-        subset_lb.lbRingHashConfig(), subset_lb.common_config_);
-    thread_aware_lb_->initialize();
-    lb_ = thread_aware_lb_->factory()->create();
-    break;
+  auto lb_pair = subset_lb.child_lb_creator_->createLoadBalancer(
+      *this, original_local_priority_set_, subset_lb.stats_, subset_lb.scope_, subset_lb.runtime_,
+      subset_lb.random_, subset_lb.time_source_);
 
-  case LoadBalancerType::Maglev:
-    // TODO(mattklein123): The Maglev LB is thread aware, but currently the subset LB is not.
-    // We should make the subset LB thread aware since the calculations are costly, and then we
-    // can also use a thread aware sub-LB properly. The following works fine but is not optimal.
-    thread_aware_lb_ = std::make_unique(
-        *this, subset_lb.stats_, subset_lb.scope_, subset_lb.runtime_, subset_lb.random_,
-        subset_lb.lbMaglevConfig(), subset_lb.common_config_);
+  if (lb_pair.first != nullptr) {
+    thread_aware_lb_ = std::move(lb_pair.first);
     thread_aware_lb_->initialize();
-    lb_ = thread_aware_lb_->factory()->create();
-    break;
-
-  case LoadBalancerType::OriginalDst:
-  case LoadBalancerType::ClusterProvided:
-  case LoadBalancerType::LoadBalancingPolicyConfig:
-    // These load balancer types can only be created when there is no subset configuration.
-    PANIC("not implemented");
+    lb_ = thread_aware_lb_->factory()->create({*this, original_local_priority_set_});
+  } else {
+    lb_ = std::move(lb_pair.second);
   }
 
   triggerCallbacks();
@@ -883,7 +900,7 @@ void SubsetLoadBalancer::PrioritySubsetImpl::update(uint32_t priority,
   // TODO(mattklein123): See the PrioritySubsetImpl constructor for additional comments on how
   // we can do better here.
   if (thread_aware_lb_ != nullptr) {
-    lb_ = thread_aware_lb_->factory()->create();
+    lb_ = thread_aware_lb_->factory()->create({*this, original_local_priority_set_});
   }
 }
 
diff --git a/source/extensions/load_balancing_policies/subset/subset_lb.h b/source/extensions/load_balancing_policies/subset/subset_lb.h
index 0f5ec5ccada6..0072dcbe8006 100644
--- a/source/extensions/load_balancing_policies/subset/subset_lb.h
+++ b/source/extensions/load_balancing_policies/subset/subset_lb.h
@@ -9,6 +9,8 @@
 
 #include "envoy/common/optref.h"
 #include "envoy/config/cluster/v3/cluster.pb.h"
+#include "envoy/extensions/load_balancing_policies/subset/v3/subset.pb.h"
+#include "envoy/extensions/load_balancing_policies/subset/v3/subset.pb.validate.h"
 #include "envoy/runtime/runtime.h"
 #include "envoy/stats/scope.h"
 #include "envoy/upstream/load_balancer.h"
@@ -27,19 +29,143 @@ namespace Upstream {
 
 using HostHashSet = absl::flat_hash_set;
 
-class SubsetLoadBalancer : public LoadBalancer, Logger::Loggable {
+using SubsetLoadbalancingPolicyProto =
+    envoy::extensions::load_balancing_policies::subset::v3::Subset;
+
+class ChildLoadBalancerCreator {
+public:
+  virtual ~ChildLoadBalancerCreator() = default;
+
+  virtual std::pair
+  createLoadBalancer(const PrioritySet& child_priority_set, const PrioritySet* local_priority_set,
+                     ClusterLbStats& stats, Stats::Scope& scope, Runtime::Loader& runtime,
+                     Random::RandomGenerator& random, TimeSource& time_source) PURE;
+};
+using ChildLoadBalancerCreatorPtr = std::unique_ptr;
+
+class LegacyChildLoadBalancerCreatorImpl : public Upstream::ChildLoadBalancerCreator {
 public:
-  SubsetLoadBalancer(
-      LoadBalancerType lb_type, const PrioritySet& priority_set,
-      const PrioritySet* local_priority_set, ClusterLbStats& stats, Stats::Scope& scope,
-      Runtime::Loader& runtime, Random::RandomGenerator& random,
-      const LoadBalancerSubsetInfo& subsets,
+  LegacyChildLoadBalancerCreatorImpl(
+      LoadBalancerType lb_type,
       OptRef lb_ring_hash_config,
       OptRef lb_maglev_config,
       OptRef round_robin_config,
       OptRef least_request_config,
-      const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config,
-      TimeSource& time_source);
+      const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config);
+
+  std::pair
+  createLoadBalancer(const Upstream::PrioritySet& child_priority_set,
+                     const Upstream::PrioritySet* local_priority_set, ClusterLbStats& stats,
+                     Stats::Scope& scope, Runtime::Loader& runtime, Random::RandomGenerator& random,
+                     TimeSource& time_source) override;
+
+  OptRef lbRoundRobinConfig() const {
+    if (round_robin_config_ != nullptr) {
+      return *round_robin_config_;
+    }
+    return absl::nullopt;
+  }
+
+  LoadBalancerType lbType() const { return lb_type_; }
+
+  OptRef
+  lbLeastRequestConfig() const {
+    if (least_request_config_ != nullptr) {
+      return *least_request_config_;
+    }
+    return absl::nullopt;
+  }
+
+  OptRef lbMaglevConfig() const {
+    if (lb_maglev_config_ != nullptr) {
+      return *lb_maglev_config_;
+    }
+    return absl::nullopt;
+  }
+
+  OptRef lbRingHashConfig() const {
+    if (lb_ring_hash_config_ != nullptr) {
+      return *lb_ring_hash_config_;
+    }
+    return absl::nullopt;
+  }
+
+private:
+  const LoadBalancerType lb_type_;
+  const std::unique_ptr
+      lb_ring_hash_config_;
+  const std::unique_ptr
+      lb_maglev_config_;
+  const std::unique_ptr
+      round_robin_config_;
+  const std::unique_ptr
+      least_request_config_;
+  const envoy::config::cluster::v3::Cluster::CommonLbConfig common_config_;
+};
+
+template 
+class LoadBalancerSubsetInfoImplBase : public Upstream::LoadBalancerSubsetInfo {
+public:
+  // TODO(wbpcode): use legacy enum for backward compatibility for now.
+  using FallbackPolicy =
+      envoy::config::cluster::v3::Cluster::LbSubsetConfig::LbSubsetFallbackPolicy;
+  using MetadataFallbackPolicy =
+      envoy::config::cluster::v3::Cluster::LbSubsetConfig::LbSubsetMetadataFallbackPolicy;
+  using SubsetFallbackPolicy = envoy::config::cluster::v3::Cluster::LbSubsetConfig::
+      LbSubsetSelector::LbSubsetSelectorFallbackPolicy;
+
+  LoadBalancerSubsetInfoImplBase(const ProtoType& subset_config)
+      : default_subset_(subset_config.default_subset()),
+        fallback_policy_(static_cast(subset_config.fallback_policy())),
+        metadata_fallback_policy_(
+            static_cast(subset_config.metadata_fallback_policy())),
+        enabled_(!subset_config.subset_selectors().empty()),
+        locality_weight_aware_(subset_config.locality_weight_aware()),
+        scale_locality_weight_(subset_config.scale_locality_weight()),
+        panic_mode_any_(subset_config.panic_mode_any()), list_as_any_(subset_config.list_as_any()) {
+    for (const auto& subset : subset_config.subset_selectors()) {
+      if (!subset.keys().empty()) {
+        subset_selectors_.emplace_back(std::make_shared(
+            subset.keys(), static_cast(subset.fallback_policy()),
+            subset.fallback_keys_subset(), subset.single_host_per_subset()));
+      }
+    }
+  }
+
+  // Upstream::LoadBalancerSubsetInfo
+  bool isEnabled() const override { return enabled_; }
+  FallbackPolicy fallbackPolicy() const override { return fallback_policy_; }
+  MetadataFallbackPolicy metadataFallbackPolicy() const override {
+    return metadata_fallback_policy_;
+  }
+  const ProtobufWkt::Struct& defaultSubset() const override { return default_subset_; }
+  const std::vector& subsetSelectors() const override {
+    return subset_selectors_;
+  }
+  bool localityWeightAware() const override { return locality_weight_aware_; }
+  bool scaleLocalityWeight() const override { return scale_locality_weight_; }
+  bool panicModeAny() const override { return panic_mode_any_; }
+  bool listAsAny() const override { return list_as_any_; }
+
+private:
+  const ProtobufWkt::Struct default_subset_;
+  std::vector subset_selectors_;
+  // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
+  const FallbackPolicy fallback_policy_;
+  const MetadataFallbackPolicy metadata_fallback_policy_;
+  const bool enabled_ : 1;
+  const bool locality_weight_aware_ : 1;
+  const bool scale_locality_weight_ : 1;
+  const bool panic_mode_any_ : 1;
+  const bool list_as_any_ : 1;
+};
+
+class SubsetLoadBalancer : public LoadBalancer, Logger::Loggable {
+public:
+  SubsetLoadBalancer(const LoadBalancerSubsetInfo& subsets, ChildLoadBalancerCreatorPtr child_lb,
+                     const PrioritySet& priority_set, const PrioritySet* local_priority_set,
+                     ClusterLbStats& stats, Stats::Scope& scope, Runtime::Loader& runtime,
+                     Random::RandomGenerator& random, TimeSource& time_source);
   ~SubsetLoadBalancer() override;
 
   // Upstream::LoadBalancer
@@ -128,6 +254,7 @@ class SubsetLoadBalancer : public LoadBalancer, Logger::Loggable;
   using MetadataFallbacks = ProtobufWkt::RepeatedPtrField;
 
+public:
   class LoadBalancerContextWrapper : public LoadBalancerContext {
   public:
     LoadBalancerContextWrapper(LoadBalancerContext* wrapped,
@@ -194,6 +322,7 @@ class SubsetLoadBalancer : public LoadBalancer, Logger::Loggable lbRoundRobinConfig() const {
-    if (round_robin_config_ != nullptr) {
-      return *round_robin_config_;
-    }
-    return absl::nullopt;
-  }
-
-  OptRef
-  lbLeastRequestConfig() const {
-    if (least_request_config_ != nullptr) {
-      return *least_request_config_;
-    }
-    return absl::nullopt;
-  }
-
-  OptRef lbMaglevConfig() const {
-    if (lb_maglev_config_ != nullptr) {
-      return *lb_maglev_config_;
-    }
-    return absl::nullopt;
-  }
-
-  OptRef lbRingHashConfig() const {
-    if (lb_ring_hash_config_ != nullptr) {
-      return *lb_ring_hash_config_;
-    }
-    return absl::nullopt;
-  }
-
-  const std::unique_ptr
-      lb_ring_hash_config_;
-  const std::unique_ptr
-      lb_maglev_config_;
-  const std::unique_ptr
-      round_robin_config_;
-  const std::unique_ptr
-      least_request_config_;
-  const envoy::config::cluster::v3::Cluster::CommonLbConfig common_config_;
   ClusterLbStats& stats_;
   Stats::Scope& scope_;
   Runtime::Loader& runtime_;
   Random::RandomGenerator& random_;
+  TimeSource& time_source_;
 
   const envoy::config::cluster::v3::Cluster::LbSubsetConfig::LbSubsetFallbackPolicy
       fallback_policy_;
@@ -411,6 +503,8 @@ class SubsetLoadBalancer : public LoadBalancer, Logger::Loggableclusters().getCluster("cluster_1");
   EXPECT_NE(cluster, absl::nullopt);
-  EXPECT_NE(cluster->get().info()->loadBalancingPolicy(), nullptr);
+  EXPECT_TRUE(cluster->get().info()->loadBalancerConfig().has_value());
 }
 
 class ClusterManagerImplThreadAwareLbTest : public ClusterManagerImplTest {
diff --git a/test/common/upstream/load_balancer_benchmark.cc b/test/common/upstream/load_balancer_benchmark.cc
index 89b001f2b7fc..4f9a22e94b77 100644
--- a/test/common/upstream/load_balancer_benchmark.cc
+++ b/test/common/upstream/load_balancer_benchmark.cc
@@ -554,10 +554,12 @@ class SubsetLbTester : public BaseTester {
     *selector->mutable_keys()->Add() = std::string(metadata_key);
 
     subset_info_ = std::make_unique(subset_config);
-    lb_ = std::make_unique(
-        LoadBalancerType::Random, priority_set_, &local_priority_set_, stats_, stats_scope_,
-        runtime_, random_, *subset_info_, absl::nullopt, absl::nullopt, absl::nullopt,
-        absl::nullopt, common_config_, simTime());
+    auto child_lb_creator = std::make_unique(
+        LoadBalancerType::Random, absl::nullopt, absl::nullopt, absl::nullopt, absl::nullopt,
+        common_config_);
+    lb_ = std::make_unique(*subset_info_, std::move(child_lb_creator),
+                                               priority_set_, &local_priority_set_, stats_,
+                                               stats_scope_, runtime_, random_, simTime());
 
     const HostVector& hosts = priority_set_.getOrCreateHostSet(0).hosts();
     ASSERT(hosts.size() == num_hosts);
diff --git a/test/common/upstream/subset_lb_test.cc b/test/common/upstream/subset_lb_test.cc
index f030eaf2b53d..0902264c537c 100644
--- a/test/common/upstream/subset_lb_test.cc
+++ b/test/common/upstream/subset_lb_test.cc
@@ -48,16 +48,24 @@ class SubsetLoadBalancerInternalStateTester {
     EXPECT_EQ(expected, lb_.get()->describeMetadata(subset_metadata));
   }
 
-  void validateLbTypeConfigs(LoadBalancerType lb_type) const {
+  void validateLbTypeConfigs() const {
+    const auto* legacy_child_lb_creator =
+        dynamic_cast(lb_->child_lb_creator_.get());
+
+    if (legacy_child_lb_creator == nullptr) {
+      return;
+    }
+
     // Each of these expects that an lb_type is set to that type iff the
     // returned config for that type exists.
-    EXPECT_EQ(lb_type == LoadBalancerType::RingHash,
-              lb_.get()->lbRingHashConfig() != absl::nullopt);
-    EXPECT_EQ(lb_type == LoadBalancerType::Maglev, lb_.get()->lbMaglevConfig() != absl::nullopt);
-    EXPECT_EQ(lb_type == LoadBalancerType::RoundRobin,
-              lb_.get()->lbRoundRobinConfig() != absl::nullopt);
-    EXPECT_EQ(lb_type == LoadBalancerType::LeastRequest,
-              lb_.get()->lbLeastRequestConfig() != absl::nullopt);
+    EXPECT_EQ(legacy_child_lb_creator->lbType() == LoadBalancerType::RingHash,
+              legacy_child_lb_creator->lbRingHashConfig() != absl::nullopt);
+    EXPECT_EQ(legacy_child_lb_creator->lbType() == LoadBalancerType::Maglev,
+              legacy_child_lb_creator->lbMaglevConfig() != absl::nullopt);
+    EXPECT_EQ(legacy_child_lb_creator->lbType() == LoadBalancerType::RoundRobin,
+              legacy_child_lb_creator->lbRoundRobinConfig() != absl::nullopt);
+    EXPECT_EQ(legacy_child_lb_creator->lbType() == LoadBalancerType::LeastRequest,
+              legacy_child_lb_creator->lbLeastRequestConfig() != absl::nullopt);
   }
 
 private:
@@ -250,8 +258,8 @@ class SubsetLoadBalancerTest : public Event::TestUsingSimulatedTime,
       configureHostSet(failover_host_metadata, *priority_set_.getMockHostSet(1));
     }
 
-    lb_ = std::make_shared(
-        lb_type_, priority_set_, nullptr, stats_, *scope_, runtime_, random_, subset_info_,
+    auto child_lb_creator = std::make_unique(
+        lb_type_,
         lb_type_ == LoadBalancerType::RingHash
             ? makeOptRef(
                   ring_hash_lb_config_)
@@ -268,7 +276,11 @@ class SubsetLoadBalancerTest : public Event::TestUsingSimulatedTime,
             ? makeOptRef(
                   least_request_lb_config_)
             : absl::nullopt,
-        common_config_, simTime());
+        common_config_);
+
+    lb_ = std::make_shared(subset_info_, std::move(child_lb_creator),
+                                               priority_set_, nullptr, stats_, *scope_, runtime_,
+                                               random_, simTime());
   }
 
   void zoneAwareInit(const std::vector& host_metadata_per_locality,
@@ -315,10 +327,13 @@ class SubsetLoadBalancerTest : public Event::TestUsingSimulatedTime,
             std::make_shared(), HostsPerLocalityImpl::empty()),
         {}, {}, {}, absl::nullopt);
 
-    lb_ = std::make_shared(
-        lb_type_, priority_set_, &local_priority_set_, stats_, *scope_, runtime_, random_,
-        subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-        least_request_lb_config_, common_config_, simTime());
+    auto child_lb_creator = std::make_unique(
+        lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+        least_request_lb_config_, common_config_);
+
+    lb_ = std::make_shared(subset_info_, std::move(child_lb_creator),
+                                               priority_set_, &local_priority_set_, stats_, *scope_,
+                                               runtime_, random_, simTime());
   }
 
   HostSharedPtr makeHost(const std::string& url, const HostMetadata& metadata) {
@@ -1516,10 +1531,12 @@ TEST_F(SubsetLoadBalancerTest, IgnoresHostsWithoutMetadata) {
   host_set_.healthy_hosts_ = host_set_.hosts_;
   host_set_.healthy_hosts_per_locality_ = host_set_.hosts_per_locality_;
 
+  auto child_lb_creator = std::make_unique(
+      lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+      least_request_lb_config_, common_config_);
   lb_ = std::make_shared(
-      lb_type_, priority_set_, nullptr, stats_, *stats_store_.rootScope(), runtime_, random_,
-      subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-      least_request_lb_config_, common_config_, simTime());
+      subset_info_, std::move(child_lb_creator), priority_set_, nullptr, stats_,
+      *stats_store_.rootScope(), runtime_, random_, simTime());
 
   TestLoadBalancerContext context_version({{"version", "1.0"}});
 
@@ -1533,31 +1550,31 @@ TEST_F(SubsetLoadBalancerTest, IgnoresHostsWithoutMetadata) {
 TEST_P(SubsetLoadBalancerTest, LoadBalancerTypesRoundRobin) {
   doLbTypeTest(LoadBalancerType::RoundRobin);
   auto tester = SubsetLoadBalancerInternalStateTester(lb_);
-  tester.validateLbTypeConfigs(LoadBalancerType::RoundRobin);
+  tester.validateLbTypeConfigs();
 }
 
 TEST_P(SubsetLoadBalancerTest, LoadBalancerTypesLeastRequest) {
   doLbTypeTest(LoadBalancerType::LeastRequest);
   auto tester = SubsetLoadBalancerInternalStateTester(lb_);
-  tester.validateLbTypeConfigs(LoadBalancerType::LeastRequest);
+  tester.validateLbTypeConfigs();
 }
 
 TEST_P(SubsetLoadBalancerTest, LoadBalancerTypesRandom) {
   doLbTypeTest(LoadBalancerType::Random);
   auto tester = SubsetLoadBalancerInternalStateTester(lb_);
-  tester.validateLbTypeConfigs(LoadBalancerType::Random);
+  tester.validateLbTypeConfigs();
 }
 
 TEST_P(SubsetLoadBalancerTest, LoadBalancerTypesRingHash) {
   doLbTypeTest(LoadBalancerType::RingHash);
   auto tester = SubsetLoadBalancerInternalStateTester(lb_);
-  tester.validateLbTypeConfigs(LoadBalancerType::RingHash);
+  tester.validateLbTypeConfigs();
 }
 
 TEST_P(SubsetLoadBalancerTest, LoadBalancerTypesMaglev) {
   doLbTypeTest(LoadBalancerType::Maglev);
   auto tester = SubsetLoadBalancerInternalStateTester(lb_);
-  tester.validateLbTypeConfigs(LoadBalancerType::Maglev);
+  tester.validateLbTypeConfigs();
 }
 
 TEST_F(SubsetLoadBalancerTest, ZoneAwareFallback) {
@@ -1950,10 +1967,12 @@ TEST_F(SubsetLoadBalancerTest, DisabledLocalityWeightAwareness) {
       },
       host_set_, {1, 100});
 
+  auto child_lb_creator = std::make_unique(
+      lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+      least_request_lb_config_, common_config_);
   lb_ = std::make_shared(
-      lb_type_, priority_set_, nullptr, stats_, *stats_store_.rootScope(), runtime_, random_,
-      subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-      least_request_lb_config_, common_config_, simTime());
+      subset_info_, std::move(child_lb_creator), priority_set_, nullptr, stats_,
+      *stats_store_.rootScope(), runtime_, random_, simTime());
 
   TestLoadBalancerContext context({{"version", "1.1"}});
 
@@ -1974,10 +1993,12 @@ TEST_F(SubsetLoadBalancerTest, DoesNotCheckHostHealth) {
 
   EXPECT_CALL(*mock_host, weight()).WillRepeatedly(Return(1));
 
+  auto child_lb_creator = std::make_unique(
+      lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+      least_request_lb_config_, common_config_);
   lb_ = std::make_shared(
-      lb_type_, priority_set_, nullptr, stats_, *stats_store_.rootScope(), runtime_, random_,
-      subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-      least_request_lb_config_, common_config_, simTime());
+      subset_info_, std::move(child_lb_creator), priority_set_, nullptr, stats_,
+      *stats_store_.rootScope(), runtime_, random_, simTime());
 }
 
 TEST_F(SubsetLoadBalancerTest, EnabledLocalityWeightAwareness) {
@@ -1999,10 +2020,12 @@ TEST_F(SubsetLoadBalancerTest, EnabledLocalityWeightAwareness) {
       host_set_, {1, 100});
 
   common_config_.mutable_locality_weighted_lb_config();
+  auto child_lb_creator = std::make_unique(
+      lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+      least_request_lb_config_, common_config_);
   lb_ = std::make_shared(
-      lb_type_, priority_set_, nullptr, stats_, *stats_store_.rootScope(), runtime_, random_,
-      subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-      least_request_lb_config_, common_config_, simTime());
+      subset_info_, std::move(child_lb_creator), priority_set_, nullptr, stats_,
+      *stats_store_.rootScope(), runtime_, random_, simTime());
 
   TestLoadBalancerContext context({{"version", "1.1"}});
 
@@ -2036,10 +2059,12 @@ TEST_F(SubsetLoadBalancerTest, EnabledScaleLocalityWeights) {
       host_set_, {50, 50});
 
   common_config_.mutable_locality_weighted_lb_config();
+  auto child_lb_creator = std::make_unique(
+      lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+      least_request_lb_config_, common_config_);
   lb_ = std::make_shared(
-      lb_type_, priority_set_, nullptr, stats_, *stats_store_.rootScope(), runtime_, random_,
-      subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-      least_request_lb_config_, common_config_, simTime());
+      subset_info_, std::move(child_lb_creator), priority_set_, nullptr, stats_,
+      *stats_store_.rootScope(), runtime_, random_, simTime());
   TestLoadBalancerContext context({{"version", "1.1"}});
 
   // Since we scale the locality weights by number of hosts removed, we expect to see the second
@@ -2083,10 +2108,12 @@ TEST_F(SubsetLoadBalancerTest, EnabledScaleLocalityWeightsRounding) {
       host_set_, {2, 2});
 
   common_config_.mutable_locality_weighted_lb_config();
+  auto child_lb_creator = std::make_unique(
+      lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+      least_request_lb_config_, common_config_);
   lb_ = std::make_shared(
-      lb_type_, priority_set_, nullptr, stats_, *stats_store_.rootScope(), runtime_, random_,
-      subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-      least_request_lb_config_, common_config_, simTime());
+      subset_info_, std::move(child_lb_creator), priority_set_, nullptr, stats_,
+      *stats_store_.rootScope(), runtime_, random_, simTime());
   TestLoadBalancerContext context({{"version", "1.0"}});
 
   // We expect to see a 33/66 split because 2 * 1 / 2 = 1 and 2 * 3 / 4 = 1.5 -> 2
@@ -2116,10 +2143,12 @@ TEST_F(SubsetLoadBalancerTest, ScaleLocalityWeightsWithNoLocalityWeights) {
       },
       host_set_);
 
+  auto child_lb_creator = std::make_unique(
+      lb_type_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
+      least_request_lb_config_, common_config_);
   lb_ = std::make_shared(
-      lb_type_, priority_set_, nullptr, stats_, *stats_store_.rootScope(), runtime_, random_,
-      subset_info_, ring_hash_lb_config_, maglev_lb_config_, round_robin_lb_config_,
-      least_request_lb_config_, common_config_, simTime());
+      subset_info_, std::move(child_lb_creator), priority_set_, nullptr, stats_,
+      *stats_store_.rootScope(), runtime_, random_, simTime());
 }
 
 TEST_P(SubsetLoadBalancerTest, GaugesUpdatedOnDestroy) {
diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc
index b6d23ac41c2e..76c6320909d6 100644
--- a/test/common/upstream/upstream_impl_test.cc
+++ b/test/common/upstream/upstream_impl_test.cc
@@ -2385,7 +2385,7 @@ TEST_F(StaticClusterImplTest, LoadBalancingPolicyWithLbPolicy) {
   EXPECT_EQ(1UL, cluster.prioritySet().hostSetsPerPriority()[0]->healthyHosts().size());
   EXPECT_EQ(LoadBalancerType::LoadBalancingPolicyConfig, cluster.info()->lbType());
   EXPECT_TRUE(cluster.info()->addedViaApi());
-  EXPECT_NE(nullptr, cluster.info()->loadBalancingPolicy());
+  EXPECT_TRUE(cluster.info()->loadBalancerConfig().has_value());
   EXPECT_NE(nullptr, cluster.info()->loadBalancerFactory());
 }
 
diff --git a/test/extensions/load_balancing_policies/cluster_provided/config_test.cc b/test/extensions/load_balancing_policies/cluster_provided/config_test.cc
index e0966208e7aa..3bec7e1bbbd8 100644
--- a/test/extensions/load_balancing_policies/cluster_provided/config_test.cc
+++ b/test/extensions/load_balancing_policies/cluster_provided/config_test.cc
@@ -29,7 +29,7 @@ TEST(ClusterProvidedConfigTest, ClusterProvidedConfigTest) {
   EXPECT_EQ("envoy.load_balancing_policies.cluster_provided", factory.name());
 
   auto thread_aware_lb =
-      factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_,
+      factory.create({}, cluster_info, main_thread_priority_set, context.runtime_loader_,
                      context.api_.random_, context.time_system_);
   EXPECT_EQ(nullptr, thread_aware_lb);
 }
diff --git a/test/extensions/load_balancing_policies/least_request/config_test.cc b/test/extensions/load_balancing_policies/least_request/config_test.cc
index a2c4d2da2dc3..82e8405d8f00 100644
--- a/test/extensions/load_balancing_policies/least_request/config_test.cc
+++ b/test/extensions/load_balancing_policies/least_request/config_test.cc
@@ -28,11 +28,10 @@ TEST(LeastRequestConfigTest, ValidateFail) {
   auto& factory = Config::Utility::getAndCheckFactory(config);
   EXPECT_EQ("envoy.load_balancing_policies.least_request", factory.name());
 
-  auto message_ptr = factory.createEmptyConfigProto();
-  EXPECT_CALL(cluster_info, loadBalancingPolicy()).WillOnce(testing::ReturnRef(message_ptr));
-
+  auto lb_config =
+      factory.loadConfig(factory.createEmptyConfigProto(), context.messageValidationVisitor());
   auto thread_aware_lb =
-      factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_,
+      factory.create(*lb_config, cluster_info, main_thread_priority_set, context.runtime_loader_,
                      context.api_.random_, context.time_system_);
   EXPECT_NE(nullptr, thread_aware_lb);
 
diff --git a/test/extensions/load_balancing_policies/maglev/config_test.cc b/test/extensions/load_balancing_policies/maglev/config_test.cc
index 733ed14a3b4b..9b103239d2c6 100644
--- a/test/extensions/load_balancing_policies/maglev/config_test.cc
+++ b/test/extensions/load_balancing_policies/maglev/config_test.cc
@@ -30,12 +30,10 @@ TEST(MaglevConfigTest, Validate) {
     auto& factory = Config::Utility::getAndCheckFactory(config);
     EXPECT_EQ("envoy.load_balancing_policies.maglev", factory.name());
 
-    auto messsage_ptr = factory.createEmptyConfigProto();
-
-    EXPECT_CALL(cluster_info, loadBalancingPolicy()).WillOnce(testing::ReturnRef(messsage_ptr));
-
+    auto lb_config =
+        factory.loadConfig(factory.createEmptyConfigProto(), context.messageValidationVisitor());
     auto thread_aware_lb =
-        factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_,
+        factory.create(*lb_config, cluster_info, main_thread_priority_set, context.runtime_loader_,
                        context.api_.random_, context.time_system_);
     EXPECT_NE(nullptr, thread_aware_lb);
 
@@ -61,12 +59,11 @@ TEST(MaglevConfigTest, Validate) {
     auto& factory = Config::Utility::getAndCheckFactory(config);
     EXPECT_EQ("envoy.load_balancing_policies.maglev", factory.name());
 
-    auto messsage_ptr = factory.createEmptyConfigProto();
-    messsage_ptr->MergeFrom(config_msg);
-
-    EXPECT_CALL(cluster_info, loadBalancingPolicy()).WillOnce(testing::ReturnRef(messsage_ptr));
+    auto message_ptr = factory.createEmptyConfigProto();
+    message_ptr->MergeFrom(config_msg);
+    auto lb_config = factory.loadConfig(std::move(message_ptr), context.messageValidationVisitor());
 
-    EXPECT_THROW_WITH_MESSAGE(factory.create(cluster_info, main_thread_priority_set,
+    EXPECT_THROW_WITH_MESSAGE(factory.create(*lb_config, cluster_info, main_thread_priority_set,
                                              context.runtime_loader_, context.api_.random_,
                                              context.time_system_),
                               EnvoyException, "The table size of maglev must be prime number");
diff --git a/test/extensions/load_balancing_policies/random/config_test.cc b/test/extensions/load_balancing_policies/random/config_test.cc
index 54aa165bf087..869d7ef64d07 100644
--- a/test/extensions/load_balancing_policies/random/config_test.cc
+++ b/test/extensions/load_balancing_policies/random/config_test.cc
@@ -28,11 +28,10 @@ TEST(RandomConfigTest, ValidateFail) {
   auto& factory = Config::Utility::getAndCheckFactory(config);
   EXPECT_EQ("envoy.load_balancing_policies.random", factory.name());
 
-  auto message_ptr = factory.createEmptyConfigProto();
-  EXPECT_CALL(cluster_info, loadBalancingPolicy()).WillOnce(testing::ReturnRef(message_ptr));
-
+  auto lb_config =
+      factory.loadConfig(factory.createEmptyConfigProto(), context.messageValidationVisitor());
   auto thread_aware_lb =
-      factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_,
+      factory.create(*lb_config, cluster_info, main_thread_priority_set, context.runtime_loader_,
                      context.api_.random_, context.time_system_);
   EXPECT_NE(nullptr, thread_aware_lb);
 
diff --git a/test/extensions/load_balancing_policies/ring_hash/config_test.cc b/test/extensions/load_balancing_policies/ring_hash/config_test.cc
index 7f2034f76fd3..24eb9c267795 100644
--- a/test/extensions/load_balancing_policies/ring_hash/config_test.cc
+++ b/test/extensions/load_balancing_policies/ring_hash/config_test.cc
@@ -30,11 +30,10 @@ TEST(RingHashConfigTest, Validate) {
     auto& factory = Config::Utility::getAndCheckFactory(config);
     EXPECT_EQ("envoy.load_balancing_policies.ring_hash", factory.name());
 
-    auto messsage_ptr = factory.createEmptyConfigProto();
-    EXPECT_CALL(cluster_info, loadBalancingPolicy()).WillOnce(testing::ReturnRef(messsage_ptr));
-
+    auto lb_config =
+        factory.loadConfig(factory.createEmptyConfigProto(), context.messageValidationVisitor());
     auto thread_aware_lb =
-        factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_,
+        factory.create(*lb_config, cluster_info, main_thread_priority_set, context.runtime_loader_,
                        context.api_.random_, context.time_system_);
     EXPECT_NE(nullptr, thread_aware_lb);
 
@@ -64,10 +63,12 @@ TEST(RingHashConfigTest, Validate) {
     auto messsage_ptr = factory.createEmptyConfigProto();
     messsage_ptr->MergeFrom(config_msg);
 
-    EXPECT_CALL(cluster_info, loadBalancingPolicy()).WillOnce(testing::ReturnRef(messsage_ptr));
+    auto message_ptr = factory.createEmptyConfigProto();
+    message_ptr->MergeFrom(config_msg);
+    auto lb_config = factory.loadConfig(std::move(message_ptr), context.messageValidationVisitor());
 
     EXPECT_THROW_WITH_MESSAGE(
-        factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_,
+        factory.create(*lb_config, cluster_info, main_thread_priority_set, context.runtime_loader_,
                        context.api_.random_, context.time_system_),
         EnvoyException, "ring hash: minimum_ring_size (4) > maximum_ring_size (2)");
   }
diff --git a/test/extensions/load_balancing_policies/round_robin/config_test.cc b/test/extensions/load_balancing_policies/round_robin/config_test.cc
index dd8541746144..a6aa8aacd5e4 100644
--- a/test/extensions/load_balancing_policies/round_robin/config_test.cc
+++ b/test/extensions/load_balancing_policies/round_robin/config_test.cc
@@ -28,11 +28,11 @@ TEST(RoundRobinConfigTest, ValidateFail) {
   auto& factory = Config::Utility::getAndCheckFactory(config);
   EXPECT_EQ("envoy.load_balancing_policies.round_robin", factory.name());
 
-  auto message_ptr = factory.createEmptyConfigProto();
-  EXPECT_CALL(cluster_info, loadBalancingPolicy()).WillOnce(testing::ReturnRef(message_ptr));
+  auto lb_config =
+      factory.loadConfig(factory.createEmptyConfigProto(), context.messageValidationVisitor());
 
   auto thread_aware_lb =
-      factory.create(cluster_info, main_thread_priority_set, context.runtime_loader_,
+      factory.create(*lb_config, cluster_info, main_thread_priority_set, context.runtime_loader_,
                      context.api_.random_, context.time_system_);
   EXPECT_NE(nullptr, thread_aware_lb);
 
diff --git a/test/extensions/load_balancing_policies/subset/BUILD b/test/extensions/load_balancing_policies/subset/BUILD
new file mode 100644
index 000000000000..417a9affab11
--- /dev/null
+++ b/test/extensions/load_balancing_policies/subset/BUILD
@@ -0,0 +1,59 @@
+load(
+    "//bazel:envoy_build_system.bzl",
+    "envoy_package",
+)
+load(
+    "//test/extensions:extensions_build_system.bzl",
+    "envoy_extension_cc_test",
+)
+
+licenses(["notice"])  # Apache 2
+
+envoy_package()
+
+envoy_extension_cc_test(
+    name = "config_test",
+    srcs = ["config_test.cc"],
+    extension_names = ["envoy.load_balancing_policies.subset"],
+    deps = [
+        "//source/extensions/load_balancing_policies/random:config",
+        "//source/extensions/load_balancing_policies/subset:config",
+        "//test/mocks/server:factory_context_mocks",
+        "//test/mocks/upstream:cluster_info_mocks",
+        "//test/mocks/upstream:priority_set_mocks",
+        "@envoy_api//envoy/config/core/v3:pkg_cc_proto",
+        "@envoy_api//envoy/extensions/load_balancing_policies/subset/v3:pkg_cc_proto",
+    ],
+)
+
+envoy_extension_cc_test(
+    name = "integration_test",
+    size = "large",
+    srcs = ["integration_test.cc"],
+    extension_names = ["envoy.load_balancing_policies.subset"],
+    deps = [
+        "//source/common/protobuf",
+        "//source/extensions/filters/http/header_to_metadata:config",
+        "//source/extensions/load_balancing_policies/random:config",
+        "//source/extensions/load_balancing_policies/subset:config",
+        "//test/integration:http_integration_lib",
+        "//test/test_common:utility_lib",
+        "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto",
+    ],
+)
+
+envoy_extension_cc_test(
+    name = "subset_test",
+    srcs = ["subset_test.cc"],
+    extension_names = ["envoy.load_balancing_policies.subset"],
+    deps = [
+        "//source/extensions/load_balancing_policies/random:config",
+        "//source/extensions/load_balancing_policies/subset:config",
+        "//test/mocks/server:factory_context_mocks",
+        "//test/mocks/upstream:cluster_info_mocks",
+        "//test/mocks/upstream:load_balancer_context_mock",
+        "//test/mocks/upstream:priority_set_mocks",
+        "@envoy_api//envoy/config/core/v3:pkg_cc_proto",
+        "@envoy_api//envoy/extensions/load_balancing_policies/subset/v3:pkg_cc_proto",
+    ],
+)
diff --git a/test/extensions/load_balancing_policies/subset/config_test.cc b/test/extensions/load_balancing_policies/subset/config_test.cc
new file mode 100644
index 000000000000..b5d77b70384c
--- /dev/null
+++ b/test/extensions/load_balancing_policies/subset/config_test.cc
@@ -0,0 +1,114 @@
+#include "envoy/config/core/v3/extension.pb.h"
+#include "envoy/extensions/load_balancing_policies/subset/v3/subset.pb.h"
+
+#include "source/extensions/load_balancing_policies/subset/config.h"
+
+#include "test/mocks/server/factory_context.h"
+#include "test/mocks/upstream/cluster_info.h"
+#include "test/mocks/upstream/priority_set.h"
+
+#include "gtest/gtest.h"
+
+namespace Envoy {
+namespace Extensions {
+namespace LoadBalancingPolices {
+namespace Subset {
+namespace {
+
+TEST(SubsetConfigTest, SubsetConfigTest) {
+  NiceMock context;
+  NiceMock cluster_info;
+  NiceMock main_thread_priority_set;
+  NiceMock thread_local_priority_set;
+
+  envoy::config::core::v3::TypedExtensionConfig config;
+  config.set_name("envoy.load_balancing_policies.subset");
+  auto config_msg =
+      std::make_unique();
+
+  const std::string config_yaml = R"EOF(
+    fallback_policy: ANY_ENDPOINT
+    subset_selectors:
+      - keys:
+          - "version"
+          - "stage"
+        fallback_policy: NO_FALLBACK
+      - keys:
+          - "version"
+        fallback_policy: ANY_ENDPOINT
+    list_as_any: true
+    subset_lb_policy:
+      policies:
+        - typed_extension_config:
+            name: envoy.load_balancing_policies.random
+            typed_config:
+              "@type": type.googleapis.com/envoy.extensions.load_balancing_policies.random.v3.Random
+    )EOF";
+  TestUtility::loadFromYaml(config_yaml, *config_msg);
+  config.mutable_typed_config()->PackFrom(*config_msg);
+
+  auto& factory = Config::Utility::getAndCheckFactory(config);
+  EXPECT_EQ("envoy.load_balancing_policies.subset", factory.name());
+
+  auto lb_config = factory.loadConfig(std::move(config_msg), context.messageValidationVisitor());
+
+  auto thread_aware_lb =
+      factory.create(*lb_config, cluster_info, main_thread_priority_set, context.runtime_loader_,
+                     context.api_.random_, context.time_system_);
+  EXPECT_NE(nullptr, thread_aware_lb);
+
+  thread_aware_lb->initialize();
+
+  auto thread_local_lb_factory = thread_aware_lb->factory();
+  EXPECT_NE(nullptr, thread_local_lb_factory);
+
+  auto thread_local_lb = thread_local_lb_factory->create({thread_local_priority_set, nullptr});
+  EXPECT_NE(nullptr, thread_local_lb);
+
+  EXPECT_DEATH(thread_local_lb_factory->create(), "not implemented");
+}
+
+TEST(SubsetConfigTest, SubsetConfigTestWithUnknownSubsetLoadBalancingPolicy) {
+  NiceMock context;
+  NiceMock cluster_info;
+  NiceMock main_thread_priority_set;
+  NiceMock thread_local_priority_set;
+
+  envoy::config::core::v3::TypedExtensionConfig config;
+  config.set_name("envoy.load_balancing_policies.subset");
+  auto config_msg =
+      std::make_unique();
+
+  const std::string config_yaml = R"EOF(
+    fallback_policy: ANY_ENDPOINT
+    subset_selectors:
+      - keys:
+          - "version"
+          - "stage"
+        fallback_policy: NO_FALLBACK
+      - keys:
+          - "version"
+        fallback_policy: ANY_ENDPOINT
+    list_as_any: true
+    subset_lb_policy:
+      policies:
+        - typed_extension_config:
+            name: envoy.load_balancing_policies.unknown
+    )EOF";
+  TestUtility::loadFromYaml(config_yaml, *config_msg);
+  config.mutable_typed_config()->PackFrom(*config_msg);
+
+  auto& factory = Config::Utility::getAndCheckFactory(config);
+  EXPECT_EQ("envoy.load_balancing_policies.subset", factory.name());
+
+  EXPECT_THROW_WITH_MESSAGE(
+      factory.loadConfig(std::move(config_msg), context.messageValidationVisitor()), EnvoyException,
+      "cluster: didn't find a registered load balancer factory implementation for subset lb with "
+      "names from [envoy.load_balancing_policies.unknown]");
+}
+
+} // namespace
+} // namespace Subset
+} // namespace LoadBalancingPolices
+} // namespace Extensions
+} // namespace Envoy
diff --git a/test/extensions/load_balancing_policies/subset/integration_test.cc b/test/extensions/load_balancing_policies/subset/integration_test.cc
new file mode 100644
index 000000000000..e995d26ee6c8
--- /dev/null
+++ b/test/extensions/load_balancing_policies/subset/integration_test.cc
@@ -0,0 +1,151 @@
+#include 
+#include 
+
+#include "envoy/config/endpoint/v3/endpoint_components.pb.h"
+
+#include "source/common/common/base64.h"
+#include "source/common/http/utility.h"
+#include "source/common/protobuf/protobuf.h"
+#include "source/extensions/load_balancing_policies/random/config.h"
+
+#include "test/integration/http_integration.h"
+
+#include "gtest/gtest.h"
+
+namespace Envoy {
+namespace Extensions {
+namespace LoadBalancingPolices {
+namespace Subset {
+namespace {
+
+class SubsetIntegrationTest : public testing::TestWithParam,
+                              public HttpIntegrationTest {
+public:
+  SubsetIntegrationTest() : HttpIntegrationTest(Http::CodecType::HTTP1, GetParam()) {
+    setUpstreamCount(3);
+
+    // Add the header to metadata filter to help set the metadata for subset load balancer.
+    config_helper_.prependFilter(R"EOF(
+    name: envoy.filters.http.header_to_metadata
+    typed_config:
+      "@type": type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config
+      request_rules:
+      - header: "version"
+        on_header_present:
+          metadata_namespace: "envoy.lb"
+          key: "version"
+    )EOF");
+
+    // Update endpoints of default cluster `cluster_0` to 3 different fake upstreams.
+    config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) {
+      auto* cluster_0 = bootstrap.mutable_static_resources()->mutable_clusters()->Mutable(0);
+      ASSERT(cluster_0->name() == "cluster_0");
+      auto* endpoint = cluster_0->mutable_load_assignment()->mutable_endpoints()->Mutable(0);
+
+      constexpr absl::string_view endpoints_yaml = R"EOF(
+        lb_endpoints:
+        - endpoint:
+            address:
+              socket_address:
+                address: {}
+                port_value: 0
+          metadata:
+            filter_metadata:
+              envoy.lb:
+                version: v1
+                stage: canary
+        - endpoint:
+            address:
+              socket_address:
+                address: {}
+                port_value: 0
+          metadata:
+            filter_metadata:
+              envoy.lb:
+                version: v2
+                stage: canary
+        - endpoint:
+            address:
+              socket_address:
+                address: {}
+                port_value: 0
+          metadata:
+            filter_metadata:
+              envoy.lb:
+                version: v3
+      )EOF";
+
+      const std::string local_address = Network::Test::getLoopbackAddressString(GetParam());
+      TestUtility::loadFromYaml(
+          fmt::format(endpoints_yaml, local_address, local_address, local_address), *endpoint);
+
+      auto* policy = cluster_0->mutable_load_balancing_policy();
+
+      const std::string policy_yaml = R"EOF(
+        policies:
+        - typed_extension_config:
+            name: envoy.load_balancing_policies.subset
+            typed_config:
+              "@type": type.googleapis.com/envoy.extensions.load_balancing_policies.subset.v3.Subset
+              fallback_policy: ANY_ENDPOINT
+              subset_selectors:
+              - keys:
+                - "version"
+                - "stage"
+                fallback_policy: NO_FALLBACK
+              - keys:
+                - "version"
+                fallback_policy: ANY_ENDPOINT
+              list_as_any: true
+              subset_lb_policy:
+                policies:
+                - typed_extension_config:
+                    name: envoy.load_balancing_policies.random
+                    typed_config:
+                      "@type": type.googleapis.com/envoy.extensions.load_balancing_policies.random.v3.Random
+       )EOF";
+
+      TestUtility::loadFromYaml(policy_yaml, *policy);
+    });
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(IpVersions, SubsetIntegrationTest,
+                         testing::ValuesIn(TestEnvironment::getIpVersionsForTest()),
+                         TestUtility::ipTestParamsToString);
+
+// Test the case where the subset load balancer is configured by the load balancing
+// policy API and it works as expected.
+TEST_P(SubsetIntegrationTest, NormalLoadBalancing) {
+  initialize();
+
+  for (uint64_t i = 1; i <= 3; i++) {
+
+    codec_client_ = makeHttpConnection(lookupPort("http"));
+
+    Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"},
+                                                   {":path", "/"},
+                                                   {":scheme", "http"},
+                                                   {":authority", "example.com"},
+                                                   {"version", fmt::format("v{}", i)}};
+
+    auto response = codec_client_->makeRequestWithBody(request_headers, 0);
+
+    waitForNextUpstreamRequest(i - 1);
+
+    upstream_request_->encodeHeaders(default_response_headers_, true);
+
+    ASSERT_TRUE(response->waitForEndStream());
+
+    EXPECT_TRUE(upstream_request_->complete());
+    EXPECT_TRUE(response->complete());
+
+    cleanupUpstreamAndDownstream();
+  }
+}
+
+} // namespace
+} // namespace Subset
+} // namespace LoadBalancingPolices
+} // namespace Extensions
+} // namespace Envoy
diff --git a/test/extensions/load_balancing_policies/subset/subset_test.cc b/test/extensions/load_balancing_policies/subset/subset_test.cc
new file mode 100644
index 000000000000..c91df65bb5ca
--- /dev/null
+++ b/test/extensions/load_balancing_policies/subset/subset_test.cc
@@ -0,0 +1,58 @@
+#include "envoy/config/core/v3/extension.pb.h"
+#include "envoy/extensions/load_balancing_policies/subset/v3/subset.pb.h"
+
+#include "source/common/router/metadatamatchcriteria_impl.h"
+#include "source/extensions/load_balancing_policies/subset/config.h"
+
+#include "test/mocks/server/factory_context.h"
+#include "test/mocks/upstream/cluster_info.h"
+#include "test/mocks/upstream/load_balancer_context.h"
+#include "test/mocks/upstream/priority_set.h"
+
+#include "gtest/gtest.h"
+
+namespace Envoy {
+namespace Extensions {
+namespace LoadBalancingPolices {
+namespace Subset {
+namespace {
+
+// Test to improve coverage of the SubsetLoadBalancerFactory.
+TEST(LoadBalancerContextWrapperTest, LoadBalancingContextWrapperTest) {
+  testing::NiceMock mock_context;
+
+  ProtobufWkt::Struct empty_struct;
+  Router::MetadataMatchCriteriaImpl match_criteria(empty_struct);
+  ON_CALL(mock_context, metadataMatchCriteria()).WillByDefault(testing::Return(&match_criteria));
+
+  Upstream::SubsetLoadBalancer::LoadBalancerContextWrapper wrapper(&mock_context,
+                                                                   std::set{});
+
+  EXPECT_CALL(mock_context, computeHashKey());
+  wrapper.computeHashKey();
+
+  EXPECT_CALL(mock_context, downstreamConnection());
+  wrapper.downstreamConnection();
+
+  EXPECT_CALL(mock_context, downstreamHeaders());
+  wrapper.downstreamHeaders();
+
+  EXPECT_CALL(mock_context, hostSelectionRetryCount());
+
+  wrapper.hostSelectionRetryCount();
+
+  EXPECT_CALL(mock_context, upstreamSocketOptions());
+  wrapper.upstreamSocketOptions();
+
+  EXPECT_CALL(mock_context, upstreamTransportSocketOptions());
+  wrapper.upstreamTransportSocketOptions();
+
+  EXPECT_CALL(mock_context, overrideHostToSelect());
+  wrapper.overrideHostToSelect();
+}
+
+} // namespace
+} // namespace Subset
+} // namespace LoadBalancingPolices
+} // namespace Extensions
+} // namespace Envoy
diff --git a/test/integration/load_balancers/custom_lb_policy.h b/test/integration/load_balancers/custom_lb_policy.h
index a6d4ed239174..8147dcd6b2f6 100644
--- a/test/integration/load_balancers/custom_lb_policy.h
+++ b/test/integration/load_balancers/custom_lb_policy.h
@@ -60,7 +60,8 @@ class CustomLbFactory : public Upstream::TypedLoadBalancerFactoryBase<
 public:
   CustomLbFactory() : TypedLoadBalancerFactoryBase("envoy.load_balancers.custom_lb") {}
 
-  Upstream::ThreadAwareLoadBalancerPtr create(const Upstream::ClusterInfo&,
+  Upstream::ThreadAwareLoadBalancerPtr create(OptRef,
+                                              const Upstream::ClusterInfo&,
                                               const Upstream::PrioritySet&, Runtime::Loader&,
                                               Random::RandomGenerator&, TimeSource&) override {
     return std::make_unique();
diff --git a/test/mocks/upstream/BUILD b/test/mocks/upstream/BUILD
index ec4625080fb1..8b4258c4f668 100644
--- a/test/mocks/upstream/BUILD
+++ b/test/mocks/upstream/BUILD
@@ -216,6 +216,7 @@ envoy_cc_mock(
     hdrs = ["typed_load_balancer_factory.h"],
     deps = [
         "//envoy/upstream:load_balancer_interface",
+        "//source/common/upstream:load_balancer_factory_base_lib",
     ],
 )
 
diff --git a/test/mocks/upstream/cluster_info.cc b/test/mocks/upstream/cluster_info.cc
index 6fd33414a641..b24f9069f58e 100644
--- a/test/mocks/upstream/cluster_info.cc
+++ b/test/mocks/upstream/cluster_info.cc
@@ -198,7 +198,8 @@ MockClusterInfo::MockClusterInfo()
             manager.applyFilterFactoryCb({}, factory_cb);
             return true;
           }));
-  ON_CALL(*this, loadBalancingPolicy).WillByDefault(ReturnRef(load_balancing_policy_));
+  ON_CALL(*this, loadBalancerConfig())
+      .WillByDefault(Return(makeOptRefFromPtr(nullptr)));
   ON_CALL(*this, makeHeaderValidator(_)).WillByDefault(Invoke([&](Http::Protocol protocol) {
     return header_validator_factory_ ? header_validator_factory_->createClientHeaderValidator(
                                            protocol, codecStats(protocol))
diff --git a/test/mocks/upstream/cluster_info.h b/test/mocks/upstream/cluster_info.h
index 3c92b980557d..d81f84b94265 100644
--- a/test/mocks/upstream/cluster_info.h
+++ b/test/mocks/upstream/cluster_info.h
@@ -126,7 +126,7 @@ class MockClusterInfo : public ClusterInfo {
               (const));
   MOCK_METHOD(ProtocolOptionsConfigConstSharedPtr, extensionProtocolOptions, (const std::string&),
               (const));
-  MOCK_METHOD(const ProtobufTypes::MessagePtr&, loadBalancingPolicy, (), (const));
+  MOCK_METHOD(OptRef, loadBalancerConfig, (), (const));
   MOCK_METHOD(TypedLoadBalancerFactory*, loadBalancerFactory, (), (const));
   MOCK_METHOD(const envoy::config::cluster::v3::Cluster::CommonLbConfig&, lbConfig, (), (const));
   MOCK_METHOD(LoadBalancerType, lbType, (), (const));
@@ -253,7 +253,6 @@ class MockClusterInfo : public ClusterInfo {
   mutable Http::Http1::CodecStats::AtomicPtr http1_codec_stats_;
   mutable Http::Http2::CodecStats::AtomicPtr http2_codec_stats_;
   mutable Http::Http3::CodecStats::AtomicPtr http3_codec_stats_;
-  ProtobufTypes::MessagePtr load_balancing_policy_;
   Http::HeaderValidatorFactoryPtr header_validator_factory_;
 };
 
diff --git a/test/mocks/upstream/typed_load_balancer_factory.h b/test/mocks/upstream/typed_load_balancer_factory.h
index eb8b0cb8d4f3..a2ec9a45e18d 100644
--- a/test/mocks/upstream/typed_load_balancer_factory.h
+++ b/test/mocks/upstream/typed_load_balancer_factory.h
@@ -2,6 +2,8 @@
 
 #include "envoy/upstream/load_balancer.h"
 
+#include "source/common/upstream/load_balancer_factory_base.h"
+
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -15,8 +17,14 @@ class MockTypedLoadBalancerFactory : public TypedLoadBalancerFactory {
   // Upstream::TypedLoadBalancerFactory
   MOCK_METHOD(std::string, name, (), (const));
   MOCK_METHOD(ThreadAwareLoadBalancerPtr, create,
-              (const ClusterInfo& cluster_info, const PrioritySet& priority_set,
-               Runtime::Loader& runtime, Random::RandomGenerator& random, TimeSource& time_source));
+              (OptRef lb_config, const ClusterInfo& cluster_info,
+               const PrioritySet& priority_set, Runtime::Loader& runtime,
+               Random::RandomGenerator& random, TimeSource& time_source));
+
+  LoadBalancerConfigPtr loadConfig(ProtobufTypes::MessagePtr config,
+                                   ProtobufMessage::ValidationVisitor&) override {
+    return std::make_unique(std::move(config));
+  }
 
   ProtobufTypes::MessagePtr createEmptyConfigProto() override {
     // Using Struct instead of a custom per-filter empty config proto

From a216acd3cfac2e14932e40e14e35198400d30864 Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Wed, 7 Jun 2023 08:31:53 -0400
Subject: [PATCH 195/228] build: adding an disable_exceptions (which does not
 yet work) (#27811)

The new build option simply compiles out all try/catch code, while leaving in the exceptions. This can not yet be successfully used as it turns up fno-exceptions which chokes on throw statements. This is by design as if we compiled out throw as well, config failures would be fatal instead of gracefully handled.

Risk Level: low
Testing: manual testing
Docs Changes: n/a
Release Notes: n/a
Part of #27412

Signed-off-by: Alyssa Wilk 
---
 bazel/BUILD                                   |  7 +++
 bazel/envoy_build_system.bzl                  |  2 +
 bazel/envoy_internal.bzl                      |  3 +-
 bazel/envoy_mobile_defines.bzl                |  3 +-
 bazel/envoy_select.bzl                        |  7 +++
 mobile/library/common/engine.cc               | 10 ++--
 source/common/common/thread.h                 | 31 ++++++++++-
 source/common/filter/config_discovery_impl.cc |  5 +-
 source/common/router/header_parser_utils.cc   |  5 +-
 source/common/runtime/runtime_impl.cc         |  4 +-
 source/common/secret/sds_api.cc               |  4 +-
 source/common/stats/tag_extractor_impl.cc     |  5 +-
 source/common/upstream/cds_api_helper.cc      |  6 +--
 .../upstream/health_discovery_service.cc      |  4 +-
 source/common/upstream/upstream_impl.cc       |  4 +-
 source/exe/stripped_main_base.cc              |  4 +-
 .../file_based_metadata/config.cc             |  3 +-
 .../network/dns_resolver/cares/dns_impl.cc    |  1 +
 source/server/options_impl.cc                 | 25 +++++----
 source/server/server.cc                       | 54 +++++++++----------
 20 files changed, 114 insertions(+), 73 deletions(-)

diff --git a/bazel/BUILD b/bazel/BUILD
index ca8db723eb3e..1ad963a26072 100644
--- a/bazel/BUILD
+++ b/bazel/BUILD
@@ -375,6 +375,13 @@ config_setting(
     values = {"define": "envoy_yaml=disabled"},
 )
 
+# The goal here is to allow Envoy to build with this option but it is not yet
+# complete.  See https://github.com/envoyproxy/envoy/issues/27412
+config_setting(
+    name = "disable_exceptions",
+    values = {"define": "envoy_exceptions=disabled"},
+)
+
 config_setting(
     name = "disable_envoy_mobile_listener",
     values = {"define": "envoy_mobile_listener=disabled"},
diff --git a/bazel/envoy_build_system.bzl b/bazel/envoy_build_system.bzl
index da025768f034..8f05c9fcb8ff 100644
--- a/bazel/envoy_build_system.bzl
+++ b/bazel/envoy_build_system.bzl
@@ -22,6 +22,7 @@ load(
     _envoy_select_admin_html = "envoy_select_admin_html",
     _envoy_select_admin_no_html = "envoy_select_admin_no_html",
     _envoy_select_boringssl = "envoy_select_boringssl",
+    _envoy_select_disable_exceptions = "envoy_select_disable_exceptions",
     _envoy_select_disable_logging = "envoy_select_disable_logging",
     _envoy_select_enable_http3 = "envoy_select_enable_http3",
     _envoy_select_enable_http_datagrams = "envoy_select_enable_http_datagrams",
@@ -242,6 +243,7 @@ envoy_select_disable_logging = _envoy_select_disable_logging
 envoy_select_google_grpc = _envoy_select_google_grpc
 envoy_select_enable_http3 = _envoy_select_enable_http3
 envoy_select_enable_yaml = _envoy_select_enable_yaml
+envoy_select_disable_exceptions = _envoy_select_disable_exceptions
 envoy_select_hot_restart = _envoy_select_hot_restart
 envoy_select_enable_http_datagrams = _envoy_select_enable_http_datagrams
 envoy_select_signal_trace = _envoy_select_signal_trace
diff --git a/bazel/envoy_internal.bzl b/bazel/envoy_internal.bzl
index 472dfd2fa483..a1f8f1dc6e50 100644
--- a/bazel/envoy_internal.bzl
+++ b/bazel/envoy_internal.bzl
@@ -1,6 +1,6 @@
 # DO NOT LOAD THIS FILE. Targets from this file should be considered private
 # and not used outside of the @envoy//bazel package.
-load(":envoy_select.bzl", "envoy_select_admin_html", "envoy_select_disable_logging", "envoy_select_google_grpc", "envoy_select_hot_restart", "envoy_select_signal_trace", "envoy_select_static_extension_registration")
+load(":envoy_select.bzl", "envoy_select_admin_html", "envoy_select_disable_exceptions", "envoy_select_disable_logging", "envoy_select_google_grpc", "envoy_select_hot_restart", "envoy_select_signal_trace", "envoy_select_static_extension_registration")
 
 # Compute the final copts based on various options.
 def envoy_copts(repository, test = False):
@@ -119,6 +119,7 @@ def envoy_copts(repository, test = False):
                repository + "//bazel:uhv_enabled": ["-DENVOY_ENABLE_UHV"],
                "//conditions:default": [],
            }) + envoy_select_hot_restart(["-DENVOY_HOT_RESTART"], repository) + \
+           envoy_select_disable_exceptions(["-fno-unwind-tables", "-fno-exceptions"], repository) + \
            envoy_select_admin_html(["-DENVOY_ADMIN_HTML"], repository) + \
            envoy_select_static_extension_registration(["-DENVOY_STATIC_EXTENSION_REGISTRATION"], repository) + \
            envoy_select_disable_logging(["-DENVOY_DISABLE_LOGGING"], repository) + \
diff --git a/bazel/envoy_mobile_defines.bzl b/bazel/envoy_mobile_defines.bzl
index df2fd7a7cdbf..5bce8ebef8bf 100644
--- a/bazel/envoy_mobile_defines.bzl
+++ b/bazel/envoy_mobile_defines.bzl
@@ -1,11 +1,12 @@
 # DO NOT LOAD THIS FILE. Load envoy_build_system.bzl instead.
-load(":envoy_select.bzl", "envoy_select_admin_functionality", "envoy_select_enable_http3", "envoy_select_enable_http_datagrams", "envoy_select_enable_yaml", "envoy_select_envoy_mobile_listener", "envoy_select_envoy_mobile_request_compression", "envoy_select_envoy_mobile_stats_reporting", "envoy_select_google_grpc")
+load(":envoy_select.bzl", "envoy_select_admin_functionality", "envoy_select_disable_exceptions", "envoy_select_enable_http3", "envoy_select_enable_http_datagrams", "envoy_select_enable_yaml", "envoy_select_envoy_mobile_listener", "envoy_select_envoy_mobile_request_compression", "envoy_select_envoy_mobile_stats_reporting", "envoy_select_google_grpc")
 
 # Compute the defines needed for Envoy Mobile libraries that don't use Envoy's main library wrappers.
 def envoy_mobile_defines(repository):
     return envoy_select_admin_functionality(["ENVOY_ADMIN_FUNCTIONALITY"], repository) + \
            envoy_select_enable_http3(["ENVOY_ENABLE_QUIC"], repository) + \
            envoy_select_enable_yaml(["ENVOY_ENABLE_YAML"], repository) + \
+           envoy_select_disable_exceptions(["ENVOY_DISABLE_EXCEPTIONS"], repository) + \
            envoy_select_enable_http_datagrams(["ENVOY_ENABLE_HTTP_DATAGRAMS"], repository) + \
            envoy_select_envoy_mobile_listener(["ENVOY_MOBILE_ENABLE_LISTENER"], repository) + \
            envoy_select_envoy_mobile_stats_reporting(["ENVOY_MOBILE_STATS_REPORTING"], repository) + \
diff --git a/bazel/envoy_select.bzl b/bazel/envoy_select.bzl
index 7fee86b3eeab..7cd774bd460e 100644
--- a/bazel/envoy_select.bzl
+++ b/bazel/envoy_select.bzl
@@ -94,6 +94,13 @@ def envoy_select_enable_yaml(xs, repository = ""):
         "//conditions:default": xs,
     })
 
+# Selects the given values if exceptions are disabled in the current build.
+def envoy_select_disable_exceptions(xs, repository = ""):
+    return select({
+        repository + "//bazel:disable_exceptions": xs,
+        "//conditions:default": [],
+    })
+
 # Selects the given values if HTTP datagram support is enabled in the current build.
 def envoy_select_enable_http_datagrams(xs, repository = ""):
     return select({
diff --git a/mobile/library/common/engine.cc b/mobile/library/common/engine.cc
index a21c37c80ac5..125b443728fe 100644
--- a/mobile/library/common/engine.cc
+++ b/mobile/library/common/engine.cc
@@ -49,7 +49,7 @@ envoy_status_t Engine::main(std::unique_ptr&& options) {
   std::unique_ptr main_common;
   {
     Thread::LockGuard lock(mutex_);
-    try {
+    TRY_NEEDS_AUDIT {
       if (event_tracker_.track != nullptr) {
         assert_handler_registration_ =
             Assert::addDebugAssertionFailureRecordAction([this](const char* location) {
@@ -79,13 +79,9 @@ envoy_status_t Engine::main(std::unique_ptr&& options) {
       event_dispatcher_ = &server_->dispatcher();
 
       cv_.notifyAll();
-    } catch (const Envoy::NoServingException& e) {
-      PANIC(e.what());
-    } catch (const Envoy::MalformedArgvException& e) {
-      PANIC(e.what());
-    } catch (const Envoy::EnvoyException& e) {
-      PANIC(e.what());
     }
+    END_TRY
+    CATCH(const Envoy::EnvoyException& e, { PANIC(e.what()); });
 
     // Note: We're waiting longer than we might otherwise to drain to the main thread's dispatcher.
     // This is because we're not simply waiting for its availability and for it to have started, but
diff --git a/source/common/common/thread.h b/source/common/common/thread.h
index b3f2fa17652c..a1d651efe679 100644
--- a/source/common/common/thread.h
+++ b/source/common/common/thread.h
@@ -237,9 +237,34 @@ class MainThread {
 
 #define END_TRY }
 
+#ifdef ENVOY_DISABLE_EXCEPTIONS
+#define TRY_NEEDS_AUDIT {
+#else
 // TODO(chaoqinli-1123): Remove this macros after we have removed all the exceptions from data
 // plane.
-#define TRY_NEEDS_AUDIT try
+#define TRY_NEEDS_AUDIT try {
+#endif
+
+#ifdef ENVOY_DISABLE_EXCEPTIONS
+#define CATCH(ExceptionType, Handler)
+#else
+#define CATCH(Exception, Handler)                                                                  \
+  catch (Exception) {                                                                              \
+    Handler                                                                                        \
+  }
+#endif
+
+#ifdef ENVOY_DISABLE_EXCEPTIONS
+#define MULTI_CATCH(ExceptionType, Handler)
+#else
+#define MULTI_CATCH(Exception, Handler, Handler2)                                                  \
+  catch (Exception) {                                                                              \
+    Handler                                                                                        \
+  }                                                                                                \
+  catch (...) {                                                                                    \
+    Handler2                                                                                       \
+  }
+#endif
 
 // These convenience macros assert properties of the threading system, when
 // feasible. There is a platform-specific mechanism for determining whether the
@@ -277,6 +302,9 @@ class MainThread {
 
 #endif
 
+#ifdef ENVOY_DISABLE_EXCEPTIONS
+#define TRY_ASSERT_MAIN_THREAD {
+#else
 /**
  * To improve exception safety in data plane, we plan to forbid the use of raw
  * try in the core code base. This macros uses main thread assertion to make
@@ -285,6 +313,7 @@ class MainThread {
 #define TRY_ASSERT_MAIN_THREAD                                                                     \
   try {                                                                                            \
     ASSERT_IS_MAIN_OR_TEST_THREAD();
+#endif
 
 /**
  * RAII class to override thread assertions checks in the macros:
diff --git a/source/common/filter/config_discovery_impl.cc b/source/common/filter/config_discovery_impl.cc
index c08e0d146383..3f6c40cce4b4 100644
--- a/source/common/filter/config_discovery_impl.cc
+++ b/source/common/filter/config_discovery_impl.cc
@@ -220,11 +220,12 @@ void FilterConfigProviderManagerImplBase::applyLastOrDefaultConfig(
                                subscription->lastFactoryName());
       last_config_valid = true;
     }
-    END_TRY catch (const EnvoyException& e) {
+    END_TRY CATCH(const EnvoyException& e, {
       ENVOY_LOG(debug, "ECDS subscription {} is invalid in a listener context: {}.",
                 filter_config_name, e.what());
       subscription->incrementConflictCounter();
-    }
+    });
+
     if (last_config_valid) {
       provider.onConfigUpdate(*subscription->lastConfig(), subscription->lastVersionInfo(),
                               nullptr);
diff --git a/source/common/router/header_parser_utils.cc b/source/common/router/header_parser_utils.cc
index 39136cfce837..d278e04de445 100644
--- a/source/common/router/header_parser_utils.cc
+++ b/source/common/router/header_parser_utils.cc
@@ -51,10 +51,7 @@ std::string HeaderParser::translateMetadataFormat(const std::string& header_valu
       int subs = absl::StrReplaceAll({{matches[0].as_string(), new_format}}, &new_header_value);
       ASSERT(subs > 0);
     }
-    END_TRY
-    catch (Json::Exception& e) {
-      return header_value;
-    }
+    END_TRY CATCH(Json::Exception & e, { return header_value; });
   }
 
   return new_header_value;
diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc
index 423493601583..bce5ae8e16a7 100644
--- a/source/common/runtime/runtime_impl.cc
+++ b/source/common/runtime/runtime_impl.cc
@@ -690,13 +690,13 @@ SnapshotImplPtr LoaderImpl::createNewSnapshot() {
           ++disk_layers;
         }
         END_TRY
-        catch (EnvoyException& e) {
+        CATCH(EnvoyException & e, {
           // TODO(htuch): Consider latching here, rather than ignoring the
           // layer. This would be consistent with filesystem RTDS.
           ++error_layers;
           ENVOY_LOG(debug, "error loading runtime values for layer {} from disk: {}",
                     layer.DebugString(), e.what());
-        }
+        });
       }
       break;
     }
diff --git a/source/common/secret/sds_api.cc b/source/common/secret/sds_api.cc
index e20ca282f22e..effcac5a1a62 100644
--- a/source/common/secret/sds_api.cc
+++ b/source/common/secret/sds_api.cc
@@ -73,10 +73,10 @@ void SdsApi::onWatchUpdate() {
     }
   }
   END_TRY
-  catch (const EnvoyException& e) {
+  CATCH(const EnvoyException& e, {
     ENVOY_LOG_MISC(warn, fmt::format("Failed to reload certificates: {}", e.what()));
     sds_api_stats_.key_rotation_failed_.inc();
-  }
+  });
 }
 
 void SdsApi::onConfigUpdate(const std::vector& resources,
diff --git a/source/common/stats/tag_extractor_impl.cc b/source/common/stats/tag_extractor_impl.cc
index 2ac20ee1648f..75efdcf73017 100644
--- a/source/common/stats/tag_extractor_impl.cc
+++ b/source/common/stats/tag_extractor_impl.cc
@@ -21,9 +21,8 @@ namespace {
 std::regex parseStdRegex(const std::string& regex) {
   TRY_ASSERT_MAIN_THREAD { return std::regex(regex, std::regex::optimize); }
   END_TRY
-  catch (const std::regex_error& e) {
-    throw EnvoyException(fmt::format("Invalid regex '{}': {}", regex, e.what()));
-  }
+  CATCH(const std::regex_error& e,
+        { throw EnvoyException(fmt::format("Invalid regex '{}': {}", regex, e.what())); });
 }
 } // namespace
 
diff --git a/source/common/upstream/cds_api_helper.cc b/source/common/upstream/cds_api_helper.cc
index 6bd1655d4a5e..306d6c0fe1e9 100644
--- a/source/common/upstream/cds_api_helper.cc
+++ b/source/common/upstream/cds_api_helper.cc
@@ -54,10 +54,10 @@ CdsApiHelper::onConfigUpdate(const std::vector& adde
       }
     }
     END_TRY
-    catch (const EnvoyException& e) {
-      exception_msgs.push_back(fmt::format("{}: {}", cluster.name(), e.what()));
-    }
+    CATCH(const EnvoyException& e,
+          { exception_msgs.push_back(fmt::format("{}: {}", cluster.name(), e.what())); });
   }
+
   for (const auto& resource_name : removed_resources) {
     if (cm_.removeCluster(resource_name)) {
       any_applied = true;
diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc
index 30f16ac78084..08815cb4acdd 100644
--- a/source/common/upstream/health_discovery_service.cc
+++ b/source/common/upstream/health_discovery_service.cc
@@ -289,14 +289,14 @@ void HdsDelegate::onReceiveMessage(
                           server_context_.messageValidationContext().dynamicValidationVisitor());
   }
   END_TRY
-  catch (const ProtoValidationException& ex) {
+  CATCH(const ProtoValidationException& ex, {
     // Increment error count
     stats_.errors_.inc();
     ENVOY_LOG(warn, "Unable to validate health check specifier: {}", ex.what());
 
     // Do not continue processing message
     return;
-  }
+  });
 
   // Set response
   auto server_response_ms = PROTOBUF_GET_MS_OR_DEFAULT(*message, interval, 1000);
diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc
index 0a36b908f407..718f2f68ec30 100644
--- a/source/common/upstream/upstream_impl.cc
+++ b/source/common/upstream/upstream_impl.cc
@@ -1625,7 +1625,7 @@ const Network::Address::InstanceConstSharedPtr
 ClusterImplBase::resolveProtoAddress(const envoy::config::core::v3::Address& address) {
   TRY_ASSERT_MAIN_THREAD { return Network::Address::resolveProtoAddress(address); }
   END_TRY
-  catch (EnvoyException& e) {
+  CATCH(EnvoyException & e, {
     if (info_->type() == envoy::config::cluster::v3::Cluster::STATIC ||
         info_->type() == envoy::config::cluster::v3::Cluster::EDS) {
       throw EnvoyException(fmt::format("{}. Consider setting resolver_name or setting cluster type "
@@ -1633,7 +1633,7 @@ ClusterImplBase::resolveProtoAddress(const envoy::config::core::v3::Address& add
                                        e.what()));
     }
     throw e;
-  }
+  });
 }
 
 void ClusterImplBase::validateEndpointsForZoneAwareRouting(
diff --git a/source/exe/stripped_main_base.cc b/source/exe/stripped_main_base.cc
index 9d532a993b90..878e72a75735 100644
--- a/source/exe/stripped_main_base.cc
+++ b/source/exe/stripped_main_base.cc
@@ -129,10 +129,10 @@ void StrippedMainBase::configureHotRestarter(Random::RandomGenerator& random_gen
                                                                options_.socketMode());
         }
         END_TRY
-        catch (Server::HotRestartDomainSocketInUseException& ex) {
+        CATCH(Server::HotRestartDomainSocketInUseException & ex, {
           // No luck, try again.
           ENVOY_LOG_MISC(debug, "dynamic base id: {}", ex.what());
-        }
+        });
       }
 
       if (restarter == nullptr) {
diff --git a/source/extensions/grpc_credentials/file_based_metadata/config.cc b/source/extensions/grpc_credentials/file_based_metadata/config.cc
index aebba3b17150..1fa300a2f711 100644
--- a/source/extensions/grpc_credentials/file_based_metadata/config.cc
+++ b/source/extensions/grpc_credentials/file_based_metadata/config.cc
@@ -75,8 +75,9 @@ FileBasedMetadataAuthenticator::GetMetadata(grpc::string_ref, grpc::string_ref,
     std::string header_value = Envoy::Config::DataSource::read(config_.secret_data(), true, api_);
     metadata->insert(std::make_pair(header_key, header_prefix + header_value));
   }
+  END_TRY
   catch (const EnvoyException& e) {
-    return grpc::Status(grpc::StatusCode::NOT_FOUND, e.what());
+    return {grpc::StatusCode::NOT_FOUND, e.what()};
   }
   return grpc::Status::OK;
 }
diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.cc b/source/extensions/network/dns_resolver/cares/dns_impl.cc
index 1c4bd6fa6a51..12cf91e9c33f 100644
--- a/source/extensions/network/dns_resolver/cares/dns_impl.cc
+++ b/source/extensions/network/dns_resolver/cares/dns_impl.cc
@@ -287,6 +287,7 @@ void DnsResolverImpl::PendingResolution::finishResolve() {
     TRY_NEEDS_AUDIT {
       callback_(pending_response_.status_, std::move(pending_response_.address_list_));
     }
+    END_TRY
     catch (const EnvoyException& e) {
       ENVOY_LOG(critical, "EnvoyException in c-ares callback: {}", e.what());
       dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); });
diff --git a/source/server/options_impl.cc b/source/server/options_impl.cc
index 6345c789e897..81d7490c095e 100644
--- a/source/server/options_impl.cc
+++ b/source/server/options_impl.cc
@@ -161,25 +161,24 @@ OptionsImpl::OptionsImpl(std::vector args,
       false, "string", cmd);
 
   cmd.setExceptionHandling(false);
-  TRY_ASSERT_MAIN_THREAD {
-    cmd.parse(args);
-    count_ = cmd.getArgList().size();
-  }
-  END_TRY
-  catch (TCLAP::ArgException& e) {
+
+  std::function failure_function = [&](TCLAP::ArgException& e) {
     TRY_ASSERT_MAIN_THREAD { cmd.getOutput()->failure(cmd, e); }
     END_TRY
-    catch (const TCLAP::ExitException&) {
+    CATCH(const TCLAP::ExitException&, {
       // failure() has already written an informative message to stderr, so all that's left to do
       // is throw our own exception with the original message.
       throw MalformedArgvException(e.what());
-    }
-  }
-  catch (const TCLAP::ExitException& e) {
-    // parse() throws an ExitException with status 0 after printing the output for --help and
-    // --version.
-    throw NoServingException();
+    });
+  };
+
+  TRY_ASSERT_MAIN_THREAD {
+    cmd.parse(args);
+    count_ = cmd.getArgList().size();
   }
+  END_TRY
+  MULTI_CATCH(
+      TCLAP::ArgException & e, { failure_function(e); }, { throw NoServingException(); });
 
   hot_restart_disabled_ = disable_hot_restart.getValue();
   mutex_tracing_enabled_ = enable_mutex_tracing.getValue();
diff --git a/source/server/server.cc b/source/server/server.cc
index 8ed78eb8b139..91c72e529197 100644
--- a/source/server/server.cc
+++ b/source/server/server.cc
@@ -105,41 +105,41 @@ InstanceImpl::InstanceImpl(
       router_context_(store.symbolTable()), process_context_(std::move(process_context)),
       hooks_(hooks), quic_stat_names_(store.symbolTable()), server_contexts_(*this),
       enable_reuse_port_default_(true), stats_flush_in_progress_(false) {
+  std::function set_up_logger = [&] {
+    TRY_ASSERT_MAIN_THREAD {
+      file_logger_ = std::make_unique(
+          options.logPath(), access_log_manager_, Logger::Registry::getSink());
+    }
+    END_TRY
+    CATCH(const EnvoyException& e, {
+      throw EnvoyException(
+          fmt::format("Failed to open log-file '{}'. e.what(): {}", options.logPath(), e.what()));
+    });
+  };
+
   TRY_ASSERT_MAIN_THREAD {
     if (!options.logPath().empty()) {
-      TRY_ASSERT_MAIN_THREAD {
-        file_logger_ = std::make_unique(
-            options.logPath(), access_log_manager_, Logger::Registry::getSink());
-      }
-      END_TRY
-      catch (const EnvoyException& e) {
-        throw EnvoyException(
-            fmt::format("Failed to open log-file '{}'. e.what(): {}", options.logPath(), e.what()));
-      }
+      set_up_logger();
     }
-
     restarter_.initialize(*dispatcher_, *this);
     drain_manager_ = component_factory.createDrainManager(*this);
     initialize(std::move(local_address), component_factory);
   }
   END_TRY
-  catch (const EnvoyException& e) {
-    ENVOY_LOG(critical, "error initializing config '{} {} {}': {}",
-              options.configProto().DebugString(), options.configYaml(), options.configPath(),
-              e.what());
-    terminate();
-    throw;
-  }
-  catch (const std::exception& e) {
-    ENVOY_LOG(critical, "error initializing due to unexpected exception: {}", e.what());
-    terminate();
-    throw;
-  }
-  catch (...) {
-    ENVOY_LOG(critical, "error initializing due to unknown exception");
-    terminate();
-    throw;
-  }
+  MULTI_CATCH(
+      const EnvoyException& e,
+      {
+        ENVOY_LOG(critical, "error initializing config '{} {} {}': {}",
+                  options.configProto().DebugString(), options.configYaml(), options.configPath(),
+                  e.what());
+        terminate();
+        throw;
+      },
+      {
+        ENVOY_LOG(critical, "error initializing due to unknown exception");
+        terminate();
+        throw;
+      });
 }
 
 InstanceImpl::~InstanceImpl() {

From a34e994f2720c2516d59b978f481643ef372d9b2 Mon Sep 17 00:00:00 2001
From: yanavlasov 
Date: Wed, 7 Jun 2023 10:05:52 -0400
Subject: [PATCH 196/228] UHV: Enable oghttp2 and UHV in HTTP/2 flood test
 (#27543)

Enable oghttp2 and UHV in HTTP/2 flood test

Signed-off-by: Yan Avlasov 
---
 source/common/http/codec_client.cc            |  1 -
 .../http2_flood_integration_test.cc           | 38 +++++++++++++------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/source/common/http/codec_client.cc b/source/common/http/codec_client.cc
index 51ac7cffa591..61cad323553c 100644
--- a/source/common/http/codec_client.cc
+++ b/source/common/http/codec_client.cc
@@ -247,7 +247,6 @@ void CodecClient::ActiveRequest::decodeHeaders(ResponseHeaderMapPtr&& headers, b
                 .http3Options()
                 .override_stream_error_on_invalid_http_message()
                 .value())) {
-        parent_.host_->cluster().trafficStats()->upstream_cx_protocol_error_.inc();
         parent_.protocol_error_ = true;
         parent_.close();
       } else {
diff --git a/test/integration/http2_flood_integration_test.cc b/test/integration/http2_flood_integration_test.cc
index 6a08c69b12a8..6f508bf35bdf 100644
--- a/test/integration/http2_flood_integration_test.cc
+++ b/test/integration/http2_flood_integration_test.cc
@@ -31,17 +31,18 @@ namespace {
 const uint32_t ControlFrameFloodLimit = 100;
 const uint32_t AllFrameFloodLimit = 1000;
 
-bool deferredProcessing(std::tuple params) {
+bool deferredProcessing(std::tuple params) {
   return std::get<2>(params);
 }
 
 } // namespace
 
 std::string testParamsToString(
-    const ::testing::TestParamInfo> params) {
-  const bool http2_new_codec_wrapper = std::get<1>(params.param);
+    const ::testing::TestParamInfo>
+        params) {
+  const Http2Impl http2_codec_impl = std::get<1>(params.param);
   return absl::StrCat(TestUtility::ipVersionToString(std::get<0>(params.param)),
-                      http2_new_codec_wrapper ? "WrappedHttp2" : "BareHttp2",
+                      http2_codec_impl == Http2Impl::Oghttp2 ? "Oghttp2" : "Nghttp2",
                       deferredProcessing(params.param) ? "WithDeferredProcessing"
                                                        : "NoDeferredProcessing");
 }
@@ -53,7 +54,7 @@ std::string testParamsToString(
 // Http2FrameIntegrationTest destructor completes.
 class Http2FloodMitigationTest
     : public SocketInterfaceSwap,
-      public testing::TestWithParam>,
+      public testing::TestWithParam>,
       public Http2RawFrameIntegrationTest {
 public:
   Http2FloodMitigationTest()
@@ -67,9 +68,7 @@ class Http2FloodMitigationTest
         [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager&
                hcm) { hcm.mutable_delayed_close_timeout()->set_seconds(1); });
     config_helper_.addConfigModifier(configureProxyStatus());
-    const bool enable_new_wrapper = std::get<1>(GetParam());
-    config_helper_.addRuntimeOverride("envoy.reloadable_features.http2_new_codec_wrapper",
-                                      enable_new_wrapper ? "true" : "false");
+    setupHttp2ImplOverrides(std::get<1>(GetParam()));
     config_helper_.addRuntimeOverride(Runtime::defer_processing_backedup_streams,
                                       deferredProcessing(GetParam()) ? "true" : "false");
   }
@@ -92,7 +91,8 @@ class Http2FloodMitigationTest
 
 INSTANTIATE_TEST_SUITE_P(
     IpVersions, Http2FloodMitigationTest,
-    testing::Combine(testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), ::testing::Bool(),
+    testing::Combine(testing::ValuesIn(TestEnvironment::getIpVersionsForTest()),
+                     testing::ValuesIn({Http2Impl::Nghttp2, Http2Impl::Oghttp2}),
                      ::testing::Bool()),
     testParamsToString);
 
@@ -680,6 +680,14 @@ TEST_P(Http2FloodMitigationTest, WindowUpdateOnLowWatermarkFlood) {
 
 // Verify that the server can detect flood of RST_STREAM frames.
 TEST_P(Http2FloodMitigationTest, RST_STREAM) {
+#ifdef ENVOY_ENABLE_UHV
+  // TODO(#27541): the invalid frame that used to cause Envoy to send only RST_STREAM now causes
+  // Envoy to also send 400 in UHV mode (it is allowed by RFC). The test needs to be fixed to make
+  // server only send RST_STREAM.
+  if (std::get<1>(GetParam()) == Http2Impl::Oghttp2) {
+    return;
+  }
+#endif
   // Use invalid HTTP headers to trigger sending RST_STREAM frames.
   config_helper_.addConfigModifier(
       [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager&
@@ -1120,13 +1128,21 @@ TEST_P(Http2FloodMitigationTest, ZerolenHeader) {
   EXPECT_EQ(1, test_server_->counter("http2.rx_messaging_error")->value());
   EXPECT_EQ(1,
             test_server_->counter("http.config_test.downstream_cx_delayed_close_timeout")->value());
-  EXPECT_THAT(waitForAccessLog(access_log_name_), HasSubstr("http2.invalid.header.field"));
+  EXPECT_THAT(waitForAccessLog(access_log_name_), HasSubstr("header"));
   // expect a downstream protocol error.
   EXPECT_THAT(waitForAccessLog(access_log_name_), HasSubstr("DPE"));
 }
 
 // Verify that only the offending stream is terminated upon receiving invalid HEADERS frame.
 TEST_P(Http2FloodMitigationTest, ZerolenHeaderAllowed) {
+#ifdef ENVOY_ENABLE_UHV
+  // TODO(#27541): the invalid frame that used to cause Envoy to send only RST_STREAM now causes
+  // Envoy to also send 400 in UHV mode (it is allowed by RFC). The test needs to be fixed to make
+  // server only send RST_STREAM.
+  if (std::get<1>(GetParam()) == Http2Impl::Oghttp2) {
+    return;
+  }
+#endif
   useAccessLog("%RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS%");
   config_helper_.addConfigModifier(
       [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager&
@@ -1161,7 +1177,7 @@ TEST_P(Http2FloodMitigationTest, ZerolenHeaderAllowed) {
   EXPECT_EQ(0,
             test_server_->counter("http.config_test.downstream_cx_delayed_close_timeout")->value());
   // expect Downstream Protocol Error
-  EXPECT_THAT(waitForAccessLog(access_log_name_, 0, true), HasSubstr("http2.invalid.header.field"));
+  EXPECT_THAT(waitForAccessLog(access_log_name_, 0, true), HasSubstr("header"));
   EXPECT_THAT(waitForAccessLog(access_log_name_, 0, true), HasSubstr("DPE"));
 }
 

From ad13bbb65d30d6c342dc842de51347a71e512951 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 7 Jun 2023 07:26:56 -0700
Subject: [PATCH 197/228] build(deps): bump elasticsearch from 8.7.1 to 8.8.0
 in /examples/skywalking (#27838)

build(deps): bump elasticsearch in /examples/skywalking

Bumps elasticsearch from 8.7.1 to 8.8.0.

---
updated-dependencies:
- dependency-name: elasticsearch
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 examples/skywalking/Dockerfile-elasticsearch | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/skywalking/Dockerfile-elasticsearch b/examples/skywalking/Dockerfile-elasticsearch
index faa8bcdab143..b721cc086bfa 100644
--- a/examples/skywalking/Dockerfile-elasticsearch
+++ b/examples/skywalking/Dockerfile-elasticsearch
@@ -1 +1 @@
-FROM elasticsearch:8.7.1@sha256:160814e5972521291420c29edf4c0348b8591ac9235156f0dbf34befcf362825
+FROM elasticsearch:8.8.0@sha256:5c28849be5e91610761fcd4a49c2561dfae72be9ac0a3e7b5c42c9576aa9157b

From 14ef459c3691bdf722b1434a0e955ff1986bada1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 7 Jun 2023 07:28:23 -0700
Subject: [PATCH 198/228] build(deps): bump golang from 1.20.4-bullseye to
 1.20.5-bullseye in /examples/shared/golang (#27837)

build(deps): bump golang in /examples/shared/golang

Bumps golang from 1.20.4-bullseye to 1.20.5-bullseye.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 examples/shared/golang/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/shared/golang/Dockerfile b/examples/shared/golang/Dockerfile
index 17bff24cf5a4..3e3ac40744eb 100644
--- a/examples/shared/golang/Dockerfile
+++ b/examples/shared/golang/Dockerfile
@@ -3,7 +3,7 @@ RUN rm -f /etc/apt/apt.conf.d/docker-clean \
     && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache
 
 
-FROM golang:1.20.4-bullseye@sha256:918857f4064db0fff49799ce5e7c4d43e394f452111cd89cca9af539c18a76a8 as golang-base
+FROM golang:1.20.5-bullseye@sha256:419bc8954c0e08c539830c8669ccd116a063303481c748fabd09d8fd6d4e2c5f as golang-base
 
 
 FROM golang-base as golang-control-plane-builder

From 29780678dba79df1088f89ac71b50b97ab2eac35 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 7 Jun 2023 07:30:59 -0700
Subject: [PATCH 199/228] build(deps): bump openpolicyagent/opa from
 0.53.0-istio to 0.53.1-istio in /examples/ext_authz (#27835)

build(deps): bump openpolicyagent/opa in /examples/ext_authz

Bumps openpolicyagent/opa from 0.53.0-istio to 0.53.1-istio.

---
updated-dependencies:
- dependency-name: openpolicyagent/opa
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 examples/ext_authz/Dockerfile-opa | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/ext_authz/Dockerfile-opa b/examples/ext_authz/Dockerfile-opa
index 70847d7d5ae2..f3ed85f6e594 100644
--- a/examples/ext_authz/Dockerfile-opa
+++ b/examples/ext_authz/Dockerfile-opa
@@ -1 +1 @@
-FROM openpolicyagent/opa:0.53.0-istio@sha256:dcf28d23b3d1919b6314ef34342687c558cec64fe4f93fa484e8c8e82824d56d
+FROM openpolicyagent/opa:0.53.1-istio@sha256:b4821d33fdbca4fe3d2ff85e3f4a18d292f2fb32fe7db995b9239d7242702bab

From 26ddee23f650f1d58bdf0327857ec3a31c54f004 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 7 Jun 2023 07:38:20 -0700
Subject: [PATCH 200/228] build(deps): bump otel/opentelemetry-collector from
 `32edac6` to `324e2c7` in /examples/opentelemetry (#27836)

build(deps): bump otel/opentelemetry-collector

Bumps otel/opentelemetry-collector from `32edac6` to `324e2c7`.

---
updated-dependencies:
- dependency-name: otel/opentelemetry-collector
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 examples/opentelemetry/Dockerfile-opentelemetry | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/opentelemetry/Dockerfile-opentelemetry b/examples/opentelemetry/Dockerfile-opentelemetry
index ad03819c59e4..38a00b8e466d 100644
--- a/examples/opentelemetry/Dockerfile-opentelemetry
+++ b/examples/opentelemetry/Dockerfile-opentelemetry
@@ -1,7 +1,7 @@
 FROM alpine:3.18@sha256:02bb6f428431fbc2809c5d1b41eab5a68350194fb508869a33cb1af4444c9b11 as otelc_curl
 RUN apk --update add curl
 
-FROM otel/opentelemetry-collector:latest@sha256:32edac6fe9479c4a33a60be226af0a3ee9f69a5b79d935835b37bf9b25e4b5ce
+FROM otel/opentelemetry-collector:latest@sha256:324e2c7bdd1ecd58c1a1347737174371b4917d71a05cc4403ce3fb83bcddf836
 
 COPY --from=otelc_curl / /
 

From 62d3974f5a9dd1291b9f9d96990e3e658c0a8240 Mon Sep 17 00:00:00 2001
From: Tony Han 
Date: Wed, 7 Jun 2023 22:59:11 +0800
Subject: [PATCH 201/228] docs: fix yaml syntax in scoped route example
 (#27805)

Signed-off-by: Bing Han 
---
 api/envoy/api/v2/scoped_route.proto          | 2 +-
 api/envoy/config/route/v3/scoped_route.proto | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/api/envoy/api/v2/scoped_route.proto b/api/envoy/api/v2/scoped_route.proto
index f3902d9d9e7e..99a39aedac5c 100644
--- a/api/envoy/api/v2/scoped_route.proto
+++ b/api/envoy/api/v2/scoped_route.proto
@@ -39,7 +39,7 @@ option (udpa.annotations.file_status).package_version_status = FROZEN;
 //       fragments:
 //         - header_value_extractor:
 //             name: X-Route-Selector
-//             element_separator: ,
+//             element_separator: ","
 //             element:
 //               separator: =
 //               key: vip
diff --git a/api/envoy/config/route/v3/scoped_route.proto b/api/envoy/config/route/v3/scoped_route.proto
index 27bcd617ae16..ff4cc689c898 100644
--- a/api/envoy/config/route/v3/scoped_route.proto
+++ b/api/envoy/config/route/v3/scoped_route.proto
@@ -44,7 +44,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
 //       fragments:
 //         - header_value_extractor:
 //             name: X-Route-Selector
-//             element_separator: ,
+//             element_separator: ","
 //             element:
 //               separator: =
 //               key: vip

From 009d73924ca66c1ff9224c61ac403d4fe6496dad Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Wed, 7 Jun 2023 13:00:52 -0400
Subject: [PATCH 202/228] coverage: fixing a coverage flake by inlining an
 error condition only run in debug builds (#27845)

Signed-off-by: Alyssa Wilk 
---
 source/common/common/posix/thread_impl.cc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/source/common/common/posix/thread_impl.cc b/source/common/common/posix/thread_impl.cc
index fae09194d8cc..5d78dd24a56e 100644
--- a/source/common/common/posix/thread_impl.cc
+++ b/source/common/common/posix/thread_impl.cc
@@ -101,12 +101,8 @@ class ThreadImplPosix : public Thread {
     // Verify that the name got written into the thread as expected.
     char buf[PTHREAD_MAX_THREADNAME_LEN_INCLUDING_NULL_BYTE];
     const int get_name_rc = pthread_getname_np(thread_handle_, buf, sizeof(buf));
-    if (get_name_rc != 0) {
-      ENVOY_LOG_MISC(trace, "Error {} getting name", get_name_rc);
-      return false;
-    }
     name = buf;
-    return true;
+    return get_name_rc == 0;
   }
 #endif
 

From 548d4771d8737fa18b568252d0e3ff833ed3bf64 Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Wed, 7 Jun 2023 14:00:24 -0400
Subject: [PATCH 203/228] http: moving exceptions out of
 http_server_properties_cache_manager_impl (#27829)

Signed-off-by: Alyssa Wilk 
---
 .../http_server_properties_cache_manager_impl.cc   |  8 +-------
 .../http/alternate_protocols_cache/filter.cc       |  1 +
 source/extensions/upstreams/http/config.cc         | 14 +++++++++++---
 .../http_server_properties_cache_manager_test.cc   | 14 +++-----------
 test/extensions/upstreams/http/config_test.cc      | 12 ++++++++++++
 tools/code_format/config.yaml                      |  1 -
 6 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/source/common/http/http_server_properties_cache_manager_impl.cc b/source/common/http/http_server_properties_cache_manager_impl.cc
index e05694c30e04..307e8991eb55 100644
--- a/source/common/http/http_server_properties_cache_manager_impl.cc
+++ b/source/common/http/http_server_properties_cache_manager_impl.cc
@@ -24,16 +24,10 @@ HttpServerPropertiesCacheManagerImpl::HttpServerPropertiesCacheManagerImpl(
 HttpServerPropertiesCacheSharedPtr HttpServerPropertiesCacheManagerImpl::getCache(
     const envoy::config::core::v3::AlternateProtocolsCacheOptions& options,
     Event::Dispatcher& dispatcher) {
-  if (options.has_key_value_store_config() && data_.concurrency_ != 1) {
-    throw EnvoyException(
-        fmt::format("options has key value store but Envoy has concurrency = {} : {}",
-                    data_.concurrency_, options.DebugString()));
-  }
-
   const auto& existing_cache = (*slot_).caches_.find(options.name());
   if (existing_cache != (*slot_).caches_.end()) {
     if (!Protobuf::util::MessageDifferencer::Equivalent(options, existing_cache->second.options_)) {
-      throw EnvoyException(fmt::format(
+      IS_ENVOY_BUG(fmt::format(
           "options specified alternate protocols cache '{}' with different settings"
           " first '{}' second '{}'",
           options.name(), existing_cache->second.options_.DebugString(), options.DebugString()));
diff --git a/source/extensions/filters/http/alternate_protocols_cache/filter.cc b/source/extensions/filters/http/alternate_protocols_cache/filter.cc
index c3130a7ce175..5982ceceb3e6 100644
--- a/source/extensions/filters/http/alternate_protocols_cache/filter.cc
+++ b/source/extensions/filters/http/alternate_protocols_cache/filter.cc
@@ -38,6 +38,7 @@ Filter::Filter(const FilterConfigSharedPtr& config, Event::Dispatcher& dispatche
     : cache_(config->getAlternateProtocolCache(dispatcher)), time_source_(config->timeSource()) {}
 
 Http::FilterHeadersStatus Filter::encodeHeaders(Http::ResponseHeaderMap& headers, bool) {
+
   if (!cache_) {
     return Http::FilterHeadersStatus::Continue;
   }
diff --git a/source/extensions/upstreams/http/config.cc b/source/extensions/upstreams/http/config.cc
index 39ee82441ef4..41feefaaf5d9 100644
--- a/source/extensions/upstreams/http/config.cc
+++ b/source/extensions/upstreams/http/config.cc
@@ -84,13 +84,21 @@ bool useHttp3(const envoy::extensions::upstreams::http::v3::HttpProtocolOptions&
 
 absl::optional
 getAlternateProtocolsCacheOptions(
-    const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options) {
+    const envoy::extensions::upstreams::http::v3::HttpProtocolOptions& options,
+    Server::Configuration::ServerFactoryContext& server_context) {
   if (options.has_auto_config() && options.auto_config().has_http3_protocol_options()) {
     if (!options.auto_config().has_alternate_protocols_cache_options()) {
       throw EnvoyException(fmt::format("alternate protocols cache must be configured when HTTP/3 "
                                        "is enabled with auto_config"));
     }
-    return options.auto_config().alternate_protocols_cache_options();
+    auto cache_options = options.auto_config().alternate_protocols_cache_options();
+    if (cache_options.has_key_value_store_config() && server_context.options().concurrency() != 1) {
+      throw EnvoyException(
+          fmt::format("options has key value store but Envoy has concurrency = {} : {}",
+                      server_context.options().concurrency(), cache_options.DebugString()));
+    }
+
+    return cache_options;
   }
   return absl::nullopt;
 }
@@ -178,7 +186,7 @@ ProtocolOptionsConfigImpl::ProtocolOptionsConfigImpl(
                     options.upstream_http_protocol_options())
               : absl::nullopt),
       http_filters_(options.http_filters()),
-      alternate_protocol_cache_options_(getAlternateProtocolsCacheOptions(options)),
+      alternate_protocol_cache_options_(getAlternateProtocolsCacheOptions(options, server_context)),
       header_validator_factory_(createHeaderValidatorFactory(options, server_context)),
       use_downstream_protocol_(options.has_use_downstream_protocol_config()),
       use_http2_(useHttp2(options)), use_http3_(useHttp3(options)),
diff --git a/test/common/http/http_server_properties_cache_manager_test.cc b/test/common/http/http_server_properties_cache_manager_test.cc
index dd4f93dae443..5f6ccede15de 100644
--- a/test/common/http/http_server_properties_cache_manager_test.cc
+++ b/test/common/http/http_server_properties_cache_manager_test.cc
@@ -100,14 +100,6 @@ TEST_F(HttpServerPropertiesCacheManagerTest, GetCacheWithCanonicalEntry) {
   EXPECT_TRUE(cache->findAlternatives(origin).has_value());
 }
 
-TEST_F(HttpServerPropertiesCacheManagerTest, GetCacheWithFlushingAndConcurrency) {
-  EXPECT_CALL(context_.options_, concurrency()).WillOnce(Return(5));
-  options1_.mutable_key_value_store_config();
-  initialize();
-  EXPECT_THROW_WITH_REGEX(manager_->getCache(options1_, dispatcher_), EnvoyException,
-                          "options has key value store but Envoy has concurrency = 5");
-}
-
 TEST_F(HttpServerPropertiesCacheManagerTest, GetCacheForDifferentOptions) {
   initialize();
   HttpServerPropertiesCacheSharedPtr cache1 = manager_->getCache(options1_, dispatcher_);
@@ -120,9 +112,9 @@ TEST_F(HttpServerPropertiesCacheManagerTest, GetCacheForConflictingOptions) {
   initialize();
   HttpServerPropertiesCacheSharedPtr cache1 = manager_->getCache(options1_, dispatcher_);
   options2_.set_name(options1_.name());
-  EXPECT_THROW_WITH_REGEX(
-      manager_->getCache(options2_, dispatcher_), EnvoyException,
-      "options specified alternate protocols cache 'name1' with different settings.*");
+  EXPECT_ENVOY_BUG(manager_->getCache(options2_, dispatcher_),
+                   "options specified alternate protocols cache 'name1' with different settings "
+                   "first 'name: \"name1\"");
 }
 
 } // namespace
diff --git a/test/extensions/upstreams/http/config_test.cc b/test/extensions/upstreams/http/config_test.cc
index 60f5ae3b8a32..7b54807970be 100644
--- a/test/extensions/upstreams/http/config_test.cc
+++ b/test/extensions/upstreams/http/config_test.cc
@@ -84,6 +84,18 @@ TEST_F(ConfigTest, AutoHttp3NoCache) {
       "alternate protocols cache must be configured when HTTP/3 is enabled with auto_config");
 }
 
+TEST_F(ConfigTest, KvStoreConcurrencyFail) {
+  options_.mutable_auto_config();
+  options_.mutable_auto_config()->mutable_http3_protocol_options();
+  options_.mutable_auto_config()
+      ->mutable_alternate_protocols_cache_options()
+      ->mutable_key_value_store_config();
+  server_context_.options_.concurrency_ = 2;
+  EXPECT_THROW_WITH_MESSAGE(
+      ProtocolOptionsConfigImpl config(options_, server_context_), EnvoyException,
+      "options has key value store but Envoy has concurrency = 2 : key_value_store_config {\n}\n");
+}
+
 namespace {
 
 class TestHeaderValidatorFactoryConfig : public ::Envoy::Http::HeaderValidatorFactoryConfig {
diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml
index c189b2c994c1..5129d452f7d8 100644
--- a/tools/code_format/config.yaml
+++ b/tools/code_format/config.yaml
@@ -130,7 +130,6 @@ paths:
     - source/common/http/filter_chain_helper.h
     - source/common/http/conn_manager_utility.cc
     - source/common/http/match_delegate/config.cc
-    - source/common/http/http_server_properties_cache_manager_impl.cc
     - source/common/protobuf/yaml_utility.cc
     - source/common/protobuf/visitor_helper.h
     - source/common/protobuf/visitor.cc

From d1cc005b75e36f15d3c5af29ccaf2bf792550091 Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Wed, 7 Jun 2023 15:32:48 -0400
Subject: [PATCH 204/228] Runtime: correctly outputting runtime on admin
 console (#27739)

Risk Level: low
Testing: new tests
Docs Changes: n/a
Release Notes: n/a
Fixes #27376

Signed-off-by: Alyssa Wilk 
---
 source/common/runtime/runtime_impl.cc         | 18 +++--
 .../circuit_breakers_integration_test.cc      | 71 ++++++++++++++++++-
 2 files changed, 83 insertions(+), 6 deletions(-)

diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc
index bce5ae8e16a7..20704683ac13 100644
--- a/source/common/runtime/runtime_impl.cc
+++ b/source/common/runtime/runtime_impl.cc
@@ -323,26 +323,35 @@ void parseEntryBooleanValue(Envoy::Runtime::Snapshot::Entry& entry) {
 SnapshotImpl::Entry SnapshotImpl::createEntry(const ProtobufWkt::Value& value,
                                               absl::string_view raw_string) {
   Entry entry;
+  entry.raw_string_value_ = value.string_value();
+  if (!raw_string.empty()) {
+    entry.raw_string_value_ = raw_string;
+  }
   switch (value.kind_case()) {
   case ProtobufWkt::Value::kNumberValue:
     setNumberValue(entry, value.number_value());
+    if (entry.raw_string_value_.empty()) {
+      entry.raw_string_value_ = absl::StrCat(value.number_value());
+    }
     break;
   case ProtobufWkt::Value::kBoolValue:
     entry.bool_value_ = value.bool_value();
+    if (entry.raw_string_value_.empty()) {
+      entry.raw_string_value_ = absl::StrCat(value.bool_value());
+    }
     break;
   case ProtobufWkt::Value::kStructValue:
+    if (entry.raw_string_value_.empty()) {
+      entry.raw_string_value_ = value.struct_value().DebugString();
+    }
     parseFractionValue(entry, value.struct_value());
     break;
   case ProtobufWkt::Value::kStringValue:
-    entry.raw_string_value_ = value.string_value();
     parseEntryDoubleValue(entry);
     // TODO(alyssawilk) after this PR lands and sticks, ENVOY_BUG these
     // functions and see if we can remove the special casing.
     parseEntryBooleanValue(entry);
     parseEntryFractionalPercentValue(entry);
-    if (!raw_string.empty()) {
-      entry.raw_string_value_ = raw_string;
-    }
   default:
     break;
   }
@@ -409,6 +418,7 @@ void DiskLayer::walkDirectory(const std::string& path, const std::string& prefix
       // Read the file and remove any comments. A comment is a line starting with a '#' character.
       // Comments are useful for placeholder files with no value.
       const std::string text_file{api.fileSystem().fileReadToEnd(full_path)};
+
       const auto lines = StringUtil::splitToken(text_file, "\n");
       for (const auto& line : lines) {
         if (!line.empty() && line.front() == '#') {
diff --git a/test/integration/circuit_breakers_integration_test.cc b/test/integration/circuit_breakers_integration_test.cc
index b0a7b5409d39..6d38b1077693 100644
--- a/test/integration/circuit_breakers_integration_test.cc
+++ b/test/integration/circuit_breakers_integration_test.cc
@@ -121,12 +121,79 @@ TEST_P(CircuitBreakersIntegrationTest, CircuitBreakerRuntime) {
   const std::string expected_json1 = R"EOF(
   "circuit_breakers.cluster_0.default.max_retries": {
 )EOF";
-  EXPECT_TRUE(absl::StrContains(response->body(), expected_json1));
+  EXPECT_TRUE(absl::StrContains(response->body(), expected_json1)) << response->body();
 
   const std::string expected_json2 = R"EOF("final_value": "1024")EOF";
-  EXPECT_TRUE(absl::StrContains(response->body(), expected_json2));
+  EXPECT_TRUE(absl::StrContains(response->body(), expected_json2)) << response->body();
 #endif
 }
 
+TEST_P(CircuitBreakersIntegrationTest, CircuitBreakerRuntimeProto) {
+  config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) {
+    auto* static_resources = bootstrap.mutable_static_resources();
+    auto* cluster = static_resources->mutable_clusters(0);
+
+    auto* outlier_detection = cluster->mutable_outlier_detection();
+    outlier_detection->mutable_consecutive_gateway_failure()->set_value(1);
+    outlier_detection->mutable_consecutive_5xx()->set_value(1);
+    outlier_detection->mutable_consecutive_local_origin_failure()->set_value(1);
+
+    outlier_detection->mutable_enforcing_consecutive_gateway_failure()->set_value(100);
+    outlier_detection->mutable_enforcing_consecutive_5xx()->set_value(100);
+    outlier_detection->mutable_enforcing_consecutive_local_origin_failure()->set_value(100);
+
+    outlier_detection->set_split_external_local_origin_errors(true);
+
+    outlier_detection->mutable_max_ejection_percent()->set_value(100);
+    outlier_detection->mutable_interval()->set_nanos(1);
+    outlier_detection->mutable_base_ejection_time()->set_seconds(3600);
+    outlier_detection->mutable_max_ejection_time()->set_seconds(3600);
+
+    auto* layer = bootstrap.mutable_layered_runtime()->add_layers();
+    layer->set_name("enable layer");
+    ProtobufWkt::Struct& runtime = *layer->mutable_static_layer();
+
+    (*runtime.mutable_fields())["circuit_breakers.cluster_0.default.max_requests"].set_number_value(
+        0);
+    (*runtime.mutable_fields())["circuit_breakers.cluster_0.default.max_retries"].set_number_value(
+        1024);
+  });
+
+  initialize();
+
+  codec_client_ = makeHttpConnection(lookupPort("http"));
+
+  auto response = codec_client_->makeRequestWithBody(default_request_headers_, 1024);
+
+  test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_active", 0);
+  test_server_->waitForGaugeEq("cluster.cluster_0.upstream_rq_pending_active", 0);
+
+  ASSERT_TRUE(response->waitForEndStream());
+
+  EXPECT_EQ("503", response->headers().getStatusValue());
+  test_server_->waitForCounterGe("cluster.cluster_0.upstream_rq_503", 1);
+
+  EXPECT_EQ(test_server_->counter("cluster.cluster_0.upstream_rq_pending_overflow")->value(), 1);
+
+  EXPECT_EQ(test_server_->counter("cluster.cluster_0.outlier_detection.ejections_enforced_total")
+                ->value(),
+            0);
+#ifdef ENVOY_ADMIN_FUNCTIONALITY
+  auto codec_client2 = makeHttpConnection(lookupPort("admin"));
+  default_request_headers_.setPath("/runtime");
+  response = codec_client2->makeHeaderOnlyRequest(default_request_headers_);
+  ASSERT_TRUE(response->waitForEndStream());
+  EXPECT_EQ("200", response->headers().getStatusValue());
+  codec_client2->close();
+
+  const std::string expected_json1 = R"EOF(
+  "circuit_breakers.cluster_0.default.max_retries": {
+)EOF";
+  EXPECT_TRUE(absl::StrContains(response->body(), expected_json1)) << response->body();
+
+  const std::string expected_json2 = R"EOF("final_value": "1024")EOF";
+  EXPECT_TRUE(absl::StrContains(response->body(), expected_json2)) << response->body();
+#endif
+}
 } // namespace
 } // namespace Envoy

From f3281aeb7339527fd7a473fe2c6af02aa058ee93 Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Wed, 7 Jun 2023 19:35:53 -0400
Subject: [PATCH 205/228] disabling flake (#27843)

Signed-off-by: Alyssa Wilk 
---
 contrib/generic_proxy/filters/network/test/integration_test.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/contrib/generic_proxy/filters/network/test/integration_test.cc b/contrib/generic_proxy/filters/network/test/integration_test.cc
index d68f2d3b154e..552dc6afcc01 100644
--- a/contrib/generic_proxy/filters/network/test/integration_test.cc
+++ b/contrib/generic_proxy/filters/network/test/integration_test.cc
@@ -379,7 +379,8 @@ TEST_P(IntegrationTest, MultipleRequestsWithSameStreamId) {
   cleanup();
 }
 
-TEST_P(IntegrationTest, MultipleRequests) {
+// https://github.com/envoyproxy/envoy/issues/27842
+TEST_P(IntegrationTest, DISABLED_MultipleRequests) {
   FakeStreamCodecFactoryConfig codec_factory_config;
   codec_factory_config.protocol_options_ = ProtocolOptions{true};
   Registry::InjectFactory registration(codec_factory_config);

From a184a9e72ff2e491ceed3f2c36569b7fc6705eaa Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Wed, 7 Jun 2023 20:09:47 -0400
Subject: [PATCH 206/228] lb: adding subset lb tests (#27825)

Signed-off-by: Alyssa Wilk 
---
 .../subset/subset_lb.h                        |  1 -
 test/common/upstream/subset_lb_test.cc        | 41 ++++++++++++++++++-
 test/per_file_coverage.sh                     |  4 +-
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/source/extensions/load_balancing_policies/subset/subset_lb.h b/source/extensions/load_balancing_policies/subset/subset_lb.h
index 0072dcbe8006..8d1c0523b464 100644
--- a/source/extensions/load_balancing_policies/subset/subset_lb.h
+++ b/source/extensions/load_balancing_policies/subset/subset_lb.h
@@ -239,7 +239,6 @@ class SubsetLoadBalancer : public LoadBalancer, Logger::Loggable(host_sets_[priority].get())
           ->update(matching_hosts, hosts_added, hosts_removed);
-
       runUpdateCallbacks(hosts_added, hosts_removed);
     }
 
diff --git a/test/common/upstream/subset_lb_test.cc b/test/common/upstream/subset_lb_test.cc
index 0902264c537c..aa2b44d3eb42 100644
--- a/test/common/upstream/subset_lb_test.cc
+++ b/test/common/upstream/subset_lb_test.cc
@@ -68,12 +68,12 @@ class SubsetLoadBalancerInternalStateTester {
               legacy_child_lb_creator->lbLeastRequestConfig() != absl::nullopt);
   }
 
+  static void testWrapper();
+
 private:
   std::shared_ptr lb_;
 };
 
-namespace SubsetLoadBalancerTest {
-
 class TestMetadataMatchCriterion : public Router::MetadataMatchCriterion {
 public:
   TestMetadataMatchCriterion(const std::string& name, const HashedValue& value)
@@ -161,6 +161,38 @@ class TestMetadataMatchCriteria : public Router::MetadataMatchCriteria {
   std::vector matches_;
 };
 
+void SubsetLoadBalancerInternalStateTester::testWrapper() {
+  MockLoadBalancerContext inner;
+  TestMetadataMatchCriteria test_criteria(std::map{});
+
+  EXPECT_CALL(inner, metadataMatchCriteria)
+      .Times(testing::AnyNumber())
+      .WillRepeatedly(Return(&test_criteria));
+  const std::set filtered_metadata_match_criteria_names;
+  SubsetLoadBalancer::LoadBalancerContextWrapper wrapper(&inner,
+                                                         filtered_metadata_match_criteria_names);
+
+  EXPECT_CALL(inner, computeHashKey());
+  wrapper.computeHashKey();
+
+  EXPECT_CALL(inner, downstreamConnection());
+  wrapper.downstreamConnection();
+
+  EXPECT_CALL(inner, downstreamHeaders());
+  wrapper.downstreamHeaders();
+
+  EXPECT_CALL(inner, upstreamSocketOptions());
+  wrapper.upstreamSocketOptions();
+
+  EXPECT_CALL(inner, upstreamTransportSocketOptions());
+  wrapper.upstreamTransportSocketOptions();
+
+  EXPECT_CALL(inner, overrideHostToSelect());
+  wrapper.overrideHostToSelect();
+}
+
+namespace SubsetLoadBalancerTest {
+
 class TestLoadBalancerContext : public LoadBalancerContextBase {
 public:
   TestLoadBalancerContext(
@@ -2860,6 +2892,11 @@ TEST_P(SubsetLoadBalancerSingleHostPerSubsetTest, Update) {
   EXPECT_EQ(host_set_.hosts_[1], lb_->chooseHost(&host_b)); // fallback
 }
 
+TEST(LoadBalancerContextWrapper, LoadBalancerContextWrapperTest) {
+  // Test private helper class via friend class.
+  SubsetLoadBalancerInternalStateTester::testWrapper();
+}
+
 INSTANTIATE_TEST_SUITE_P(UpdateOrderings, SubsetLoadBalancerSingleHostPerSubsetTest,
                          testing::ValuesIn({UpdateOrder::RemovesFirst, UpdateOrder::Simultaneous}));
 
diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh
index c96fc8feb579..6d350e692d40 100755
--- a/test/per_file_coverage.sh
+++ b/test/per_file_coverage.sh
@@ -76,8 +76,8 @@ declare -a KNOWN_LOW_COVERAGE=(
 "source/extensions/health_checkers:95.9"
 "source/extensions/health_checkers/http:93.8"
 "source/extensions/health_checkers/grpc:92.0"
-"source/extensions/load_balancing_policies:95.5"
-"source/extensions/load_balancing_policies/subset:94.3"
+"source/extensions/load_balancing_policies:96.4"
+"source/extensions/load_balancing_policies/subset:96.0"
 "source/extensions/config_subscription/rest:94.3"
 "source/extensions/matching/input_matchers/cel_matcher:90.7" #Death tests don't report LCOV
 )

From 72c2b962244585cb782161a732eea46f88cc6838 Mon Sep 17 00:00:00 2001
From: yanavlasov 
Date: Wed, 7 Jun 2023 22:50:31 -0400
Subject: [PATCH 207/228] Decommission
 http_strip_fragment_from_path_unsafe_if_disabled (#27847)

Signed-off-by: Yan Avlasov 
---
 changelogs/current.yaml                       |  3 ++
 source/common/http/conn_manager_utility.cc    |  6 +---
 source/common/runtime/runtime_features.cc     |  1 -
 test/common/http/conn_manager_utility_test.cc | 34 -------------------
 4 files changed, 4 insertions(+), 40 deletions(-)

diff --git a/changelogs/current.yaml b/changelogs/current.yaml
index 841fea503761..7fbafbe3002e 100644
--- a/changelogs/current.yaml
+++ b/changelogs/current.yaml
@@ -189,6 +189,9 @@ removed_config_or_runtime:
 - area: config
   change: |
     removed runtime key ``envoy.reloadable_features.delta_xds_subscription_state_tracking_fix`` and legacy code paths.
+- area: http
+  change: |
+    removed runtime key ``envoy.reloadable_features.http_strip_fragment_from_path_unsafe_if_disabled`` and legacy code paths.
 
 new_features:
 - area: access_log
diff --git a/source/common/http/conn_manager_utility.cc b/source/common/http/conn_manager_utility.cc
index 39805b8de253..6d32df007dd5 100644
--- a/source/common/http/conn_manager_utility.cc
+++ b/source/common/http/conn_manager_utility.cc
@@ -564,11 +564,7 @@ ConnectionManagerUtility::maybeNormalizePath(RequestHeaderMap& request_headers,
       return NormalizePathAction::Reject;
     }
     // Check runtime override and throw away fragment from URI path
-    // TODO(yanavlasov): remove this override after deprecation period.
-    if (Runtime::runtimeFeatureEnabled(
-            "envoy.reloadable_features.http_strip_fragment_from_path_unsafe_if_disabled")) {
-      request_headers.setPath(request_headers.getPathValue().substr(0, fragment_pos));
-    }
+    request_headers.setPath(request_headers.getPathValue().substr(0, fragment_pos));
   }
 
   NormalizePathAction final_action = NormalizePathAction::Continue;
diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc
index c7ce0d53bc49..750b702ec48e 100644
--- a/source/common/runtime/runtime_features.cc
+++ b/source/common/runtime/runtime_features.cc
@@ -50,7 +50,6 @@ RUNTIME_GUARD(envoy_reloadable_features_http_allow_partial_urls_in_referer);
 RUNTIME_GUARD(envoy_reloadable_features_http_ext_auth_failure_mode_allow_header_add);
 RUNTIME_GUARD(envoy_reloadable_features_http_filter_avoid_reentrant_local_reply);
 RUNTIME_GUARD(envoy_reloadable_features_http_reject_path_with_fragment);
-RUNTIME_GUARD(envoy_reloadable_features_http_strip_fragment_from_path_unsafe_if_disabled);
 RUNTIME_GUARD(envoy_reloadable_features_ignore_optional_option_from_hcm_for_route_config);
 RUNTIME_GUARD(envoy_reloadable_features_initialize_upstream_filters);
 RUNTIME_GUARD(envoy_reloadable_features_no_extension_lookup_by_name);
diff --git a/test/common/http/conn_manager_utility_test.cc b/test/common/http/conn_manager_utility_test.cc
index 9d6aadb157be..6633650dd204 100644
--- a/test/common/http/conn_manager_utility_test.cc
+++ b/test/common/http/conn_manager_utility_test.cc
@@ -2160,40 +2160,6 @@ TEST_F(ConnectionManagerUtilityTest, DropFragmentFromPathWithOverride) {
   EXPECT_EQ(header_map_with_fragment2.getPathValue(), "/baz/");
 }
 
-TEST_F(ConnectionManagerUtilityTest, KeepFragmentFromPathWithBothOverrides) {
-  TestScopedRuntime scoped_runtime;
-  scoped_runtime.mergeValues(
-      {{"envoy.reloadable_features.http_reject_path_with_fragment", "false"}});
-  scoped_runtime.mergeValues(
-      {{"envoy.reloadable_features.http_strip_fragment_from_path_unsafe_if_disabled", "false"}});
-
-  TestRequestHeaderMapImpl header_map{{":path", "/foo/bar#boom"}};
-  EXPECT_EQ(ConnectionManagerUtility::NormalizePathAction::Continue,
-            ConnectionManagerUtility::maybeNormalizePath(header_map, config_));
-  EXPECT_EQ(header_map.getPathValue(), "/foo/bar#boom");
-
-  TestRequestHeaderMapImpl header_map_just_fragment{{":path", "#"}};
-  EXPECT_EQ(ConnectionManagerUtility::NormalizePathAction::Continue,
-            ConnectionManagerUtility::maybeNormalizePath(header_map_just_fragment, config_));
-  EXPECT_EQ(header_map_just_fragment.getPathValue(), "#");
-
-  TestRequestHeaderMapImpl header_map_just_fragment2{{":path", "/#"}};
-  EXPECT_EQ(ConnectionManagerUtility::NormalizePathAction::Continue,
-            ConnectionManagerUtility::maybeNormalizePath(header_map_just_fragment2, config_));
-  EXPECT_EQ(header_map_just_fragment2.getPathValue(), "/#");
-
-  TestRequestHeaderMapImpl header_map_with_empty_fragment{{":path", "/foo/baz/#"}};
-  EXPECT_EQ(ConnectionManagerUtility::NormalizePathAction::Continue,
-            ConnectionManagerUtility::maybeNormalizePath(header_map_with_empty_fragment, config_));
-  EXPECT_EQ(header_map_with_empty_fragment.getPathValue(), "/foo/baz/#");
-
-  ON_CALL(config_, shouldNormalizePath()).WillByDefault(Return(true));
-  TestRequestHeaderMapImpl header_map_with_fragment2{{":path", "/foo/../baz/#fragment"}};
-  EXPECT_EQ(ConnectionManagerUtility::NormalizePathAction::Continue,
-            ConnectionManagerUtility::maybeNormalizePath(header_map_with_fragment2, config_));
-  EXPECT_EQ(header_map_with_fragment2.getPathValue(), "/baz/%23fragment");
-}
-
 // Verify when append_x_forwarded_port is turned on, the x-forwarded-port header should be appended.
 TEST_F(ConnectionManagerUtilityTest, AppendXForwardedPort) {
   ON_CALL(config_, appendXForwardedPort()).WillByDefault(Return(true));

From aa89bdf9f8f23c9a03c5c536949c93bfe9cb04d1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 8 Jun 2023 09:39:16 +0100
Subject: [PATCH 208/228] build(deps): bump python from 3.11.3-slim-bullseye to
 3.11.4-slim-bullseye in /examples/shared/python (#27867)

build(deps): bump python in /examples/shared/python

Bumps python from 3.11.3-slim-bullseye to 3.11.4-slim-bullseye.

---
updated-dependencies:
- dependency-name: python
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 examples/shared/python/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/shared/python/Dockerfile b/examples/shared/python/Dockerfile
index d64811d72d2d..e152f2165b9d 100644
--- a/examples/shared/python/Dockerfile
+++ b/examples/shared/python/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.11.3-slim-bullseye@sha256:eaee5f73efa9ae962d2077756292bc4878c04fcbc13dc168bb00cc365f35647e as python-base
+FROM python:3.11.4-slim-bullseye@sha256:1966141ab594e175852a033da2a38f0cb042b5b92896c22073f8477f96f43b06 as python-base
 RUN rm -f /etc/apt/apt.conf.d/docker-clean \
     && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache
 ARG PYTHON_REQUIREMENTS_FILE=aiohttp/requirements.txt

From 9b3d08985d70b7ff41812ab48816b062e4f1dbcc Mon Sep 17 00:00:00 2001
From: Paul Sohn 
Date: Thu, 8 Jun 2023 08:09:17 -0400
Subject: [PATCH 209/228] Fix flaky test
 QuicHttpIntegrationTest::DeferredLoggingWithRetransmission (#27850)

Fixes #27841:

Increase the sleep from 500->1000 ms.
Properly clean up the SocketInterfaceSwap.
Commit Message: Fix flaky test DeferredLoggingWithRetransmission
Risk Level: N/A, just testing

Signed-off-by: Paul Sohn 
---
 .../integration/quic_http_integration_test.cc | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc
index c11b91987849..41e7e6c92ce3 100644
--- a/test/integration/quic_http_integration_test.cc
+++ b/test/integration/quic_http_integration_test.cc
@@ -1392,16 +1392,16 @@ TEST_P(QuicHttpIntegrationTest, DeferredLoggingWithRetransmission) {
 
   // Temporarily prevent server from writing packets (i.e. to respond to downstream)
   // to simulate packet loss and trigger retransmissions.
-  SocketInterfaceSwap socket_swap(upstreamProtocol() == Http::CodecType::HTTP3
-                                      ? Network::Socket::Type::Datagram
-                                      : Network::Socket::Type::Stream);
-  Network::IoSocketError* ebadf = Network::IoSocketError::getIoSocketEbadfInstance();
-  socket_swap.write_matcher_->setDestinationPort(lookupPort("http"));
-  socket_swap.write_matcher_->setWriteOverride(ebadf);
-  upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, true);
-  absl::SleepFor(absl::Milliseconds(500 * TSAN_TIMEOUT_FACTOR));
-  // Allow the response to be sent downstream again.
-  socket_swap.write_matcher_->setWriteOverride(nullptr);
+  {
+    SocketInterfaceSwap socket_swap(downstreamProtocol() == Http::CodecType::HTTP3
+                                        ? Network::Socket::Type::Datagram
+                                        : Network::Socket::Type::Stream);
+    Network::IoSocketError* ebadf = Network::IoSocketError::getIoSocketEbadfInstance();
+    socket_swap.write_matcher_->setDestinationPort(lookupPort("http"));
+    socket_swap.write_matcher_->setWriteOverride(ebadf);
+    upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, true);
+    timeSystem().advanceTimeWait(std::chrono::seconds(TSAN_TIMEOUT_FACTOR));
+  }
 
   ASSERT_TRUE(response->waitForEndStream());
   codec_client_->close();

From a9571872dbf1c3c125ab0aaba086e5416e1048f9 Mon Sep 17 00:00:00 2001
From: alyssawilk 
Date: Thu, 8 Jun 2023 08:21:49 -0400
Subject: [PATCH 210/228] runtime: warning (ENVOY_BUG) on bad yaml (#27735)

Adding an ENVOY_BUG for badly formed runtime yaml. If no one complains, I'll runtime-guard remove support after the next release or two with the goal of giving it a year of runtime.

Also cleaning up tests with bad yaml or removed runtime guards which are now flagged by the cleaner code.

Risk Level: medium
Testing: updated tests
Docs Changes:
Release Notes:

Part of #27434

Signed-off-by: Alyssa Wilk 
---
 source/common/runtime/runtime_impl.cc         | 66 +++++++++++++------
 source/common/runtime/runtime_impl.h          |  5 +-
 test/common/runtime/runtime_impl_test.cc      | 30 +++++----
 .../runtime/test_data/root/envoy/file12       |  1 -
 test/config/utility.cc                        | 10 ++-
 .../proxy_filter_integration_test.cc          |  2 -
 .../ext_authz/ext_authz_integration_test.cc   | 11 +++-
 7 files changed, 86 insertions(+), 39 deletions(-)
 delete mode 100644 test/common/runtime/test_data/root/envoy/file12

diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc
index 20704683ac13..81bc35baaf29 100644
--- a/source/common/runtime/runtime_impl.cc
+++ b/source/common/runtime/runtime_impl.cc
@@ -265,39 +265,41 @@ void setNumberValue(Envoy::Runtime::Snapshot::Entry& entry, double value) {
 }
 
 // Handle corner cases in parsing: negatives and decimals aren't always parsed as doubles.
-void parseEntryDoubleValue(Envoy::Runtime::Snapshot::Entry& entry) {
+bool parseEntryDoubleValue(Envoy::Runtime::Snapshot::Entry& entry) {
   double converted_double;
   if (absl::SimpleAtod(entry.raw_string_value_, &converted_double)) {
     setNumberValue(entry, converted_double);
+    return true;
   }
+  return false;
 }
 
 // Handle an awful corner case where we explicitly shove a yaml percent in a proto string
 // value. Basically due to prior parsing logic we have to handle any combination
 // of numerator: #### [denominator Y] with quotes braces etc that could possibly be valid json.
 // E.g. "final_value": "{\"numerator\": 10000, \"denominator\": \"TEN_THOUSAND\"}",
-void parseEntryFractionalPercentValue(Envoy::Runtime::Snapshot::Entry& entry) {
+bool parseEntryFractionalPercentValue(Envoy::Runtime::Snapshot::Entry& entry) {
   if (!absl::StrContains(entry.raw_string_value_, "numerator")) {
-    return;
+    return false;
   }
 
   const re2::RE2 numerator_re(".*numerator[^\\d]+(\\d+)[^\\d]*");
 
   std::string match_string;
   if (!re2::RE2::FullMatch(entry.raw_string_value_.c_str(), numerator_re, &match_string)) {
-    return;
+    return false;
   }
 
   uint32_t numerator;
   if (!absl::SimpleAtoi(match_string, &numerator)) {
-    return;
+    return false;
   }
   envoy::type::v3::FractionalPercent converted_fractional_percent;
   converted_fractional_percent.set_numerator(numerator);
   entry.fractional_percent_value_ = converted_fractional_percent;
 
   if (!absl::StrContains(entry.raw_string_value_, "denominator")) {
-    return;
+    return true;
   }
   if (absl::StrContains(entry.raw_string_value_, "TEN_THOUSAND")) {
     entry.fractional_percent_value_->set_denominator(
@@ -306,22 +308,48 @@ void parseEntryFractionalPercentValue(Envoy::Runtime::Snapshot::Entry& entry) {
   if (absl::StrContains(entry.raw_string_value_, "MILLION")) {
     entry.fractional_percent_value_->set_denominator(envoy::type::v3::FractionalPercent::MILLION);
   }
+  return true;
 }
 
 // Handle corner cases in non-yaml parsing: mixed case strings aren't parsed as booleans.
-void parseEntryBooleanValue(Envoy::Runtime::Snapshot::Entry& entry) {
+bool parseEntryBooleanValue(Envoy::Runtime::Snapshot::Entry& entry) {
   absl::string_view stripped = entry.raw_string_value_;
   stripped = absl::StripAsciiWhitespace(stripped);
 
   if (absl::EqualsIgnoreCase(stripped, "true")) {
     entry.bool_value_ = true;
+    return true;
   } else if (absl::EqualsIgnoreCase(stripped, "false")) {
     entry.bool_value_ = false;
+    return true;
+  }
+  return false;
+}
+
+void SnapshotImpl::addEntry(Snapshot::EntryMap& values, const std::string& key,
+                            const ProtobufWkt::Value& value, absl::string_view raw_string) {
+  const char* error_message = nullptr;
+  values.emplace(key, SnapshotImpl::createEntry(value, raw_string, error_message));
+  if (error_message != nullptr) {
+    IS_ENVOY_BUG(
+        absl::StrCat(error_message, "\n[ key:", key, ", value: ", value.DebugString(), "]"));
   }
 }
 
+static const char* kBoolError =
+    "Runtime YAML appears to be setting booleans as strings. Support for this is planned "
+    "to removed in an upcoming release. If you can not fix your YAML and need this to continue "
+    "working "
+    "please ping on https://github.com/envoyproxy/envoy/issues/27434";
+static const char* kFractionError =
+    "Runtime YAML appears to be setting fractions as strings. Support for this is planned "
+    "to removed in an upcoming release. If you can not fix your YAML and need this to continue "
+    "working "
+    "please ping on https://github.com/envoyproxy/envoy/issues/27434";
+
 SnapshotImpl::Entry SnapshotImpl::createEntry(const ProtobufWkt::Value& value,
-                                              absl::string_view raw_string) {
+                                              absl::string_view raw_string,
+                                              const char*& error_message) {
   Entry entry;
   entry.raw_string_value_ = value.string_value();
   if (!raw_string.empty()) {
@@ -348,10 +376,12 @@ SnapshotImpl::Entry SnapshotImpl::createEntry(const ProtobufWkt::Value& value,
     break;
   case ProtobufWkt::Value::kStringValue:
     parseEntryDoubleValue(entry);
-    // TODO(alyssawilk) after this PR lands and sticks, ENVOY_BUG these
-    // functions and see if we can remove the special casing.
-    parseEntryBooleanValue(entry);
-    parseEntryFractionalPercentValue(entry);
+    if (parseEntryBooleanValue(entry)) {
+      error_message = kBoolError;
+    }
+    if (parseEntryFractionalPercentValue(entry)) {
+      error_message = kFractionError;
+    }
   default:
     break;
   }
@@ -364,8 +394,7 @@ void AdminLayer::mergeValues(const absl::node_hash_map
   for (const auto& kv : values) {
     values_.erase(kv.first);
     if (!kv.second.empty()) {
-      values_.emplace(kv.first,
-                      SnapshotImpl::createEntry(ValueUtil::loadFromYaml(kv.second), kv.second));
+      SnapshotImpl::addEntry(values_, kv.first, ValueUtil::loadFromYaml(kv.second), kv.second);
     }
   }
   stats_.admin_overrides_active_.set(values_.empty() ? 0 : 1);
@@ -435,8 +464,7 @@ void DiskLayer::walkDirectory(const std::string& path, const std::string& prefix
       // the use of the [] operator. Can leverage insert_or_assign in C++17 in the future.
       values_.erase(full_prefix);
 #ifdef ENVOY_ENABLE_YAML
-      values_.insert(
-          {full_prefix, SnapshotImpl::createEntry(ValueUtil::loadFromYaml(value), value)});
+      SnapshotImpl::addEntry(values_, full_prefix, ValueUtil::loadFromYaml(value), value);
 #else
       IS_ENVOY_BUG("Runtime admin reload requires YAML support");
       UNREFERENCED_PARAMETER(value);
@@ -461,7 +489,7 @@ void ProtoLayer::walkProtoValue(const ProtobufWkt::Value& v, const std::string&
     throw EnvoyException(absl::StrCat("Invalid runtime entry value for ", prefix));
     break;
   case ProtobufWkt::Value::kStringValue:
-    values_.emplace(prefix, SnapshotImpl::createEntry(v));
+    SnapshotImpl::addEntry(values_, prefix, v, "");
     break;
   case ProtobufWkt::Value::kNumberValue:
   case ProtobufWkt::Value::kBoolValue:
@@ -470,13 +498,13 @@ void ProtoLayer::walkProtoValue(const ProtobufWkt::Value& v, const std::string&
           "Using a removed guard ", prefix,
           ". In future version of Envoy this will be treated as invalid configuration"));
     }
-    values_.emplace(prefix, SnapshotImpl::createEntry(v));
+    SnapshotImpl::addEntry(values_, prefix, v, "");
     break;
   case ProtobufWkt::Value::kStructValue: {
     const ProtobufWkt::Struct& s = v.struct_value();
     if (s.fields().empty() || s.fields().find("numerator") != s.fields().end() ||
         s.fields().find("denominator") != s.fields().end()) {
-      values_.emplace(prefix, SnapshotImpl::createEntry(v));
+      SnapshotImpl::addEntry(values_, prefix, v, "");
       break;
     }
     for (const auto& f : s.fields()) {
diff --git a/source/common/runtime/runtime_impl.h b/source/common/runtime/runtime_impl.h
index f8e98ec72aec..393228f3323c 100644
--- a/source/common/runtime/runtime_impl.h
+++ b/source/common/runtime/runtime_impl.h
@@ -87,7 +87,10 @@ class SnapshotImpl : public Snapshot, Logger::Loggable {
 
   const EntryMap& values() const;
 
-  static Entry createEntry(const ProtobufWkt::Value& value, absl::string_view raw_string = "");
+  static Entry createEntry(const ProtobufWkt::Value& value, absl::string_view raw_string,
+                           const char*& error_message);
+  static void addEntry(Snapshot::EntryMap& values, const std::string& key,
+                       const ProtobufWkt::Value& value, absl::string_view raw_string = "");
 
 private:
   const std::vector layers_;
diff --git a/test/common/runtime/runtime_impl_test.cc b/test/common/runtime/runtime_impl_test.cc
index e4413c09413d..4992e9fb102c 100644
--- a/test/common/runtime/runtime_impl_test.cc
+++ b/test/common/runtime/runtime_impl_test.cc
@@ -180,9 +180,6 @@ TEST_F(DiskLoaderImplTest, All) {
   // Lower-case boolean specification.
   EXPECT_EQ(true, snapshot->getBoolean("file11", false));
   EXPECT_EQ(true, snapshot->getBoolean("file11", true));
-  // Mixed-case boolean specification.
-  EXPECT_EQ(false, snapshot->getBoolean("file12", true));
-  EXPECT_EQ(false, snapshot->getBoolean("file12", false));
   // Lower-case boolean specification with leading whitespace.
   EXPECT_EQ(true, snapshot->getBoolean("file13", true));
   EXPECT_EQ(true, snapshot->getBoolean("file13", false));
@@ -262,7 +259,7 @@ TEST_F(DiskLoaderImplTest, All) {
 
   EXPECT_EQ(0, store_.counter("runtime.load_error").value());
   EXPECT_EQ(1, store_.counter("runtime.load_success").value());
-  EXPECT_EQ(25, store_.gauge("runtime.num_keys", Stats::Gauge::ImportMode::NeverImport).value());
+  EXPECT_EQ(24, store_.gauge("runtime.num_keys", Stats::Gauge::ImportMode::NeverImport).value());
   EXPECT_EQ(4, store_.gauge("runtime.num_layers", Stats::Gauge::ImportMode::NeverImport).value());
 }
 
@@ -604,7 +601,6 @@ TEST_F(StaticLoaderImplTest, ProtoParsing) {
       denominator: NONSENSE
     file10: 52
     file11: true
-    file12: FaLSe
     file13: false
     subdir:
       file: "hello"
@@ -648,9 +644,6 @@ TEST_F(StaticLoaderImplTest, ProtoParsing) {
   EXPECT_EQ(true, snapshot->getBoolean("file11", true));
   EXPECT_EQ(true, snapshot->getBoolean("file11", false));
 
-  EXPECT_EQ(false, snapshot->getBoolean("file12", true));
-  EXPECT_EQ(false, snapshot->getBoolean("file12", false));
-
   EXPECT_EQ(false, snapshot->getBoolean("file13", true));
   EXPECT_EQ(false, snapshot->getBoolean("file13", false));
 
@@ -733,19 +726,20 @@ TEST_F(StaticLoaderImplTest, ProtoParsing) {
 
   EXPECT_EQ(0, store_.counter("runtime.load_error").value());
   EXPECT_EQ(1, store_.counter("runtime.load_success").value());
-  EXPECT_EQ(23, store_.gauge("runtime.num_keys", Stats::Gauge::ImportMode::NeverImport).value());
+  EXPECT_EQ(22, store_.gauge("runtime.num_keys", Stats::Gauge::ImportMode::NeverImport).value());
   EXPECT_EQ(2, store_.gauge("runtime.num_layers", Stats::Gauge::ImportMode::NeverImport).value());
 
+  const char* error = nullptr;
   // While null values are generally filtered out by walkProtoValue, test manually.
   ProtobufWkt::Value empty_value;
   const_cast(dynamic_cast(loader_->snapshot()))
-      .createEntry(empty_value);
+      .createEntry(empty_value, "", error);
 
   // Make sure the hacky fractional percent function works.
   ProtobufWkt::Value fractional_value;
   fractional_value.set_string_value(" numerator:  11 ");
   auto entry = const_cast(dynamic_cast(loader_->snapshot()))
-                   .createEntry(fractional_value);
+                   .createEntry(fractional_value, "", error);
   ASSERT_TRUE(entry.fractional_percent_value_.has_value());
   EXPECT_EQ(entry.fractional_percent_value_->denominator(),
             envoy::type::v3::FractionalPercent::HUNDRED);
@@ -754,7 +748,7 @@ TEST_F(StaticLoaderImplTest, ProtoParsing) {
   // Make sure the hacky percent function works with numerator and denominator
   fractional_value.set_string_value("{\"numerator\": 10000, \"denominator\": \"TEN_THOUSAND\"}");
   entry = const_cast(dynamic_cast(loader_->snapshot()))
-              .createEntry(fractional_value);
+              .createEntry(fractional_value, "", error);
   ASSERT_TRUE(entry.fractional_percent_value_.has_value());
   EXPECT_EQ(entry.fractional_percent_value_->denominator(),
             envoy::type::v3::FractionalPercent::TEN_THOUSAND);
@@ -763,7 +757,7 @@ TEST_F(StaticLoaderImplTest, ProtoParsing) {
   // Make sure the hacky fractional percent function works with million
   fractional_value.set_string_value("{\"numerator\": 10000, \"denominator\": \"MILLION\"}");
   entry = const_cast(dynamic_cast(loader_->snapshot()))
-              .createEntry(fractional_value);
+              .createEntry(fractional_value, "", error);
   ASSERT_TRUE(entry.fractional_percent_value_.has_value());
   EXPECT_EQ(entry.fractional_percent_value_->denominator(),
             envoy::type::v3::FractionalPercent::MILLION);
@@ -772,8 +766,16 @@ TEST_F(StaticLoaderImplTest, ProtoParsing) {
   // Test atoi failure for the hacky fractional percent value function.
   fractional_value.set_string_value(" numerator:  1.1 ");
   entry = const_cast(dynamic_cast(loader_->snapshot()))
-              .createEntry(fractional_value);
+              .createEntry(fractional_value, "", error);
   ASSERT_FALSE(entry.fractional_percent_value_.has_value());
+
+  // Test legacy malformed boolean support
+  ProtobufWkt::Value boolean_value;
+  boolean_value.set_string_value("FaLsE");
+  entry = const_cast(dynamic_cast(loader_->snapshot()))
+              .createEntry(boolean_value, "", error);
+  ASSERT_TRUE(entry.bool_value_.has_value());
+  ASSERT_FALSE(entry.bool_value_.value());
 }
 
 TEST_F(StaticLoaderImplTest, InvalidNumerator) {
diff --git a/test/common/runtime/test_data/root/envoy/file12 b/test/common/runtime/test_data/root/envoy/file12
deleted file mode 100644
index 11bdefe7b29b..000000000000
--- a/test/common/runtime/test_data/root/envoy/file12
+++ /dev/null
@@ -1 +0,0 @@
-FaLSe
diff --git a/test/config/utility.cc b/test/config/utility.cc
index f55bcbf0b362..21781be3852e 100644
--- a/test/config/utility.cc
+++ b/test/config/utility.cc
@@ -928,7 +928,15 @@ void ConfigHelper::configureUpstreamTls(
 void ConfigHelper::addRuntimeOverride(absl::string_view key, absl::string_view value) {
   auto* static_layer =
       bootstrap_.mutable_layered_runtime()->mutable_layers(0)->mutable_static_layer();
-  (*static_layer->mutable_fields())[std::string(key)] = ValueUtil::stringValue(std::string(value));
+
+  if (value == "true") {
+    (*static_layer->mutable_fields())[std::string(key)] = ValueUtil::boolValue(true);
+  } else if (value == "false") {
+    (*static_layer->mutable_fields())[std::string(key)] = ValueUtil::boolValue(false);
+  } else {
+    (*static_layer->mutable_fields())[std::string(key)] =
+        ValueUtil::stringValue(std::string(value));
+  }
 }
 
 void ConfigHelper::setProtocolOptions(envoy::config::cluster::v3::Cluster& cluster,
diff --git a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc
index 093e2ef2b782..d4208cf070da 100644
--- a/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc
+++ b/test/extensions/filters/http/dynamic_forward_proxy/proxy_filter_integration_test.cc
@@ -639,8 +639,6 @@ TEST_P(ProxyFilterIntegrationTest, UseCacheFileAndTestHappyEyeballs) {
   upstream_tls_ = false; // upstream creation doesn't handle autonomous_upstream_
   autonomous_upstream_ = true;
 
-  config_helper_.addRuntimeOverride("envoy.reloadable_features.allow_multiple_dns_addresses",
-                                    "true");
   use_cache_file_ = true;
   // Prepend a bad address
   if (GetParam() == Network::Address::IpVersion::v4) {
diff --git a/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc b/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc
index 3cd67502d74b..2fac3262c22a 100644
--- a/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc
+++ b/test/extensions/filters/http/ext_authz/ext_authz_integration_test.cc
@@ -87,7 +87,16 @@ class ExtAuthzGrpcIntegrationTest : public Grpc::GrpcClientIntegrationParamTest,
 
   void setDenyAtDisableRuntimeConfig(bool deny_at_disable, bool disable_with_metadata) {
     if (!disable_with_metadata) {
-      config_helper_.addRuntimeOverride("envoy.ext_authz.enable", "numerator: 0");
+      config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) {
+        auto* layer = bootstrap.mutable_layered_runtime()->add_layers();
+        layer->set_name("enable layer");
+        ProtobufWkt::Struct& runtime = *layer->mutable_static_layer();
+        bootstrap.mutable_layered_runtime()->mutable_layers(0)->set_name("base layer");
+
+        ProtobufWkt::Struct& enable =
+            *(*runtime.mutable_fields())["envoy.ext_authz.enable"].mutable_struct_value();
+        (*enable.mutable_fields())["numerator"].set_number_value(0);
+      });
     }
     if (deny_at_disable) {
       config_helper_.addRuntimeOverride("envoy.ext_authz.deny_at_disable", "true");

From c5b204ce93f2557c9f1e5868ace160c5f703f89e Mon Sep 17 00:00:00 2001
From: Yousuk Seung 
Date: Thu, 8 Jun 2023 07:04:21 -0700
Subject: [PATCH 211/228] api: use application_utilization in WRR (#27807)

* api: use application_utilization in WRR

Signed-off-by: Yousuk Seung 

* Comment addressed

Signed-off-by: Yousuk Seung 

---------

Signed-off-by: Yousuk Seung 
---
 .../v3/client_side_weighted_round_robin.proto   | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto b/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto
index ae4a99b4517a..c70360a0946b 100644
--- a/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto
+++ b/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto
@@ -22,14 +22,15 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
 // This policy differs from the built-in ROUND_ROBIN policy in terms of
 // how the endpoint weights are determined. In the ROUND_ROBIN policy,
 // the endpoint weights are sent by the control plane via EDS. However,
-// in this policy, the endpoint weights are instead determined via
-// qps (queries per second), eps (errors per second), and CPU utilization
-// metrics sent by the endpoint using the Open Request Cost Aggregation (ORCA)
-// protocol. A query counts towards qps when successful, otherwise towards both
-// qps and eps. What counts as an error is up to the endpoint to define.
-// A config parameter error_utilization_penalty controls the penalty to adjust
-// endpoint weights using eps and qps. The weight of a given endpoint is
-// computed as: qps / (cpu_utilization + eps/qps * error_utilization_penalty)
+// in this policy, the endpoint weights are instead determined via qps (queries
+// per second), eps (errors per second), and utilization metrics sent by the
+// endpoint using the Open Request Cost Aggregation (ORCA) protocol. Utilization
+// is determined by using the ORCA application_utilization field, if set, or
+// else falling back to the cpu_utilization field. All queries count toward qps,
+// regardless of result. Only failed queries count toward eps. A config
+// parameter error_utilization_penalty controls the penalty to adjust endpoint
+// weights using eps and qps. The weight of a given endpoint is computed as:
+//   qps / (utilization + eps/qps * error_utilization_penalty)
 //
 // See the :ref:`load balancing architecture overview` for more information.
 //

From b6bf6fc63359bf551aa2e5fb15553475a9938e3b Mon Sep 17 00:00:00 2001
From: doujiang24 
Date: Thu, 8 Jun 2023 22:27:53 +0800
Subject: [PATCH 212/228] golang filter: parse plugin config in the golang side
 while initializing golang filter (#27821)

Signed-off-by: doujiang24 
---
 contrib/exe/BUILD                             |  1 +
 contrib/golang/common/dso/dso.h               | 57 ++++++++---
 contrib/golang/common/dso/test/dso_test.cc    | 21 ++--
 contrib/golang/filters/http/source/config.cc  |  7 +-
 .../filters/http/source/go/pkg/api/filter.go  |  3 -
 .../http/source/go/pkg/http/capi_impl.go      |  2 +-
 .../filters/http/source/go/pkg/http/config.go |  2 -
 .../filters/http/source/golang_filter.cc      | 96 ++++++++++++-------
 .../filters/http/source/golang_filter.h       | 13 ++-
 contrib/golang/filters/http/test/BUILD        |  1 +
 .../filters/http/test/golang_filter_test.cc   | 38 +++++---
 .../http/test/test_data/passthrough/filter.go |  2 +-
 .../http/test/test_data/routeconfig/config.go | 11 ++-
 .../source/golang_cluster_specifier.cc        | 10 +-
 test/config_test/BUILD                        |  5 +-
 15 files changed, 165 insertions(+), 104 deletions(-)

diff --git a/contrib/exe/BUILD b/contrib/exe/BUILD
index 4391b745912e..f6029dccc224 100644
--- a/contrib/exe/BUILD
+++ b/contrib/exe/BUILD
@@ -37,6 +37,7 @@ envoy_cc_test(
     env = {
         "EXAMPLE_CONFIGS_TAR_PATH": "envoy/configs/example_contrib_configs.tar",
         "DISABLE_TEST_MERGE": "true",
+        "GODEBUG": "cgocheck=0",
     },
     deps = [
         "//test/config_test:example_configs_test_lib",
diff --git a/contrib/golang/common/dso/dso.h b/contrib/golang/common/dso/dso.h
index 36dbedffbc79..4f3cba97688e 100644
--- a/contrib/golang/common/dso/dso.h
+++ b/contrib/golang/common/dso/dso.h
@@ -98,6 +98,11 @@ class ClusterSpecifierDsoImpl : public ClusterSpecifierDso {
 using HttpFilterDsoPtr = std::shared_ptr;
 using ClusterSpecifierDsoPtr = std::shared_ptr;
 
+/*
+ * We do not unload a dynamic library once it is loaded. This is because
+ * Go shared library could not be unload by dlclose yet, see:
+ * https://github.com/golang/go/issues/11100
+ */
 template  class DsoManager {
 
 public:
@@ -105,33 +110,54 @@ template  class DsoManager {
    * Load the go plugin dynamic library.
    * @param dso_id is unique ID for dynamic library.
    * @param dso_name used to specify the absolute path of the dynamic library.
-   * @return false if load are invalid. Otherwise, return true.
+   * @param plugin_name used to specify the unique plugin name.
+   * @return nullptr if load are invalid.
    */
-  static bool load(std::string dso_id, std::string dso_name) {
-    ENVOY_LOG_MISC(debug, "load {} {} dso instance.", dso_id, dso_name);
-    if (getDsoByID(dso_id) != nullptr) {
-      return true;
+  static std::shared_ptr load(std::string dso_id, std::string dso_name,
+                                 std::string plugin_name) {
+    auto dso = load(dso_id, dso_name);
+    if (dso != nullptr) {
+      DsoStoreType& dsoStore = getDsoStore();
+      absl::WriterMutexLock lock(&dsoStore.mutex_);
+      dsoStore.plugin_name_to_dso_[plugin_name] = dso;
     }
+    return dso;
+  };
+
+  /**
+   * Load the go plugin dynamic library.
+   * @param dso_id is unique ID for dynamic library.
+   * @param dso_name used to specify the absolute path of the dynamic library.
+   * @return nullptr if load are invalid.
+   */
+  static std::shared_ptr load(std::string dso_id, std::string dso_name) {
+    ENVOY_LOG_MISC(debug, "load {} {} dso instance.", dso_id, dso_name);
+
     DsoStoreType& dsoStore = getDsoStore();
     absl::WriterMutexLock lock(&dsoStore.mutex_);
+    auto it = dsoStore.id_to_dso_.find(dso_id);
+    if (it != dsoStore.id_to_dso_.end()) {
+      return it->second;
+    }
+
     auto dso = std::make_shared(dso_name);
     if (!dso->loaded()) {
-      return false;
+      return nullptr;
     }
-    dsoStore.map_[dso_id] = std::move(dso);
-    return true;
+    dsoStore.id_to_dso_[dso_id] = dso;
+    return dso;
   };
 
   /**
-   * Get the go plugin dynamic library.
-   * @param dso_id is unique ID for dynamic library.
+   * Get the go plugin dynamic library by plugin name.
+   * @param plugin_name is unique ID for a plugin, one DSO may contains multiple plugins.
    * @return nullptr if get failed. Otherwise, return the DSO instance.
    */
-  static std::shared_ptr getDsoByID(std::string dso_id) {
+  static std::shared_ptr getDsoByPluginName(std::string plugin_name) {
     DsoStoreType& dsoStore = getDsoStore();
     absl::ReaderMutexLock lock(&dsoStore.mutex_);
-    auto it = dsoStore.map_.find(dso_id);
-    if (it != dsoStore.map_.end()) {
+    auto it = dsoStore.plugin_name_to_dso_.find(plugin_name);
+    if (it != dsoStore.plugin_name_to_dso_.end()) {
       return it->second;
     }
     return nullptr;
@@ -140,7 +166,10 @@ template  class DsoManager {
 private:
   using DsoMapType = absl::flat_hash_map>;
   struct DsoStoreType {
-    DsoMapType map_ ABSL_GUARDED_BY(mutex_){{
+    DsoMapType id_to_dso_ ABSL_GUARDED_BY(mutex_){{
+        {"", nullptr},
+    }};
+    DsoMapType plugin_name_to_dso_ ABSL_GUARDED_BY(mutex_){{
         {"", nullptr},
     }};
     absl::Mutex mutex_;
diff --git a/contrib/golang/common/dso/test/dso_test.cc b/contrib/golang/common/dso/test/dso_test.cc
index a24d0cdd4d22..a3d0fd807497 100644
--- a/contrib/golang/common/dso/test/dso_test.cc
+++ b/contrib/golang/common/dso/test/dso_test.cc
@@ -26,32 +26,29 @@ TEST(DsoInstanceTest, SimpleAPI) {
 
 TEST(DsoManagerTest, Pub) {
   auto id = "simple.so";
+  auto plugin_name = "example";
   auto path = genSoPath(id);
 
   // get before load http filter dso
-  auto dso = DsoManager::getDsoByID(id);
+  auto dso = DsoManager::getDsoByPluginName(plugin_name);
   EXPECT_EQ(dso, nullptr);
 
   // first time load http filter dso
-  auto res = DsoManager::load(id, path);
-  EXPECT_EQ(res, true);
+  dso = DsoManager::load(id, path, plugin_name);
+  EXPECT_NE(dso, nullptr);
 
   // get after load http filter dso
-  dso = DsoManager::getDsoByID(id);
+  dso = DsoManager::getDsoByPluginName(plugin_name);
   EXPECT_NE(dso, nullptr);
   EXPECT_EQ(dso->envoyGoFilterNewHttpPluginConfig(0, 0, 0, 0), 100);
 
   // second time load http filter dso
-  res = DsoManager::load(id, path);
-  EXPECT_EQ(res, true);
+  dso = DsoManager::load(id, path, plugin_name);
+  EXPECT_NE(dso, nullptr);
 
   // first time load cluster specifier dso
-  res = DsoManager::load(id, path);
-  EXPECT_EQ(res, true);
-
-  // get after load cluster specifier dso
-  auto cluster_dso = DsoManager::getDsoByID(id);
-  EXPECT_NE(cluster_dso, nullptr);
+  auto cluster_dso = DsoManager::load(id, path);
+  EXPECT_NE(dso, nullptr);
 
   EXPECT_EQ(cluster_dso->envoyGoClusterSpecifierNewPlugin(0, 0), 200);
 }
diff --git a/contrib/golang/filters/http/source/config.cc b/contrib/golang/filters/http/source/config.cc
index 8944c0e45c2f..3b27e08beaa0 100644
--- a/contrib/golang/filters/http/source/config.cc
+++ b/contrib/golang/filters/http/source/config.cc
@@ -22,14 +22,13 @@ Http::FilterFactoryCb GolangFilterConfig::createFilterFactoryFromProtoTyped(
   // loads DSO store a static map and a open handles leak will occur when the filter gets loaded and
   // unloaded.
   // TODO: unload DSO when filter updated.
-  auto res = Dso::DsoManager::load(proto_config.library_id(),
-                                                           proto_config.library_path());
-  if (!res) {
+  auto dso_lib = Dso::DsoManager::load(
+      proto_config.library_id(), proto_config.library_path(), proto_config.plugin_name());
+  if (dso_lib == nullptr) {
     throw EnvoyException(fmt::format("golang_filter: load library failed: {} {}",
                                      proto_config.library_id(), proto_config.library_path()));
   }
 
-  auto dso_lib = Dso::DsoManager::getDsoByID(proto_config.library_id());
   FilterConfigSharedPtr config = std::make_shared(
       proto_config, dso_lib, fmt::format("{}golang.", stats_prefix), context);
 
diff --git a/contrib/golang/filters/http/source/go/pkg/api/filter.go b/contrib/golang/filters/http/source/go/pkg/api/filter.go
index 1d3973a2f525..88d658c8f1b0 100644
--- a/contrib/golang/filters/http/source/go/pkg/api/filter.go
+++ b/contrib/golang/filters/http/source/go/pkg/api/filter.go
@@ -24,10 +24,8 @@ type StreamDecoderFilter interface {
 	DecodeHeaders(RequestHeaderMap, bool) StatusType
 	DecodeData(BufferInstance, bool) StatusType
 	DecodeTrailers(RequestTrailerMap) StatusType
-	// TODO add more for metadata
 }
 
-// TODO merge it to StreamFilterConfigFactory
 type StreamFilterConfigParser interface {
 	Parse(any *anypb.Any) (interface{}, error)
 	Merge(parentConfig interface{}, childConfig interface{}) interface{}
@@ -51,7 +49,6 @@ type StreamEncoderFilter interface {
 	EncodeHeaders(ResponseHeaderMap, bool) StatusType
 	EncodeData(BufferInstance, bool) StatusType
 	EncodeTrailers(ResponseTrailerMap) StatusType
-	// TODO add more for metadata
 }
 
 // stream info
diff --git a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go
index 3df76682028e..ca5993d98814 100644
--- a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go
+++ b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go
@@ -58,7 +58,7 @@ const (
 type httpCApiImpl struct{}
 
 // Only CAPIOK is expected, otherwise, it means unexpected stage when invoke C API,
-// panic here and it will be recover in the Go entry function (TODO).
+// panic here and it will be recover in the Go entry function.
 func handleCApiStatus(status C.CAPIStatus) {
 	switch status {
 	case C.CAPIOK:
diff --git a/contrib/golang/filters/http/source/go/pkg/http/config.go b/contrib/golang/filters/http/source/go/pkg/http/config.go
index b58b2dfd9f0d..eb3dd284f625 100644
--- a/contrib/golang/filters/http/source/go/pkg/http/config.go
+++ b/contrib/golang/filters/http/source/go/pkg/http/config.go
@@ -67,8 +67,6 @@ func envoyGoFilterNewHttpPluginConfig(namePtr, nameLen, configPtr, configLen uin
 		parsedConfig, err := configParser.Parse(&any)
 		if err != nil {
 			cAPI.HttpLog(api.Error, fmt.Sprintf("failed to parse golang plugin config: %v", err))
-			// TODO: we should reject the config in the Envoy side when Go returning 0.
-			// https://github.com/envoyproxy/envoy/issues/25369
 			return 0
 		}
 		configCache.Store(configNum, parsedConfig)
diff --git a/contrib/golang/filters/http/source/golang_filter.cc b/contrib/golang/filters/http/source/golang_filter.cc
index 82aa29bdd97f..674a58209378 100644
--- a/contrib/golang/filters/http/source/golang_filter.cc
+++ b/contrib/golang/filters/http/source/golang_filter.cc
@@ -1123,7 +1123,7 @@ uint64_t Filter::getMergedConfigId(ProcessorState& state) {
   auto id = config_->getConfigId();
   for (auto it : route_config_list) {
     auto route_config = *it;
-    id = route_config.getPluginConfigId(id, config_->pluginName(), config_->soId());
+    id = route_config.getPluginConfigId(id, config_->pluginName());
   }
 
   return id;
@@ -1138,33 +1138,29 @@ FilterConfig::FilterConfig(
     : plugin_name_(proto_config.plugin_name()), so_id_(proto_config.library_id()),
       so_path_(proto_config.library_path()), plugin_config_(proto_config.plugin_config()),
       stats_(GolangFilterStats::generateStats(stats_prefix, context.scope())), dso_lib_(dso_lib) {
-  ENVOY_LOG(debug, "initilizing golang filter config");
-  // NP: dso may not loaded yet, can not invoke envoyGoFilterNewHttpPluginConfig yet.
-};
-
-uint64_t FilterConfig::getConfigId() {
-  if (config_id_ != 0) {
-    return config_id_;
-  }
+  ENVOY_LOG(debug, "initializing golang filter config");
 
   std::string buf;
   auto res = plugin_config_.SerializeToString(&buf);
-  ASSERT(res, "SerializeToString is always successful");
+  ASSERT(res, "SerializeToString should always successful");
   auto buf_ptr = reinterpret_cast(buf.data());
   auto name_ptr = reinterpret_cast(plugin_name_.data());
   config_id_ = dso_lib_->envoyGoFilterNewHttpPluginConfig(name_ptr, plugin_name_.length(), buf_ptr,
                                                           buf.length());
-  ASSERT(config_id_, "config id is always grows");
+  if (config_id_ == 0) {
+    throw EnvoyException(fmt::format("golang filter failed to parse plugin config: {} {}",
+                                     proto_config.library_id(), proto_config.library_path()));
+  }
   ENVOY_LOG(debug, "golang filter new plugin config, id: {}", config_id_);
+};
 
-  return config_id_;
-}
+uint64_t FilterConfig::getConfigId() { return config_id_; }
 
 FilterConfigPerRoute::FilterConfigPerRoute(
     const envoy::extensions::filters::http::golang::v3alpha::ConfigsPerRoute& config,
     Server::Configuration::ServerFactoryContext&) {
   // NP: dso may not loaded yet, can not invoke envoyGoFilterNewHttpPluginConfig yet.
-  ENVOY_LOG(debug, "initilizing per route golang filter config");
+  ENVOY_LOG(debug, "initializing per route golang filter config");
 
   for (const auto& it : config.plugins_config()) {
     auto plugin_name = it.first;
@@ -1176,40 +1172,70 @@ FilterConfigPerRoute::FilterConfigPerRoute(
   }
 }
 
-uint64_t FilterConfigPerRoute::getPluginConfigId(uint64_t parent_id, std::string plugin_name,
-                                                 std::string so_id) const {
+uint64_t FilterConfigPerRoute::getPluginConfigId(uint64_t parent_id,
+                                                 std::string plugin_name) const {
   auto it = plugins_config_.find(plugin_name);
   if (it != plugins_config_.end()) {
-    return it->second->getMergedConfigId(parent_id, so_id);
+    return it->second->getMergedConfigId(parent_id);
   }
   ENVOY_LOG(debug, "golang filter not found plugin config: {}", plugin_name);
   // not found
   return parent_id;
 }
 
-uint64_t RoutePluginConfig::getMergedConfigId(uint64_t parent_id, std::string so_id) {
+RoutePluginConfig::RoutePluginConfig(
+    const std::string plugin_name,
+    const envoy::extensions::filters::http::golang::v3alpha::RouterPlugin& config)
+    : plugin_name_(plugin_name), plugin_config_(config.config()) {
+
+  ENVOY_LOG(debug, "initializing golang filter route plugin config, plugin_name: {}, type_url: {}",
+            plugin_name_, config.config().type_url());
+
+  dso_lib_ = Dso::DsoManager::getDsoByPluginName(plugin_name_);
+  if (dso_lib_ == nullptr) {
+    // RoutePluginConfig may be created before FilterConfig, so dso_lib_ may be null.
+    // i.e. per route config is used in LDS route_config.
+    return;
+  }
+
+  config_id_ = getConfigId();
+  if (config_id_ == 0) {
+    throw EnvoyException(
+        fmt::format("golang filter failed to parse plugin config: {}", plugin_name_));
+  }
+  ENVOY_LOG(debug, "golang filter new per route '{}' plugin config, id: {}", plugin_name_,
+            config_id_);
+};
+
+uint64_t RoutePluginConfig::getConfigId() {
+  if (config_id_ > 0) {
+    return config_id_;
+  }
+  if (dso_lib_ == nullptr) {
+    dso_lib_ = Dso::DsoManager::getDsoByPluginName(plugin_name_);
+    ASSERT(dso_lib_ != nullptr, "load at the request time, so it should not be null");
+  }
+
+  std::string buf;
+  auto res = plugin_config_.SerializeToString(&buf);
+  ASSERT(res, "SerializeToString is always successful");
+  auto buf_ptr = reinterpret_cast(buf.data());
+  auto name_ptr = reinterpret_cast(plugin_name_.data());
+  return dso_lib_->envoyGoFilterNewHttpPluginConfig(name_ptr, plugin_name_.length(), buf_ptr,
+                                                    buf.length());
+};
+
+uint64_t RoutePluginConfig::getMergedConfigId(uint64_t parent_id) {
   if (merged_config_id_ > 0) {
     return merged_config_id_;
   }
 
-  auto name_ptr = reinterpret_cast(plugin_name_.data());
-  auto dlib = Dso::DsoManager::getDsoByID(so_id);
-  ASSERT(dlib != nullptr, "load at the config parse phase, so it should not be null");
+  config_id_ = getConfigId();
+  RELEASE_ASSERT(config_id_, "TODO: terminate request or passthrough");
 
-  if (config_id_ == 0) {
-    std::string buf;
-    auto res = plugin_config_.SerializeToString(&buf);
-    ASSERT(res, "SerializeToString is always successful");
-    auto buf_ptr = reinterpret_cast(buf.data());
-    config_id_ = dlib->envoyGoFilterNewHttpPluginConfig(name_ptr, plugin_name_.length(), buf_ptr,
-                                                        buf.length());
-    ASSERT(config_id_, "config id is always grows");
-    ENVOY_LOG(debug, "golang filter new per route '{}' plugin config, id: {}", plugin_name_,
-              config_id_);
-  }
-
-  merged_config_id_ = dlib->envoyGoFilterMergeHttpPluginConfig(name_ptr, plugin_name_.length(),
-                                                               parent_id, config_id_);
+  auto name_ptr = reinterpret_cast(plugin_name_.data());
+  merged_config_id_ = dso_lib_->envoyGoFilterMergeHttpPluginConfig(name_ptr, plugin_name_.length(),
+                                                                   parent_id, config_id_);
   ASSERT(merged_config_id_, "config id is always grows");
   ENVOY_LOG(debug, "golang filter merge '{}' plugin config, from {} + {} to {}", plugin_name_,
             parent_id, config_id_, merged_config_id_);
diff --git a/contrib/golang/filters/http/source/golang_filter.h b/contrib/golang/filters/http/source/golang_filter.h
index 7d175df45ed2..23f9e6c8b908 100644
--- a/contrib/golang/filters/http/source/golang_filter.h
+++ b/contrib/golang/filters/http/source/golang_filter.h
@@ -56,18 +56,17 @@ using FilterConfigSharedPtr = std::shared_ptr;
 class RoutePluginConfig : Logger::Loggable {
 public:
   RoutePluginConfig(const std::string plugin_name,
-                    const envoy::extensions::filters::http::golang::v3alpha::RouterPlugin& config)
-      : plugin_name_(plugin_name), plugin_config_(config.config()) {
-    ENVOY_LOG(debug, "initilizing golang filter route plugin config, type_url: {}",
-              config.config().type_url());
-  };
+                    const envoy::extensions::filters::http::golang::v3alpha::RouterPlugin& config);
   // TODO: delete plugin config in Go
   ~RoutePluginConfig() = default;
-  uint64_t getMergedConfigId(uint64_t parent_id, std::string so_id);
+  uint64_t getConfigId();
+  uint64_t getMergedConfigId(uint64_t parent_id);
 
 private:
   const std::string plugin_name_;
   const ProtobufWkt::Any plugin_config_;
+
+  Dso::HttpFilterDsoPtr dso_lib_;
   uint64_t config_id_{0};
   uint64_t merged_config_id_{0};
 };
@@ -82,7 +81,7 @@ class FilterConfigPerRoute : public Router::RouteSpecificFilterConfig,
 public:
   FilterConfigPerRoute(const envoy::extensions::filters::http::golang::v3alpha::ConfigsPerRoute&,
                        Server::Configuration::ServerFactoryContext&);
-  uint64_t getPluginConfigId(uint64_t parent_id, std::string plugin_name, std::string so_id) const;
+  uint64_t getPluginConfigId(uint64_t parent_id, std::string plugin_name) const;
 
   ~FilterConfigPerRoute() override { plugins_config_.clear(); }
 
diff --git a/contrib/golang/filters/http/test/BUILD b/contrib/golang/filters/http/test/BUILD
index 6721341093b2..040024a78082 100644
--- a/contrib/golang/filters/http/test/BUILD
+++ b/contrib/golang/filters/http/test/BUILD
@@ -29,6 +29,7 @@ envoy_cc_test(
     srcs = ["golang_filter_test.cc"],
     data = [
         "//contrib/golang/filters/http/test/test_data/passthrough:filter.so",
+        "//contrib/golang/filters/http/test/test_data/routeconfig:filter.so",
     ],
     env = {"GODEBUG": "cgocheck=0"},
     deps = [
diff --git a/contrib/golang/filters/http/test/golang_filter_test.cc b/contrib/golang/filters/http/test/golang_filter_test.cc
index 4af781d110f1..bf21fb7513bc 100644
--- a/contrib/golang/filters/http/test/golang_filter_test.cc
+++ b/contrib/golang/filters/http/test/golang_filter_test.cc
@@ -73,7 +73,11 @@ class GolangHttpFilterTest : public testing::Test {
     EXPECT_CALL(decoder_callbacks_, streamInfo()).Times(testing::AnyNumber());
   }
 
-  ~GolangHttpFilterTest() override { filter_->onDestroy(); }
+  ~GolangHttpFilterTest() override {
+    if (filter_ != nullptr) {
+      filter_->onDestroy();
+    }
+  }
 
   void setup(const std::string& lib_id, const std::string& lib_path,
              const std::string& plugin_name) {
@@ -81,13 +85,13 @@ class GolangHttpFilterTest : public testing::Test {
     library_id: %s
     library_path: %s
     plugin_name: %s
-    merge_policy: MERGE_VIRTUALHOST_ROUTER_FILTER
     plugin_config:
-      "@type": type.googleapis.com/udpa.type.v1.TypedStruct
+      "@type": type.googleapis.com/xds.type.v3.TypedStruct
       type_url: typexx
       value:
           key: value
           int: 10
+          invalid: "invalid"
     )EOF";
 
     auto yaml_string = absl::StrFormat(yaml_fmt, lib_id, lib_path, plugin_name);
@@ -95,9 +99,9 @@ class GolangHttpFilterTest : public testing::Test {
     TestUtility::loadFromYaml(yaml_string, proto_config);
 
     envoy::extensions::filters::http::golang::v3alpha::ConfigsPerRoute per_route_proto_config;
-    setupDso();
-    setupConfig(proto_config, per_route_proto_config);
-    setupFilter(lib_id);
+    setupDso(lib_id, lib_path, plugin_name);
+    setupConfig(proto_config, per_route_proto_config, plugin_name);
+    setupFilter(plugin_name);
   }
 
   std::string genSoPath(std::string name) {
@@ -105,29 +109,29 @@ class GolangHttpFilterTest : public testing::Test {
         "{{ test_rundir }}/contrib/golang/filters/http/test/test_data/" + name + "/filter.so");
   }
 
-  void setupDso() {
-    Dso::DsoManager::load(PASSTHROUGH, genSoPath(PASSTHROUGH));
+  void setupDso(std::string id, std::string path, std::string plugin_name) {
+    Dso::DsoManager::load(id, path, plugin_name);
   }
 
   void setupConfig(
       envoy::extensions::filters::http::golang::v3alpha::Config& proto_config,
-      envoy::extensions::filters::http::golang::v3alpha::ConfigsPerRoute& per_route_proto_config) {
+      envoy::extensions::filters::http::golang::v3alpha::ConfigsPerRoute& per_route_proto_config,
+      std::string plugin_name) {
     // Setup filter config for Golang filter.
     config_ = std::make_shared(
-        proto_config,
-        Dso::DsoManager::getDsoByID(proto_config.library_id()), "",
+        proto_config, Dso::DsoManager::getDsoByPluginName(plugin_name), "",
         context_);
     // Setup per route config for Golang filter.
     per_route_config_ =
         std::make_shared(per_route_proto_config, server_factory_context_);
   }
 
-  void setupFilter(const std::string& so_id) {
+  void setupFilter(const std::string& plugin_name) {
     Event::SimulatedTimeSystem test_time;
     test_time.setSystemTime(std::chrono::microseconds(1583879145572237));
 
     filter_ = std::make_unique(
-        config_, Dso::DsoManager::getDsoByID(so_id));
+        config_, Dso::DsoManager::getDsoByPluginName(plugin_name));
     filter_->setDecoderFilterCallbacks(decoder_callbacks_);
     filter_->setEncoderFilterCallbacks(encoder_callbacks_);
   }
@@ -155,6 +159,7 @@ class GolangHttpFilterTest : public testing::Test {
   Stats::TestUtil::TestStore stats_store_;
 
   const std::string PASSTHROUGH{"passthrough"};
+  const std::string ROUTECONFIG{"routeconfig"};
 };
 
 // request that is headers only.
@@ -175,6 +180,13 @@ TEST_F(GolangHttpFilterTest, SetHeaderAtWrongStage) {
   EXPECT_EQ(CAPINotInGo, filter_->setHeader("foo", "bar", HeaderSet));
 }
 
+// invalid config for routeconfig filter
+TEST_F(GolangHttpFilterTest, InvalidConfigForRouteConfigFilter) {
+  InSequence s;
+  EXPECT_THROW_WITH_REGEX(setup(ROUTECONFIG, genSoPath(ROUTECONFIG), ROUTECONFIG), EnvoyException,
+                          "golang filter failed to parse plugin config");
+}
+
 } // namespace
 } // namespace Golang
 } // namespace HttpFilters
diff --git a/contrib/golang/filters/http/test/test_data/passthrough/filter.go b/contrib/golang/filters/http/test/test_data/passthrough/filter.go
index c78dbee0f462..17b40b0e459e 100644
--- a/contrib/golang/filters/http/test/test_data/passthrough/filter.go
+++ b/contrib/golang/filters/http/test/test_data/passthrough/filter.go
@@ -5,7 +5,7 @@ import (
 )
 
 func init() {
-	http.RegisterHttpFilterConfigFactoryAndParser("", http.PassThroughFactory, nil)
+	http.RegisterHttpFilterConfigFactoryAndParser("passthrough", http.PassThroughFactory, nil)
 }
 
 func main() {
diff --git a/contrib/golang/filters/http/test/test_data/routeconfig/config.go b/contrib/golang/filters/http/test/test_data/routeconfig/config.go
index fe7067edb01c..5af08bf8a41e 100644
--- a/contrib/golang/filters/http/test/test_data/routeconfig/config.go
+++ b/contrib/golang/filters/http/test/test_data/routeconfig/config.go
@@ -1,6 +1,8 @@
 package main
 
 import (
+	"errors"
+
 	xds "github.com/cncf/xds/go/xds/type/v3"
 	"github.com/envoyproxy/envoy/contrib/golang/filters/http/source/go/pkg/api"
 	"github.com/envoyproxy/envoy/contrib/golang/filters/http/source/go/pkg/http"
@@ -40,12 +42,15 @@ func (p *parser) Parse(any *anypb.Any) (interface{}, error) {
 		return nil, err
 	}
 
-	v := configStruct.Value
 	conf := &config{}
-	if remove, ok := v.AsMap()["remove"].(string); ok {
+	m := configStruct.Value.AsMap()
+	if _, ok := m["invalid"].(string); ok {
+		return nil, errors.New("testing invalid config")
+	}
+	if remove, ok := m["remove"].(string); ok {
 		conf.removeHeader = remove
 	}
-	if set, ok := v.AsMap()["set"].(string); ok {
+	if set, ok := m["set"].(string); ok {
 		conf.setHeader = set
 	}
 	return conf, nil
diff --git a/contrib/golang/router/cluster_specifier/source/golang_cluster_specifier.cc b/contrib/golang/router/cluster_specifier/source/golang_cluster_specifier.cc
index 37cd2c0a1cb5..96f90930b2d4 100644
--- a/contrib/golang/router/cluster_specifier/source/golang_cluster_specifier.cc
+++ b/contrib/golang/router/cluster_specifier/source/golang_cluster_specifier.cc
@@ -21,15 +21,9 @@ ClusterConfig::ClusterConfig(const GolangClusterProto& config)
   // loads DSO store a static map and a open handles leak will occur when the filter gets loaded and
   // unloaded.
   // TODO: unload DSO when filter updated.
-  auto res = Envoy::Dso::DsoManager::load(so_id_, so_path_);
-  if (!res) {
-    throw EnvoyException(fmt::format("golang_cluster_specifier_plugin: load library failed: {} {}",
-                                     so_id_, so_path_));
-  }
-
-  dynamic_lib_ = Dso::DsoManager::getDsoByID(so_id_);
+  dynamic_lib_ = Envoy::Dso::DsoManager::load(so_id_, so_path_);
   if (dynamic_lib_ == nullptr) {
-    throw EnvoyException(fmt::format("golang_cluster_specifier_plugin: get library failed: {} {}",
+    throw EnvoyException(fmt::format("golang_cluster_specifier_plugin: load library failed: {} {}",
                                      so_id_, so_path_));
   }
 
diff --git a/test/config_test/BUILD b/test/config_test/BUILD
index 5ad16a344c68..3fa4a6234c2f 100644
--- a/test/config_test/BUILD
+++ b/test/config_test/BUILD
@@ -35,7 +35,10 @@ envoy_cc_test(
         "example_configs_test_setup.sh",
         "//configs:example_configs",
     ],
-    env = {"EXAMPLE_CONFIGS_TAR_PATH": "envoy/configs/example_configs.tar"},
+    env = {
+        "EXAMPLE_CONFIGS_TAR_PATH": "envoy/configs/example_configs.tar",
+        "GODEBUG": "cgocheck=0",
+    },
     deps = [
         ":example_configs_test_lib",
     ],

From 46c37678e5c9ffc7e06189fe060ec02e9296d58b Mon Sep 17 00:00:00 2001
From: botengyao 
Date: Thu, 8 Jun 2023 10:33:08 -0400
Subject: [PATCH 213/228] hc: add host related info to the health check event
 (#27833)

Signed-off-by: Boteng Yao 
---
 .../data/core/v3/health_check_event.proto     |  9 +++++-
 changelogs/current.yaml                       |  5 ++++
 .../upstream/health_checker_event_logger.cc   |  4 +++
 .../upstream/health_checker_impl_test.cc      | 28 +++++++++++++++++--
 4 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/api/envoy/data/core/v3/health_check_event.proto b/api/envoy/data/core/v3/health_check_event.proto
index a349fa31bc08..17e78ea5ecb1 100644
--- a/api/envoy/data/core/v3/health_check_event.proto
+++ b/api/envoy/data/core/v3/health_check_event.proto
@@ -3,6 +3,7 @@ syntax = "proto3";
 package envoy.data.core.v3;
 
 import "envoy/config/core/v3/address.proto";
+import "envoy/config/core/v3/base.proto";
 
 import "google/protobuf/timestamp.proto";
 
@@ -34,7 +35,7 @@ enum HealthCheckerType {
   THRIFT = 4;
 }
 
-// [#next-free-field: 10]
+// [#next-free-field: 12]
 message HealthCheckEvent {
   option (udpa.annotations.versioning).previous_message_type =
       "envoy.data.core.v2alpha.HealthCheckEvent";
@@ -66,6 +67,12 @@ message HealthCheckEvent {
 
   // Timestamp for event.
   google.protobuf.Timestamp timestamp = 6;
+
+  // Host metadata
+  config.core.v3.Metadata metadata = 10;
+
+  // Host locality
+  config.core.v3.Locality locality = 11;
 }
 
 message HealthCheckEjectUnhealthy {
diff --git a/changelogs/current.yaml b/changelogs/current.yaml
index 7fbafbe3002e..a393fc0e6b39 100644
--- a/changelogs/current.yaml
+++ b/changelogs/current.yaml
@@ -326,6 +326,11 @@ new_features:
 - area: http
   change: |
     added support for configuring additional :ref:`cookie attributes `.
+- area: health_check
+  change: |
+    added host related information :ref:`metadata ` and
+    :ref:`locality ` to
+    the :ref:`health check event ` definition.
 
 deprecated:
 - area: access_log
diff --git a/source/common/upstream/health_checker_event_logger.cc b/source/common/upstream/health_checker_event_logger.cc
index a293bcaa3be3..c75d3a55e6db 100644
--- a/source/common/upstream/health_checker_event_logger.cc
+++ b/source/common/upstream/health_checker_event_logger.cc
@@ -61,6 +61,10 @@ void HealthCheckEventLoggerImpl::createHealthCheckEvent(
   envoy::config::core::v3::Address address;
   Network::Utility::addressToProtobufAddress(*host.address(), address);
   *event.mutable_host() = std::move(address);
+  if (host.metadata() != nullptr) {
+    *event.mutable_metadata() = *host.metadata();
+  }
+  *event.mutable_locality() = host.locality();
 
   TimestampUtil::systemClockToTimestamp(time_source_.systemTime(), *event.mutable_timestamp());
 
diff --git a/test/common/upstream/health_checker_impl_test.cc b/test/common/upstream/health_checker_impl_test.cc
index 8e97475b2e73..8c44cd9b1f31 100644
--- a/test/common/upstream/health_checker_impl_test.cc
+++ b/test/common/upstream/health_checker_impl_test.cc
@@ -6404,7 +6404,9 @@ TEST(HealthCheckEventLoggerImplTest, All) {
 
   std::shared_ptr host(new NiceMock());
   NiceMock cluster_info;
+  MetadataConstSharedPtr metadata(new envoy::config::core::v3::Metadata());
   ON_CALL(*host, cluster()).WillByDefault(ReturnRef(cluster_info));
+  ON_CALL(*host, metadata()).WillByDefault(Return(metadata));
 
   HealthCheckerFactoryContextImpl context(cluster, runtime, dispatcher, validation_visitor, api,
                                           log_manager);
@@ -6420,6 +6422,8 @@ TEST(HealthCheckEventLoggerImplTest, All) {
                          "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                          "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
                          "cluster\",\"eject_unhealthy_event\":{\"failure_type\":\"ACTIVE\"},"
+                         "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+                         "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
                          "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"}));
   event_logger.logEjectUnhealthy(envoy::data::core::v3::HTTP, host, envoy::data::core::v3::ACTIVE);
 
@@ -6427,7 +6431,9 @@ TEST(HealthCheckEventLoggerImplTest, All) {
                          "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{"
                          "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                          "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
-                         "cluster\",\"add_healthy_event\":{\"first_check\":false},\"timestamp\":"
+                         "cluster\",\"add_healthy_event\":{\"first_check\":false},\"metadata\":"
+                         "{\"filter_metadata\":{},\"typed_filter_metadata\":{}},\"locality\":"
+                         "{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},\"timestamp\":"
                          "\"2009-02-13T23:31:31.234Z\"}\n"}));
   event_logger.logAddHealthy(envoy::data::core::v3::HTTP, host, false);
 
@@ -6437,6 +6443,8 @@ TEST(HealthCheckEventLoggerImplTest, All) {
                          "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
                          "cluster\",\"health_check_failure_event\":{\"failure_type\":\"ACTIVE\","
                          "\"first_check\":false},"
+                         "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+                         "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
                          "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"}));
   event_logger.logUnhealthy(envoy::data::core::v3::HTTP, host, envoy::data::core::v3::ACTIVE,
                             false);
@@ -6446,6 +6454,8 @@ TEST(HealthCheckEventLoggerImplTest, All) {
                          "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                          "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
                          "cluster\",\"degraded_healthy_host\":{},"
+                         "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+                         "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
                          "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"}));
   event_logger.logDegraded(envoy::data::core::v3::HTTP, host);
 
@@ -6454,6 +6464,8 @@ TEST(HealthCheckEventLoggerImplTest, All) {
                          "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                          "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
                          "cluster\",\"no_longer_degraded_host\":{},"
+                         "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+                         "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
                          "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n"}));
   event_logger.logNoLongerDegraded(envoy::data::core::v3::HTTP, host);
 }
@@ -6477,7 +6489,9 @@ TEST(HealthCheckEventLoggerImplTest, OneEventLogger) {
 
   std::shared_ptr host(new NiceMock());
   NiceMock cluster_info;
+  MetadataConstSharedPtr metadata(new envoy::config::core::v3::Metadata());
   ON_CALL(*host, cluster()).WillByDefault(ReturnRef(cluster_info));
+  ON_CALL(*host, metadata()).WillByDefault(Return(metadata));
 
   HealthCheckerFactoryContextImpl context(cluster, runtime, dispatcher, validation_visitor, api,
                                           log_manager);
@@ -6493,13 +6507,17 @@ TEST(HealthCheckEventLoggerImplTest, OneEventLogger) {
                            "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                            "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
                            "cluster\",\"eject_unhealthy_event\":{\"failure_type\":\"ACTIVE\"},"
+                           "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+                           "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
                            "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n");
 
   event_logger.logAddHealthy(envoy::data::core::v3::HTTP, host, false);
   EXPECT_EQ(file_log_data, "{\"health_checker_type\":\"HTTP\",\"host\":{\"socket_address\":{"
                            "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                            "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
-                           "cluster\",\"add_healthy_event\":{\"first_check\":false},\"timestamp\":"
+                           "cluster\",\"add_healthy_event\":{\"first_check\":false},\"metadata\":"
+                           "{\"filter_metadata\":{},\"typed_filter_metadata\":{}},\"locality\":"
+                           "{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},\"timestamp\":"
                            "\"2009-02-13T23:31:31.234Z\"}\n");
 
   event_logger.logUnhealthy(envoy::data::core::v3::HTTP, host, envoy::data::core::v3::ACTIVE,
@@ -6510,6 +6528,8 @@ TEST(HealthCheckEventLoggerImplTest, OneEventLogger) {
             "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
             "cluster\",\"health_check_failure_event\":{\"failure_type\":\"ACTIVE\","
             "\"first_check\":false},"
+            "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+            "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
             "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n");
 
   event_logger.logDegraded(envoy::data::core::v3::HTTP, host);
@@ -6517,6 +6537,8 @@ TEST(HealthCheckEventLoggerImplTest, OneEventLogger) {
                            "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                            "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
                            "cluster\",\"degraded_healthy_host\":{},"
+                           "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+                           "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
                            "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n");
 
   event_logger.logNoLongerDegraded(envoy::data::core::v3::HTTP, host);
@@ -6524,6 +6546,8 @@ TEST(HealthCheckEventLoggerImplTest, OneEventLogger) {
                            "\"protocol\":\"TCP\",\"address\":\"10.0.0.1\",\"resolver_name\":\"\","
                            "\"ipv4_compat\":false,\"port_value\":443}},\"cluster_name\":\"fake_"
                            "cluster\",\"no_longer_degraded_host\":{},"
+                           "\"metadata\":{\"filter_metadata\":{},\"typed_filter_metadata\":{}},"
+                           "\"locality\":{\"region\":\"\",\"zone\":\"\",\"sub_zone\":\"\"},"
                            "\"timestamp\":\"2009-02-13T23:31:31.234Z\"}\n");
 }
 

From 08dd6fedf0c433c341e74e689194beb23540932c Mon Sep 17 00:00:00 2001
From: ohadvano <49730675+ohadvano@users.noreply.github.com>
Date: Thu, 8 Jun 2023 17:34:03 +0300
Subject: [PATCH 214/228] application_logs: add bootstrap option to set log
 format (#27816)

add bootstrap option to set log format

Signed-off-by: ohadvano 
---
 api/envoy/config/bootstrap/v3/bootstrap.proto |  5 +++
 changelogs/current.yaml                       |  5 +++
 source/server/utils.cc                        |  9 +++-
 test/server/config_validation/server_test.cc  | 41 +++++++++++++++++++
 .../test_data/text_application_logs.yaml      | 10 +++++
 test/server/server_test.cc                    | 13 ++++++
 .../server/text_application_log.yaml          | 10 +++++
 test/server/utils_test.cc                     |  6 +++
 8 files changed, 97 insertions(+), 2 deletions(-)
 create mode 100644 test/server/config_validation/test_data/text_application_logs.yaml
 create mode 100644 test/server/test_data/server/text_application_log.yaml

diff --git a/api/envoy/config/bootstrap/v3/bootstrap.proto b/api/envoy/config/bootstrap/v3/bootstrap.proto
index f171068aaeed..43e3a33a3f15 100644
--- a/api/envoy/config/bootstrap/v3/bootstrap.proto
+++ b/api/envoy/config/bootstrap/v3/bootstrap.proto
@@ -110,6 +110,11 @@ message Bootstrap {
         // support all the format flags specified in the :option:`--log-format`
         // command line options section, except for the ``%v`` and ``%_`` flags.
         google.protobuf.Struct json_format = 1;
+
+        // Flush application log in a format defined by a string. The text format
+        // can support all the format flags specified in the :option:`--log-format`
+        // command line option section.
+        string text_format = 2;
       }
     }
 
diff --git a/changelogs/current.yaml b/changelogs/current.yaml
index a393fc0e6b39..da7ca4343063 100644
--- a/changelogs/current.yaml
+++ b/changelogs/current.yaml
@@ -309,6 +309,11 @@ new_features:
     Added bootstrap option
     :ref:`application_log_format `
     to enable setting application log format as JSON structure.
+- area: application_logs
+  change: |
+    Added bootstrap option
+    :ref:`application_log_format `
+    to enable setting application log text format from config.
 - area: ext_proc
   change: |
     added new field ``filter_metadata  getAllConfigFiles() {
+    setupTestDirectory();
+    return {"text_application_logs.yaml"};
+  }
+};
+
 TEST_P(ValidationServerTest, Validate) {
   EXPECT_TRUE(validateConfig(options_, Network::Address::InstanceConstSharedPtr(),
                              component_factory_, Thread::threadFactoryForTest(),
@@ -324,6 +341,30 @@ INSTANTIATE_TEST_SUITE_P(
     ::testing::ValuesIn(
         JsonApplicationLogsValidationServerForbiddenFlagUnderscoreTest::getAllConfigFiles()));
 
+TEST_P(TextApplicationLogsValidationServerTest, TextApplicationLogs) {
+  Thread::MutexBasicLockable access_log_lock;
+  Stats::IsolatedStoreImpl stats_store;
+  DangerousDeprecatedTestTime time_system;
+  ValidationInstance server(options_, time_system.timeSystem(),
+                            Network::Address::InstanceConstSharedPtr(), stats_store,
+                            access_log_lock, component_factory_, Thread::threadFactoryForTest(),
+                            Filesystem::fileSystemForTest());
+
+  Envoy::Logger::Registry::setLogLevel(spdlog::level::info);
+  MockLogSink sink(Envoy::Logger::Registry::getSink());
+  EXPECT_CALL(sink, log(_, _)).WillOnce(Invoke([](auto msg, auto& log) {
+    EXPECT_THAT(msg, HasSubstr("[lvl: info][msg: hello]"));
+    EXPECT_EQ(log.logger_name, "misc");
+  }));
+
+  ENVOY_LOG_MISC(info, "hello");
+  server.shutdown();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    AllConfigs, TextApplicationLogsValidationServerTest,
+    ::testing::ValuesIn(TextApplicationLogsValidationServerTest::getAllConfigFiles()));
+
 } // namespace
 } // namespace Server
 } // namespace Envoy
diff --git a/test/server/config_validation/test_data/text_application_logs.yaml b/test/server/config_validation/test_data/text_application_logs.yaml
new file mode 100644
index 000000000000..f598e8ffcde5
--- /dev/null
+++ b/test/server/config_validation/test_data/text_application_logs.yaml
@@ -0,0 +1,10 @@
+---
+application_log_config:
+  log_format:
+    text_format: "[lvl: %l][msg: %v]"
+
+admin:
+  address:
+    socket_address:
+      address: 0.0.0.0
+      port_value: 9000
diff --git a/test/server/server_test.cc b/test/server/server_test.cc
index a98c6e9d2663..c732c88209ab 100644
--- a/test/server/server_test.cc
+++ b/test/server/server_test.cc
@@ -1648,6 +1648,19 @@ TEST_P(ServerInstanceImplTest, JsonApplicationLogFailWithForbiddenFlagUnderscore
       "setJsonLogFormat error: INVALID_ARGUMENT: Usage of %_ is unavailable for JSON log formats");
 }
 
+TEST_P(ServerInstanceImplTest, TextApplicationLog) {
+  EXPECT_NO_THROW(initialize("test/server/test_data/server/text_application_log.yaml"));
+
+  Envoy::Logger::Registry::setLogLevel(spdlog::level::info);
+  MockLogSink sink(Envoy::Logger::Registry::getSink());
+  EXPECT_CALL(sink, log(_, _)).WillOnce(Invoke([](auto msg, auto& log) {
+    EXPECT_THAT(msg, HasSubstr("[lvl: info][msg: hello]"));
+    EXPECT_EQ(log.logger_name, "misc");
+  }));
+
+  ENVOY_LOG_MISC(info, "hello");
+}
+
 } // namespace
 } // namespace Server
 } // namespace Envoy
diff --git a/test/server/test_data/server/text_application_log.yaml b/test/server/test_data/server/text_application_log.yaml
new file mode 100644
index 000000000000..f598e8ffcde5
--- /dev/null
+++ b/test/server/test_data/server/text_application_log.yaml
@@ -0,0 +1,10 @@
+---
+application_log_config:
+  log_format:
+    text_format: "[lvl: %l][msg: %v]"
+
+admin:
+  address:
+    socket_address:
+      address: 0.0.0.0
+      port_value: 9000
diff --git a/test/server/utils_test.cc b/test/server/utils_test.cc
index 7576e41522c1..ea05b4836af2 100644
--- a/test/server/utils_test.cc
+++ b/test/server/utils_test.cc
@@ -69,6 +69,12 @@ TEST(UtilsTest, MaybeSetApplicationLogFormat) {
     EXPECT_NO_THROW(Utility::maybeSetApplicationLogFormat(log_config));
   }
 
+  {
+    envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config;
+    log_config.mutable_log_format()->mutable_text_format();
+    EXPECT_NO_THROW(Utility::maybeSetApplicationLogFormat(log_config));
+  }
+
   {
     envoy::config::bootstrap::v3::Bootstrap::ApplicationLogConfig log_config;
     auto* format = log_config.mutable_log_format()->mutable_json_format();

From 26f2fce16bb417f8615d929fe8b8b93486820cc3 Mon Sep 17 00:00:00 2001
From: realtimetodie 
Date: Thu, 8 Jun 2023 16:43:54 +0200
Subject: [PATCH 215/228] chore: update owner for http language filter contrib
 extension (#27873)

Signed-off-by: shooj4aegohbaivo 
---
 CODEOWNERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CODEOWNERS b/CODEOWNERS
index 33b257f22307..c544bdb82b03 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -358,7 +358,7 @@ extensions/filters/http/oauth2 @derekargueta @snowp
 /contrib/cryptomb/ @giantcroc @soulxu
 /contrib/vcl/ @florincoras @KfreeZ
 /contrib/hyperscan/ @zhxie @soulxu
-/contrib/language/ @diceride @diceride
+/contrib/language/ @realtimetodie @realtimetodie
 /contrib/dlb/ @mattklein123 @daixiang0
 /contrib/qat/ @giantcroc @soulxu
 /contrib/generic_proxy/ @wbpcode @soulxu @zhaohuabing @rojkov @htuch

From d7e2fa27e5ca4633d8d64d44dcc56e9b661f5bd2 Mon Sep 17 00:00:00 2001
From: yanavlasov 
Date: Thu, 8 Jun 2023 10:54:06 -0400
Subject: [PATCH 216/228] Avoid copying garbage if pthread_getname_np fails
 (#27862)

Signed-off-by: Yan Avlasov 
---
 source/common/common/posix/thread_impl.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/common/common/posix/thread_impl.cc b/source/common/common/posix/thread_impl.cc
index 5d78dd24a56e..e935ac53c11b 100644
--- a/source/common/common/posix/thread_impl.cc
+++ b/source/common/common/posix/thread_impl.cc
@@ -99,7 +99,7 @@ class ThreadImplPosix : public Thread {
   // may fail, if the thread exits prior to the system call.
   bool getNameFromOS(std::string& name) {
     // Verify that the name got written into the thread as expected.
-    char buf[PTHREAD_MAX_THREADNAME_LEN_INCLUDING_NULL_BYTE];
+    char buf[PTHREAD_MAX_THREADNAME_LEN_INCLUDING_NULL_BYTE] = {0};
     const int get_name_rc = pthread_getname_np(thread_handle_, buf, sizeof(buf));
     name = buf;
     return get_name_rc == 0;

From a757dc8d18f52680dec34485376687a7da0a2509 Mon Sep 17 00:00:00 2001
From: yanavlasov 
Date: Thu, 8 Jun 2023 10:58:19 -0400
Subject: [PATCH 217/228] Make Balsa validation of transfer-encoding consistent
 with http-parser and UHV (#27849)

Signed-off-by: Yan Avlasov 
---
 source/common/http/http1/balsa_parser.cc  |  3 ---
 test/common/http/http1/codec_impl_test.cc | 29 ++---------------------
 test/integration/integration_test.cc      |  9 -------
 3 files changed, 2 insertions(+), 39 deletions(-)

diff --git a/source/common/http/http1/balsa_parser.cc b/source/common/http/http1/balsa_parser.cc
index 7a354a8afe8c..33082e1b120f 100644
--- a/source/common/http/http1/balsa_parser.cc
+++ b/source/common/http/http1/balsa_parser.cc
@@ -153,10 +153,7 @@ BalsaParser::BalsaParser(MessageType type, ParserCallbacks* connection, size_t m
   http_validation_policy.require_header_colon = true;
   http_validation_policy.disallow_multiple_content_length = false;
   http_validation_policy.disallow_transfer_encoding_with_content_length = false;
-#ifdef ENVOY_ENABLE_UHV
-  // UHV - disable transfer-encoding validations in Balsa
   http_validation_policy.validate_transfer_encoding = false;
-#endif
   framer_.set_http_validation_policy(http_validation_policy);
 
   framer_.set_balsa_headers(&headers_);
diff --git a/test/common/http/http1/codec_impl_test.cc b/test/common/http/http1/codec_impl_test.cc
index c269f4513533..94d848188028 100644
--- a/test/common/http/http1/codec_impl_test.cc
+++ b/test/common/http/http1/codec_impl_test.cc
@@ -549,18 +549,8 @@ TEST_P(Http1ServerConnectionImplTest, UnsupportedEncoding) {
   EXPECT_CALL(callbacks_, newStream(_, _)).WillOnce(ReturnRef(decoder));
 
   Buffer::OwnedImpl buffer("GET / HTTP/1.1\r\nHost: host\r\ntransfer-encoding: gzip\r\n\r\n");
-#ifdef ENVOY_ENABLE_UHV
   EXPECT_CALL(decoder, sendLocalReply(Http::Code::NotImplemented, _, _, _,
                                       "http1.invalid_transfer_encoding"));
-#else
-  if (parser_impl_ == Http1ParserImpl::HttpParser) {
-    EXPECT_CALL(decoder, sendLocalReply(Http::Code::NotImplemented, _, _, _,
-                                        "http1.invalid_transfer_encoding"));
-  } else {
-    // TODO(#27375): Balsa codec produces invalid response in non UHV mode
-    EXPECT_CALL(decoder, sendLocalReply(Http::Code::BadRequest, _, _, _, "http1.codec_error"));
-  }
-#endif
   auto status = codec_->dispatch(buffer);
 #ifdef ENVOY_ENABLE_UHV
   EXPECT_TRUE(status.ok());
@@ -4542,18 +4532,8 @@ TEST_P(Http1ServerConnectionImplTest, MultipleTransferEncoding) {
         decoder.setResponseEncoder(&encoder);
         return decoder;
       }));
-#ifdef ENVOY_ENABLE_UHV
   EXPECT_CALL(decoder, sendLocalReply(Http::Code::NotImplemented, "Not Implemented", _, _,
                                       "http1.invalid_transfer_encoding"));
-#else
-  if (parser_impl_ == Http1ParserImpl::BalsaParser) {
-    EXPECT_CALL(decoder,
-                sendLocalReply(Http::Code::BadRequest, "Bad Request", _, _, "http1.codec_error"));
-  } else {
-    EXPECT_CALL(decoder, sendLocalReply(Http::Code::NotImplemented, "Not Implemented", _, _,
-                                        "http1.invalid_transfer_encoding"));
-  }
-#endif
   Buffer::OwnedImpl buffer("POST / HTTP/1.1\r\nHost: foo.bar\r\n"
                            "Transfer-Encoding: chunked\r\n"
                            "Transfer-Encoding: chunked\r\n"
@@ -4566,13 +4546,8 @@ TEST_P(Http1ServerConnectionImplTest, MultipleTransferEncoding) {
 #else
   EXPECT_TRUE(isCodecProtocolError(status));
 
-  if (parser_impl_ == Http1ParserImpl::BalsaParser) {
-    EXPECT_EQ("http1.codec_error", response_encoder->getStream().responseDetails());
-    EXPECT_EQ(status.message(), "http/1.1 protocol error: MULTIPLE_TRANSFER_ENCODING_KEYS");
-  } else {
-    EXPECT_EQ("http1.invalid_transfer_encoding", response_encoder->getStream().responseDetails());
-    EXPECT_EQ(status.message(), "http/1.1 protocol error: unsupported transfer encoding");
-  }
+  EXPECT_EQ("http1.invalid_transfer_encoding", response_encoder->getStream().responseDetails());
+  EXPECT_EQ(status.message(), "http/1.1 protocol error: unsupported transfer encoding");
 #endif
 }
 
diff --git a/test/integration/integration_test.cc b/test/integration/integration_test.cc
index 7c30ed707159..bd5d97d44422 100644
--- a/test/integration/integration_test.cc
+++ b/test/integration/integration_test.cc
@@ -924,16 +924,7 @@ TEST_P(IntegrationTest, TestInvalidTransferEncoding) {
   const std::string request = "GET / HTTP/1.1\r\nHost: host\r\ntransfer-encoding: "
                               "identity\r\ntransfer-encoding: chunked \r\n\r\n";
   sendRawHttpAndWaitForResponse(lookupPort("http"), request.c_str(), &response, false);
-#ifdef ENVOY_ENABLE_UHV
   EXPECT_THAT(response, StartsWith("HTTP/1.1 501 Not Implemented\r\n"));
-#else
-  if (http1_implementation_ == Http1ParserImpl::BalsaParser) {
-    // TODO(#27375): Balsa codec produces invalid response in non UHV mode
-    EXPECT_THAT(response, StartsWith("HTTP/1.1 400 Bad Request\r\n"));
-  } else {
-    EXPECT_THAT(response, StartsWith("HTTP/1.1 501 Not Implemented\r\n"));
-  }
-#endif
 }
 
 TEST_P(IntegrationTest, TestPipelinedResponses) {

From df778241161ee9077fadde47bfe8e018ad6a685b Mon Sep 17 00:00:00 2001
From: phlax 
Date: Thu, 8 Jun 2023 16:04:57 +0100
Subject: [PATCH 218/228] ci: Fix cache mount (#27778)

Signed-off-by: Ryan Northey 
---
 .azure-pipelines/bazel.yml               |  4 ++++
 .azure-pipelines/cached.yml              |  5 ++++-
 .azure-pipelines/docker/load_cache.sh    | 10 +++++++---
 .azure-pipelines/docker/prepare_cache.sh |  8 ++++++--
 .azure-pipelines/docker/save_cache.sh    |  9 +++++++--
 .azure-pipelines/stage/publish.yml       |  3 ++-
 6 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/.azure-pipelines/bazel.yml b/.azure-pipelines/bazel.yml
index 37c7d4735fd0..f0fc48dde0f1 100644
--- a/.azure-pipelines/bazel.yml
+++ b/.azure-pipelines/bazel.yml
@@ -24,6 +24,9 @@ parameters:
 - name: cacheKeyDockerTmpDir
   type: string
   default: /mnt/docker_cache
+- name: cacheKeyDockerNoTmpfs
+  type: string
+  default: ''
 - name: cacheKey
   type: string
   default: $(cacheKeyBazelFiles)
@@ -151,6 +154,7 @@ steps:
     name: "${{ parameters.cacheKeyDockerName }}"
     path: "${{ parameters.cacheKeyDockerPath }}"
     tmpDirectory: "${{ parameters.cacheKeyDockerTmpDir }}"
+    tmpNoTmpfs: "${{ parameters.cacheKeyDockerNoTmpfs }}"
     arch: "${{ parameters.artifactSuffix }}"
 
 - ${{ each step in parameters.stepsPre }}:
diff --git a/.azure-pipelines/cached.yml b/.azure-pipelines/cached.yml
index 591807fb063d..d75ef8b5771e 100644
--- a/.azure-pipelines/cached.yml
+++ b/.azure-pipelines/cached.yml
@@ -15,6 +15,9 @@ parameters:
 - name: tmpDirectory
   type: string
   default: /mnt/docker_cache
+- name: tmpNoTmpfs
+  type: string
+  default:
 - name: path
   type: string
   default: /mnt/docker
@@ -27,7 +30,7 @@ parameters:
 
 
 steps:
-- script: sudo .azure-pipelines/docker/prepare_cache.sh "${{ parameters.tmpDirectory }}"
+- script: sudo .azure-pipelines/docker/prepare_cache.sh "${{ parameters.tmpDirectory }}" "${{ parameters.tmpNoTmpfs }}"
   displayName: "Cache/prepare (${{ parameters.name }})"
 - task: Cache@2
   env:
diff --git a/.azure-pipelines/docker/load_cache.sh b/.azure-pipelines/docker/load_cache.sh
index ae2c486f806a..78c6cd8e5d99 100755
--- a/.azure-pipelines/docker/load_cache.sh
+++ b/.azure-pipelines/docker/load_cache.sh
@@ -43,9 +43,13 @@ fi
 echo "Starting Docker daemon ..."
 systemctl start docker
 
-echo "Unmount cache tmp ${DOCKER_CACHE_PATH} ..."
-umount "${DOCKER_CACHE_PATH}"
-
+if mountpoint -q "${DOCKER_CACHE_PATH}"; then
+    echo "Unmount cache tmp ${DOCKER_CACHE_PATH} ..."
+    umount "${DOCKER_CACHE_PATH}"
+else
+    echo "Remove cache tmp ${DOCKER_CACHE_PATH} ..."
+    rm -rf "${DOCKER_CACHE_PATH}"
+fi
 docker images
 df -h
 
diff --git a/.azure-pipelines/docker/prepare_cache.sh b/.azure-pipelines/docker/prepare_cache.sh
index 0cb4f0e55772..fe417d5f5e41 100755
--- a/.azure-pipelines/docker/prepare_cache.sh
+++ b/.azure-pipelines/docker/prepare_cache.sh
@@ -1,6 +1,7 @@
 #!/bin/bash -e
 
 DOCKER_CACHE_PATH="$1"
+NO_MOUNT_TMPFS="${2:-}"
 DOCKER_CACHE_OWNERSHIP="vsts:vsts"
 
 
@@ -13,7 +14,10 @@ if ! id -u vsts &> /dev/null; then
     DOCKER_CACHE_OWNERSHIP=azure-pipelines
 fi
 
-echo "Mounting tmpfs cache directory (${DOCKER_CACHE_PATH}) ..."
+echo "Creating cache directory (${DOCKER_CACHE_PATH}) ..."
 mkdir -p "${DOCKER_CACHE_PATH}"
-mount -t tmpfs none "${DOCKER_CACHE_PATH}"
+if [[ -z "$NO_MOUNT_TMPFS" ]]; then
+    echo "Mount tmpfs directory: ${DOCKER_CACHE_PATH}"
+    mount -t tmpfs none "$DOCKER_CACHE_PATH"
+fi
 chown -R "$DOCKER_CACHE_OWNERSHIP" "${DOCKER_CACHE_PATH}"
diff --git a/.azure-pipelines/docker/save_cache.sh b/.azure-pipelines/docker/save_cache.sh
index c21c6bad1db5..85f912cbad2d 100755
--- a/.azure-pipelines/docker/save_cache.sh
+++ b/.azure-pipelines/docker/save_cache.sh
@@ -1,6 +1,7 @@
 #!/bin/bash -e
 
 DOCKER_CACHE_PATH="$1"
+NO_MOUNT_TMPFS="${2:-}"
 
 if [[ -z "$DOCKER_CACHE_PATH" ]]; then
     echo "prime_docker_cache called without path arg" >&2
@@ -19,9 +20,13 @@ docker images
 echo "Stopping Docker ..."
 systemctl stop docker
 
-echo "Creating tmpfs directory to save tarball: ${DOCKER_CACHE_PATH}"
+echo "Creating directory to save tarball: ${DOCKER_CACHE_PATH}"
 mkdir -p "$DOCKER_CACHE_PATH"
-mount -t tmpfs none "$DOCKER_CACHE_PATH"
+
+if [[ -z "$NO_MOUNT_TMPFS" ]]; then
+    echo "Mount tmpfs directory: ${DOCKER_CACHE_PATH}"
+    mount -t tmpfs none "$DOCKER_CACHE_PATH"
+fi
 
 echo "Creating tarball: /var/lib/docker -> ${DOCKER_CACHE_TARBALL}"
 tar cf - -C /var/lib/docker . | zstd - -T0 -o "$DOCKER_CACHE_TARBALL"
diff --git a/.azure-pipelines/stage/publish.yml b/.azure-pipelines/stage/publish.yml
index beb715a6b46d..17101a5bc84f 100644
--- a/.azure-pipelines/stage/publish.yml
+++ b/.azure-pipelines/stage/publish.yml
@@ -122,6 +122,7 @@ jobs:
       cacheKeyDocker: "ci/Dockerfile-envoy | VERSION.txt| $(cacheKeyBazelFiles)"
       cacheKeyDockerName: publish_docker
       cacheKeyDockerTmpDir: /var/azpcache
+      cacheKeyDockerNoTmpfs: true
       cacheKeyDockerPath: ""
       cacheKeyDockerVersion: "$(cacheKeyDockerBuild)"
       env:
@@ -189,7 +190,7 @@ jobs:
           GCS_ARTIFACT_BUCKET: ${{ parameters.bucketGCP }}
           ENVOY_DOCKER_BUILD_DIR: $(Build.StagingDirectory)
           ENVOY_RBE: "1"
-      - script: sudo .azure-pipelines/docker/save_cache.sh /var/azpcache
+      - script: sudo .azure-pipelines/docker/save_cache.sh /var/azpcache true
         displayName: "Cache/save (publish_docker)"
 
 - job: package_x64

From d2adc854b6eabdc13844b5170478127969d16f24 Mon Sep 17 00:00:00 2001
From: phlax 
Date: Thu, 8 Jun 2023 16:05:15 +0100
Subject: [PATCH 219/228] deps: Bump toolshed github actions version (#27800)

Signed-off-by: Ryan Northey 
---
 .github/workflows/commands.yml          | 2 +-
 .github/workflows/envoy-sync.yml        | 2 +-
 .github/workflows/workflow-complete.yml | 2 +-
 .github/workflows/workflow-start.yml    | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml
index 35da322861f1..63af84c63af5 100644
--- a/.github/workflows/commands.yml
+++ b/.github/workflows/commands.yml
@@ -22,6 +22,6 @@ jobs:
       pull-requests: write
       actions: write
     steps:
-    - uses: envoyproxy/toolshed/gh-actions/retest@56d5781416445ed530e075b71546dedee94cf054
+    - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.0.1
       with:
         token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/envoy-sync.yml b/.github/workflows/envoy-sync.yml
index da65ccc55984..ce191989bf3a 100644
--- a/.github/workflows/envoy-sync.yml
+++ b/.github/workflows/envoy-sync.yml
@@ -20,7 +20,7 @@ jobs:
         - envoy-filter-example
         - data-plane-api
     steps:
-    - uses: envoyproxy/toolshed/gh-actions/dispatch@1f1feae1e372dde41ecc6830028989bb6037c480
+    - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.0.1
       with:
         repository: "envoyproxy/${{ matrix.downstream }}"
         ref: main
diff --git a/.github/workflows/workflow-complete.yml b/.github/workflows/workflow-complete.yml
index 8b0d7f8c98d1..7b6050b9d75a 100644
--- a/.github/workflows/workflow-complete.yml
+++ b/.github/workflows/workflow-complete.yml
@@ -52,7 +52,7 @@ jobs:
         echo "state=${STATE}" >> "$GITHUB_OUTPUT"
       id: job
     - name: Complete status check
-      uses: envoyproxy/toolshed/gh-actions/status@a6e1c951217efae1ac6b2bf32c5a9729976442b8
+      uses: envoyproxy/toolshed/gh-actions/status@actions-v0.0.1
       with:
         authToken: ${{ secrets.GITHUB_TOKEN }}
         context: ${{ github.event.workflow.name }}
diff --git a/.github/workflows/workflow-start.yml b/.github/workflows/workflow-start.yml
index 64c2999c1201..6b377a395e7a 100644
--- a/.github/workflows/workflow-start.yml
+++ b/.github/workflows/workflow-start.yml
@@ -19,7 +19,7 @@ jobs:
       statuses: write
     steps:
     - name: Start status check
-      uses: envoyproxy/toolshed/gh-actions/status@a6e1c951217efae1ac6b2bf32c5a9729976442b8
+      uses: envoyproxy/toolshed/gh-actions/status@actions-v0.0.1
       with:
         authToken: ${{ secrets.GITHUB_TOKEN }}
         context: ${{ inputs.workflowName }}

From cf1af7660d910c275bee1d7b34218c32c6419198 Mon Sep 17 00:00:00 2001
From: "Vikas Choudhary (vikasc)" 
Date: Thu, 8 Jun 2023 20:40:35 +0530
Subject: [PATCH 220/228] Update curl command in the tunneling examples
 (#27777)

* Update curl command in the tunneling examples

Signed-off-by: Vikas Choudhary 

* fix typo

Signed-off-by: Vikas Choudhary 

* add host header

Signed-off-by: Vikas Choudhary 

* nits

Signed-off-by: Vikas Choudhary 

---------

Signed-off-by: Vikas Choudhary 
---
 configs/encapsulate_http_in_http2_connect.yaml | 1 +
 configs/encapsulate_in_http1_connect.yaml      | 2 +-
 configs/encapsulate_in_http2_connect.yaml      | 2 +-
 configs/encapsulate_in_http2_post.yaml         | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/configs/encapsulate_http_in_http2_connect.yaml b/configs/encapsulate_http_in_http2_connect.yaml
index adbe66d1c3aa..d51724ae42f5 100644
--- a/configs/encapsulate_http_in_http2_connect.yaml
+++ b/configs/encapsulate_http_in_http2_connect.yaml
@@ -1,5 +1,6 @@
 # This configuration takes incoming HTTP requests on port 10000 and encapsulates it in a CONNECT
 # request which is sent upstream port 10001.
+# `curl -H 'Host: www.google.com' --resolve www.google.com:10000:127.0.0.1 https://www.google.com:10000`
 bootstrap_extensions:
 - name: envoy.bootstrap.internal_listener
   typed_config:
diff --git a/configs/encapsulate_in_http1_connect.yaml b/configs/encapsulate_in_http1_connect.yaml
index bc51e8c7cea1..4140cb6ccf9e 100644
--- a/configs/encapsulate_in_http1_connect.yaml
+++ b/configs/encapsulate_in_http1_connect.yaml
@@ -7,7 +7,7 @@
 # It can be used to test TCP tunneling as described in
 # https://envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/upgrades
 # and running `curl -x 127.0.0.1:10000 https://www.google.com`,
-# or running `curl -H "Host: the-hosted-domain-on-port-10003"  http://127.0.0.1:10002
+# or running `curl -H 'Host: www.google.com' --resolve www.google.com:10000:127.0.0.1 https://www.google.com:10000`
 
 admin:
   address:
diff --git a/configs/encapsulate_in_http2_connect.yaml b/configs/encapsulate_in_http2_connect.yaml
index 75a5d5fcd295..9346b75bb2f1 100644
--- a/configs/encapsulate_in_http2_connect.yaml
+++ b/configs/encapsulate_in_http2_connect.yaml
@@ -2,7 +2,7 @@
 # request which is sent upstream port 10001.
 # It can be used to test TCP tunneling as described in
 # https://envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/upgrades
-# and running `curl -x 127.0.0.1:10000 https://www.google.com`
+# and running `curl -H 'Host: www.google.com' --resolve www.google.com:10000:127.0.0.1 https://www.google.com:10000`
 
 admin:
   address:
diff --git a/configs/encapsulate_in_http2_post.yaml b/configs/encapsulate_in_http2_post.yaml
index d24737bbfdd4..55af299e1494 100644
--- a/configs/encapsulate_in_http2_post.yaml
+++ b/configs/encapsulate_in_http2_post.yaml
@@ -2,7 +2,7 @@
 # request which is sent upstream port 10001.
 # It can be used to test TCP tunneling as described in
 # https://envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/upgrades
-# and running `curl -x 127.0.0.1:10000 https://www.google.com`
+# and running `curl -H 'Host: www.google.com' --resolve www.google.com:10000:127.0.0.1 https://www.google.com:10000`
 
 admin:
   address:

From 75f7741c7af847cde4f54e31b9e612ca58cc4367 Mon Sep 17 00:00:00 2001
From: botengyao 
Date: Thu, 8 Jun 2023 12:49:39 -0400
Subject: [PATCH 221/228] hc: add more logs for tcp health checker (#27857)

add more logs for tcp health checker

Signed-off-by: Boteng Yao 
---
 .../health_checkers/tcp/health_checker_impl.cc      | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/source/extensions/health_checkers/tcp/health_checker_impl.cc b/source/extensions/health_checkers/tcp/health_checker_impl.cc
index 08a3fdde67fc..aefab127a1d2 100644
--- a/source/extensions/health_checkers/tcp/health_checker_impl.cc
+++ b/source/extensions/health_checkers/tcp/health_checker_impl.cc
@@ -69,12 +69,13 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onDeferredDelete() {
 }
 
 void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onData(Buffer::Instance& data) {
-  ENVOY_CONN_LOG(trace, "total pending buffer={}", *client_, data.length());
+  ENVOY_CONN_LOG(debug, "hc tcp total pending buffer={}", *client_, data.length());
   // TODO(lilika): The TCP health checker does generic pattern matching so we can't differentiate
   // between wrong data and not enough data. We could likely do better here and figure out cases in
   // which a match is not possible but that is not done now.
   if (PayloadMatcher::match(parent_.receive_bytes_, data)) {
-    ENVOY_CONN_LOG(trace, "healthcheck passed", *client_);
+    ENVOY_CONN_LOG(debug, "hc tcp healthcheck passed, health_check_address={}", *client_,
+                   host_->healthCheckAddress()->asString());
     data.drain(data.length());
     handleSuccess(false);
     if (!parent_.reuse_connection_) {
@@ -88,6 +89,8 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onEvent(Network::Connect
   if (event == Network::ConnectionEvent::RemoteClose ||
       event == Network::ConnectionEvent::LocalClose) {
     if (!expect_close_) {
+      ENVOY_CONN_LOG(debug, "hc tcp connection unexpected closed, health_check_address={}",
+                     *client_, host_->healthCheckAddress()->asString());
       handleFailure(envoy::data::core::v3::NETWORK);
     }
     parent_.dispatcher_.deferredDelete(std::move(client_));
@@ -108,7 +111,8 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onEvent(Network::Connect
     // TODO(mattklein123): In the case that a user configured bytes to write, they will not be
     // be written, since we currently have no way to know if the bytes actually get written via
     // the connection interface. We might want to figure out how to handle this better later.
-    ENVOY_CONN_LOG(trace, "healthcheck passed", *client_);
+    ENVOY_CONN_LOG(debug, "hc tcp healthcheck passed, health_check_address={}", *client_,
+                   host_->healthCheckAddress()->asString());
     expect_close_ = true;
     client_->close(Network::ConnectionCloseType::Abort);
     handleSuccess(false);
@@ -143,6 +147,9 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onInterval() {
 }
 
 void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onTimeout() {
+  ENVOY_CONN_LOG(debug, "hc tcp connection timeout, health_flags={}, health_check_address={}",
+                 *client_, HostUtility::healthFlagsToString(*host_),
+                 host_->healthCheckAddress()->asString());
   expect_close_ = true;
   client_->close(Network::ConnectionCloseType::Abort);
 }

From 285e0a4fc58ebd916745f02ce6a885a32f5f0754 Mon Sep 17 00:00:00 2001
From: Raven Black 
Date: Thu, 8 Jun 2023 12:24:07 -0700
Subject: [PATCH 222/228] Fix flaky race in file_system_http_cache_test
 (#27887)

Fix race in test

Signed-off-by: Raven Black 
---
 .../cache/file_system_http_cache/file_system_http_cache_test.cc  | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc
index b334411bf390..43cbcb94f5b7 100644
--- a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc
+++ b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc
@@ -568,6 +568,7 @@ TEST_F(FileSystemHttpCacheTestWithMockFiles, FailedReadOfHeaderBlockInvalidatesT
   // unlink
   mock_async_file_manager_->nextActionCompletes(absl::OkStatus());
   EXPECT_EQ(result.cache_entry_status_, CacheEntryStatus::Unusable);
+  waitForEvictionThreadIdle();
   // Should have deducted the size of the file that got deleted. Since we started at 2 * 12345,
   // this should make the value 12345.
   EXPECT_EQ(cache_->stats().size_bytes_.value(), 12345);

From 2b0b1869a864abcc9e6f0309f914bdabf58b4455 Mon Sep 17 00:00:00 2001
From: realtimetodie 
Date: Thu, 8 Jun 2023 21:32:32 +0200
Subject: [PATCH 223/228] filter: clear route cache in language filter (#27872)

Signed-off-by: shooj4aegohbaivo 
---
 .../filters/http/language/v3alpha/language.proto    |  5 +++++
 contrib/language/filters/http/source/config.cc      |  3 ++-
 .../language/filters/http/source/language_filter.cc | 13 +++++++++++--
 .../language/filters/http/source/language_filter.h  |  9 ++++++++-
 4 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/api/contrib/envoy/extensions/filters/http/language/v3alpha/language.proto b/api/contrib/envoy/extensions/filters/http/language/v3alpha/language.proto
index 7f45d5e6be9a..47f296707b21 100644
--- a/api/contrib/envoy/extensions/filters/http/language/v3alpha/language.proto
+++ b/api/contrib/envoy/extensions/filters/http/language/v3alpha/language.proto
@@ -33,4 +33,9 @@ message Language {
     unique: true
     items {string {min_len: 2}}
   }];
+
+  // If the x-language header is altered, clear the route cache for the current request.
+  // This should be set if the route configuration may depend on the x-language header.
+  // Otherwise it should be unset to avoid the performance cost of route recalculation.
+  bool clear_route_cache = 3;
 }
diff --git a/contrib/language/filters/http/source/config.cc b/contrib/language/filters/http/source/config.cc
index 0130bf0ff771..b4bf1bd6b908 100644
--- a/contrib/language/filters/http/source/config.cc
+++ b/contrib/language/filters/http/source/config.cc
@@ -55,7 +55,8 @@ Http::FilterFactoryCb LanguageFilterFactory::createFilterFactoryFromProtoTyped(
   }
 
   auto config = std::make_shared(
-      std::make_shared(default_locale), locale_matcher, stats_prefix, context.scope());
+      std::make_shared(default_locale), locale_matcher,
+      proto_config.clear_route_cache(), stats_prefix, context.scope());
 
   return [config](Http::FilterChainFactoryCallbacks& callbacks) -> void {
     auto filter = std::make_shared(config);
diff --git a/contrib/language/filters/http/source/language_filter.cc b/contrib/language/filters/http/source/language_filter.cc
index 5108dd28a960..647398a02ec2 100644
--- a/contrib/language/filters/http/source/language_filter.cc
+++ b/contrib/language/filters/http/source/language_filter.cc
@@ -31,9 +31,10 @@ bool validateHeaderValue(absl::string_view value_str) {
 
 LanguageFilterConfigImpl::LanguageFilterConfigImpl(
     const std::shared_ptr default_locale,
-    const std::shared_ptr locale_matcher, const std::string& stats_prefix,
-    Stats::Scope& scope)
+    const std::shared_ptr locale_matcher, const bool clear_route_cache,
+    const std::string& stats_prefix, Stats::Scope& scope)
     : default_locale_(std::move(default_locale)), locale_matcher_(std::move(locale_matcher)),
+      clear_route_cache_(clear_route_cache),
       stats_(LanguageFilter::generateStats(stats_prefix, scope)) {}
 
 const std::shared_ptr& LanguageFilterConfigImpl::defaultLocale() const {
@@ -44,6 +45,8 @@ const std::shared_ptr& LanguageFilterConfigImpl::localeMatch
   return locale_matcher_;
 }
 
+bool LanguageFilterConfigImpl::clearRouteCache() const { return clear_route_cache_; }
+
 LanguageStats& LanguageFilterConfigImpl::stats() { return stats_; }
 
 LanguageFilter::LanguageFilter(const LanguageFilterConfigSharedPtr config)
@@ -76,6 +79,12 @@ Http::FilterHeadersStatus LanguageFilter::decodeHeaders(Http::RequestHeaderMap&
         if (U_SUCCESS(errorCode)) {
           if (!language_tag.empty()) {
             request_headers.addCopy(Language, language_tag);
+
+            if (config_->clearRouteCache()) {
+              ENVOY_LOG(debug, "clearing route cache");
+              decoder_callbacks_->downstreamCallbacks()->clearRouteCache();
+            }
+
             config_->stats().header_.inc();
 
             return Http::FilterHeadersStatus::Continue;
diff --git a/contrib/language/filters/http/source/language_filter.h b/contrib/language/filters/http/source/language_filter.h
index 738ce9803bb5..b4cc1adbb478 100644
--- a/contrib/language/filters/http/source/language_filter.h
+++ b/contrib/language/filters/http/source/language_filter.h
@@ -41,6 +41,8 @@ class LanguageFilterConfig {
 
   virtual const std::shared_ptr& localeMatcher() const PURE;
 
+  virtual bool clearRouteCache() const PURE;
+
   virtual LanguageStats& stats() PURE;
 };
 
@@ -51,12 +53,15 @@ class LanguageFilterConfigImpl : public LanguageFilterConfig {
 public:
   LanguageFilterConfigImpl(const std::shared_ptr default_locale,
                            const std::shared_ptr locale_matcher,
-                           const std::string& stats_prefix, Stats::Scope& scope);
+                           const bool clear_route_cache, const std::string& stats_prefix,
+                           Stats::Scope& scope);
 
   const std::shared_ptr& defaultLocale() const override;
 
   const std::shared_ptr& localeMatcher() const override;
 
+  bool clearRouteCache() const override;
+
   LanguageStats& stats() override;
 
 private:
@@ -64,6 +69,8 @@ class LanguageFilterConfigImpl : public LanguageFilterConfig {
 
   const std::shared_ptr locale_matcher_;
 
+  const bool clear_route_cache_;
+
   LanguageStats stats_;
 };
 using LanguageFilterConfigSharedPtr = std::shared_ptr;

From 5e05a494c75aeb112661584975f4bd668cc923c6 Mon Sep 17 00:00:00 2001
From: Ali Beyad 
Date: Thu, 8 Jun 2023 16:17:30 -0400
Subject: [PATCH 224/228] test: Fix comment (#27884)

Signed-off-by: Ali Beyad 
---
 test/integration/base_integration_test.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/integration/base_integration_test.h b/test/integration/base_integration_test.h
index fddd40fbff4e..0f750483b4a6 100644
--- a/test/integration/base_integration_test.h
+++ b/test/integration/base_integration_test.h
@@ -531,7 +531,7 @@ class BaseIntegrationTest : protected Logger::Loggable {
 private:
   // Configuration for the fake upstream.
   FakeUpstreamConfig upstream_config_{time_system_};
-  // True if initialized() has been called.
+  // True if initialize() has been called.
   bool initialized_{};
   // Optional factory that the proxy-under-test should use to create watermark buffers. If nullptr,
   // the proxy uses the default watermark buffer factory to create buffers.

From b8e112190ef14bced0509a0fb201b5ee49da46d7 Mon Sep 17 00:00:00 2001
From: code 
Date: Fri, 9 Jun 2023 05:55:47 +0800
Subject: [PATCH 225/228] generic proxy: add new request matcher to simplify
 route table (#27785)

A new custom matcher for generic proxy is added to simplify the route table. When simple AND semantic is used, the users needn't write complex configuration to combine different input/match.

Risk Level: low.
Testing: unit.

Signed-off-by: wbpcode 
---
 .../generic_proxy/matcher/v3/matcher.proto    |   2 -
 .../filters/network/source/match.cc           |  88 +++++++++
 .../filters/network/source/match.h            |  84 +++++++++
 .../filters/network/test/match_test.cc        | 174 ++++++++++++++++++
 4 files changed, 346 insertions(+), 2 deletions(-)

diff --git a/api/contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3/matcher.proto b/api/contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3/matcher.proto
index 021d1f85346a..47dcc212f439 100644
--- a/api/contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3/matcher.proto
+++ b/api/contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3/matcher.proto
@@ -52,7 +52,6 @@ message PropertyMatchInput {
 message RequestMatchInput {
 }
 
-// [#not-implemented-hide:]
 // Used to match an arbitrary key-value pair for headers, trailers or properties.
 message KeyValueMatchEntry {
   // The key name to match on.
@@ -62,7 +61,6 @@ message KeyValueMatchEntry {
   type.matcher.v3.StringMatcher string_match = 2 [(validate.rules).message = {required: true}];
 }
 
-// [#not-implemented-hide:]
 // Custom matcher to match on the generic downstream request. This is used to match
 // multiple fields of the downstream request and avoid complex combinations of
 // HostMatchInput, PathMatchInput, MethodMatchInput and PropertyMatchInput.
diff --git a/contrib/generic_proxy/filters/network/source/match.cc b/contrib/generic_proxy/filters/network/source/match.cc
index 37ddc4bd15fa..83719c2b6c4d 100644
--- a/contrib/generic_proxy/filters/network/source/match.cc
+++ b/contrib/generic_proxy/filters/network/source/match.cc
@@ -15,6 +15,94 @@ REGISTER_FACTORY(MethodMatchDataInputFactory, Matcher::DataInputFactory
 
 REGISTER_FACTORY(PropertyMatchDataInputFactory, Matcher::DataInputFactory);
 
+REGISTER_FACTORY(RequestMatchDataInputFactory, Matcher::DataInputFactory);
+
+using StringMatcherImpl = Matchers::StringMatcherImpl;
+
+RequestMatchInputMatcher::RequestMatchInputMatcher(const RequestMatcherProto& proto_config) {
+
+  if (proto_config.has_host()) {
+    host_ = std::make_unique(proto_config.host());
+  }
+  if (proto_config.has_path()) {
+    path_ = std::make_unique(proto_config.path());
+  }
+  if (proto_config.has_method()) {
+    method_ = std::make_unique(proto_config.method());
+  }
+
+  for (const auto& property : proto_config.properties()) {
+    properties_.push_back(
+        {property.name(), std::make_unique(property.string_match())});
+  }
+}
+
+bool RequestMatchInputMatcher::match(const Matcher::MatchingDataType& input) {
+  if (!absl::holds_alternative>(input)) {
+    return false;
+  }
+
+  const auto* typed_data = dynamic_cast(
+      absl::get>(input).get());
+
+  if (typed_data == nullptr) {
+    return false;
+  }
+
+  return match(typed_data->request());
+}
+
+bool RequestMatchInputMatcher::match(const Request& request) {
+  // TODO(wbpcode): may add more debug log for request match?
+  if (host_ != nullptr) {
+    if (!host_->match(request.host())) {
+      // Host does not match.
+      return false;
+    }
+  }
+
+  if (path_ != nullptr) {
+    if (!path_->match(request.path())) {
+      // Path does not match.
+      return false;
+    }
+  }
+
+  if (method_ != nullptr) {
+    if (!method_->match(request.method())) {
+      // Method does not match.
+      return false;
+    }
+  }
+
+  for (const auto& property : properties_) {
+    if (auto val = request.getByKey(property.first); val.has_value()) {
+      if (!property.second->match(val.value())) {
+        // Property does not match.
+        return false;
+      }
+    } else {
+      // Property does not exist.
+      return false;
+    }
+  }
+
+  // All matchers passed.
+  return true;
+}
+
+Matcher::InputMatcherFactoryCb RequestMatchDataInputMatcherFactory::createInputMatcherFactoryCb(
+    const Protobuf::Message& config, Server::Configuration::ServerFactoryContext& factory_context) {
+  const auto& proto_config = MessageUtil::downcastAndValidate(
+      config, factory_context.messageValidationVisitor());
+
+  return [proto_config]() -> Matcher::InputMatcherPtr {
+    return std::make_unique(proto_config);
+  };
+}
+
+REGISTER_FACTORY(RequestMatchDataInputMatcherFactory, Matcher::InputMatcherFactory);
+
 } // namespace GenericProxy
 } // namespace NetworkFilters
 } // namespace Extensions
diff --git a/contrib/generic_proxy/filters/network/source/match.h b/contrib/generic_proxy/filters/network/source/match.h
index d339f4c54ef5..447e44a4a7c6 100644
--- a/contrib/generic_proxy/filters/network/source/match.h
+++ b/contrib/generic_proxy/filters/network/source/match.h
@@ -24,6 +24,16 @@ using MethodDataInputProto =
     envoy::extensions::filters::network::generic_proxy::matcher::v3::MethodMatchInput;
 using PropertyDataInputProto =
     envoy::extensions::filters::network::generic_proxy::matcher::v3::PropertyMatchInput;
+using RequestInputProto =
+    envoy::extensions::filters::network::generic_proxy::matcher::v3::RequestMatchInput;
+using RequestMatcherProto =
+    envoy::extensions::filters::network::generic_proxy::matcher::v3::RequestMatcher;
+using StringMatcherProto = envoy::type::matcher::v3::StringMatcher;
+
+// Fully qualified name of the generic proxy request match data type to avoid any possible
+// collision with other match data types.
+inline constexpr absl::string_view GenericRequestMatcheInputType =
+    "Envoy::Extensions::NetworkFilters::GenericProxy::RequestMatchData";
 
 class ServiceMatchDataInput : public Matcher::DataInput {
 public:
@@ -158,6 +168,80 @@ class PropertyMatchDataInputFactory : public Matcher::DataInputFactory
   std::string name() const override { return "envoy.matching.generic_proxy.input.property"; }
 };
 
+// RequestMatchData is a wrapper of Request to be used as the matching data type.
+class RequestMatchData : public Matcher::CustomMatchData {
+public:
+  RequestMatchData(const Request& data) : data_(data) {}
+
+  const Request& request() const { return data_; }
+
+private:
+  const Request& data_;
+};
+
+class RequestMatchDataInput : public Matcher::DataInput {
+public:
+  RequestMatchDataInput() = default;
+
+  Matcher::DataInputGetResult get(const Request& data) const override {
+    auto request = std::make_shared(data);
+    return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable,
+            Matcher::MatchingDataType{std::move(request)}};
+  }
+
+  absl::string_view dataInputType() const override { return GenericRequestMatcheInputType; }
+};
+
+class RequestMatchDataInputFactory : public Matcher::DataInputFactory {
+public:
+  RequestMatchDataInputFactory() = default;
+
+  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
+    return std::make_unique();
+  }
+
+  Matcher::DataInputFactoryCb
+  createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override {
+    return []() { return std::make_unique(); };
+  }
+
+  std::string name() const override { return "envoy.matching.generic_proxy.input.request"; }
+};
+
+class RequestMatchInputMatcher : public Matcher::InputMatcher {
+public:
+  RequestMatchInputMatcher(const RequestMatcherProto& config);
+
+  bool match(const Matcher::MatchingDataType& input) override;
+
+  bool match(const Request& request);
+
+  absl::flat_hash_set supportedDataInputTypes() const override {
+    return absl::flat_hash_set{std::string(GenericRequestMatcheInputType)};
+  }
+
+private:
+  Matchers::StringMatcherPtr host_;
+  Matchers::StringMatcherPtr path_;
+  Matchers::StringMatcherPtr method_;
+  std::vector> properties_;
+};
+
+class RequestMatchDataInputMatcherFactory : public Matcher::InputMatcherFactory {
+public:
+  Matcher::InputMatcherFactoryCb createInputMatcherFactoryCb(
+      const Protobuf::Message& config,
+      Server::Configuration::ServerFactoryContext& factory_context) override;
+
+  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
+    return std::make_unique();
+  }
+
+  std::string name() const override {
+    return "envoy.matching.input_matchers.generic_request_matcher";
+  }
+};
+
 } // namespace GenericProxy
 } // namespace NetworkFilters
 } // namespace Extensions
diff --git a/contrib/generic_proxy/filters/network/test/match_test.cc b/contrib/generic_proxy/filters/network/test/match_test.cc
index 447810ad13dd..e2daf8a0d55d 100644
--- a/contrib/generic_proxy/filters/network/test/match_test.cc
+++ b/contrib/generic_proxy/filters/network/test/match_test.cc
@@ -1,3 +1,5 @@
+#include 
+
 #include "test/mocks/server/factory_context.h"
 
 #include "contrib/generic_proxy/filters/network/source/match.h"
@@ -97,6 +99,178 @@ TEST(PropertyMatchDataInputTest, PropertyMatchDataInputTest) {
   EXPECT_EQ("value_0", absl::get(input->get(request).data_));
 }
 
+TEST(RequestMatchDataInputTest, RequestMatchDataInputTest) {
+  NiceMock factory_context;
+  RequestMatchDataInputFactory factory;
+  auto proto_config = factory.createEmptyConfigProto();
+  auto input =
+      factory.createDataInputFactoryCb(*proto_config, factory_context.messageValidationVisitor())();
+
+  FakeStreamCodecFactory::FakeRequest request;
+
+  EXPECT_EQ(
+      &request,
+      &dynamic_cast(
+           absl::get>(input->get(request).data_).get())
+           ->request());
+}
+
+TEST(RequestMatchInputMatcherTest, RequestMatchInputMatcherTest) {
+  NiceMock factory_context;
+  RequestMatchDataInputMatcherFactory factory;
+  auto proto_config = factory.createEmptyConfigProto();
+  auto matcher = factory.createInputMatcherFactoryCb(*proto_config,
+                                                     factory_context.getServerFactoryContext())();
+
+  {
+    Matcher::MatchingDataType input;
+    EXPECT_FALSE(matcher->match(input));
+  }
+
+  {
+    Matcher::MatchingDataType input = std::string("fake_data");
+    EXPECT_FALSE(matcher->match(input));
+  }
+
+  {
+    FakeStreamCodecFactory::FakeRequest request;
+    Matcher::MatchingDataType input = std::make_shared(request);
+    EXPECT_TRUE(matcher->match(input));
+  }
+}
+
+TEST(RequestMatchInputMatcherTest, SpecificRequestMatchInputMatcherTest) {
+  // Empty matcher.
+  {
+    RequestMatcherProto matcher_proto;
+    RequestMatchInputMatcher matcher(matcher_proto);
+
+    FakeStreamCodecFactory::FakeRequest request;
+    EXPECT_TRUE(matcher.match(request));
+  }
+
+  // Host match failed.
+  {
+    RequestMatcherProto matcher_proto;
+
+    const std::string config_yaml = R"EOF(
+    host:
+      exact: fake_host
+    )EOF";
+
+    TestUtility::loadFromYaml(config_yaml, matcher_proto);
+
+    RequestMatchInputMatcher matcher(matcher_proto);
+
+    FakeStreamCodecFactory::FakeRequest request;
+    request.host_ = "another_fake_host";
+    EXPECT_FALSE(matcher.match(request));
+  }
+
+  // Path match failed.
+  {
+    RequestMatcherProto matcher_proto;
+
+    const std::string config_yaml = R"EOF(
+    host:
+      exact: fake_host
+    path:
+      exact: fake_path
+    )EOF";
+
+    TestUtility::loadFromYaml(config_yaml, matcher_proto);
+
+    RequestMatchInputMatcher matcher(matcher_proto);
+
+    FakeStreamCodecFactory::FakeRequest request;
+    request.host_ = "fake_host";
+    request.path_ = "another_fake_path";
+    EXPECT_FALSE(matcher.match(request));
+  }
+
+  // Method match failed.
+  {
+    RequestMatcherProto matcher_proto;
+
+    const std::string config_yaml = R"EOF(
+    host:
+      exact: fake_host
+    path:
+      exact: fake_path
+    method:
+      exact: fake_method
+    )EOF";
+
+    TestUtility::loadFromYaml(config_yaml, matcher_proto);
+
+    RequestMatchInputMatcher matcher(matcher_proto);
+
+    FakeStreamCodecFactory::FakeRequest request;
+    request.host_ = "fake_host";
+    request.path_ = "fake_path";
+    request.method_ = "another_fake_method";
+    EXPECT_FALSE(matcher.match(request));
+  }
+
+  // Property match failed.
+  {
+    RequestMatcherProto matcher_proto;
+
+    const std::string config_yaml = R"EOF(
+    host:
+      exact: fake_host
+    path:
+      exact: fake_path
+    method:
+      exact: fake_method
+    properties:
+      - name: key_0
+        string_match:
+          exact: value_0
+    )EOF";
+
+    TestUtility::loadFromYaml(config_yaml, matcher_proto);
+
+    RequestMatchInputMatcher matcher(matcher_proto);
+
+    FakeStreamCodecFactory::FakeRequest request;
+    request.host_ = "fake_host";
+    request.path_ = "fake_path";
+    request.method_ = "fake_method";
+    request.data_["key_0"] = "another_value_0";
+    EXPECT_FALSE(matcher.match(request));
+  }
+
+  // All match.
+  {
+    RequestMatcherProto matcher_proto;
+
+    const std::string config_yaml = R"EOF(
+    host:
+      exact: fake_host
+    path:
+      exact: fake_path
+    method:
+      exact: fake_method
+    properties:
+      - name: key_0
+        string_match:
+          exact: value_0
+    )EOF";
+
+    TestUtility::loadFromYaml(config_yaml, matcher_proto);
+
+    RequestMatchInputMatcher matcher(matcher_proto);
+
+    FakeStreamCodecFactory::FakeRequest request;
+    request.host_ = "fake_host";
+    request.path_ = "fake_path";
+    request.method_ = "fake_method";
+    request.data_["key_0"] = "value_0";
+    EXPECT_TRUE(matcher.match(request));
+  }
+}
+
 } // namespace
 } // namespace GenericProxy
 } // namespace NetworkFilters

From ddc50bb6b07269ba499a93af77d85e141d534882 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 9 Jun 2023 07:40:04 -0700
Subject: [PATCH 226/228] build(deps): bump urllib3 from 2.0.2 to 2.0.3 in
 /mobile/docs (#27893)

Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.0.2...2.0.3)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 mobile/docs/requirements.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mobile/docs/requirements.txt b/mobile/docs/requirements.txt
index a5feef288926..e1cec53555c7 100644
--- a/mobile/docs/requirements.txt
+++ b/mobile/docs/requirements.txt
@@ -197,6 +197,6 @@ sphinxcontrib-qthelp==1.0.3 \
 sphinxcontrib-serializinghtml==1.1.5 \
     --hash=sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd \
     --hash=sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952
-urllib3==2.0.2 \
-    --hash=sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc \
-    --hash=sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e
+urllib3==2.0.3 \
+    --hash=sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1 \
+    --hash=sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825

From 52cfd445ffe20110c5c75dbc8aa00f8edb82864d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 9 Jun 2023 07:40:47 -0700
Subject: [PATCH 227/228] build(deps): bump jaegertracing/all-in-one from
 `12e96c7` to `3703087` in /examples/shared/jaeger (#27894)

build(deps): bump jaegertracing/all-in-one in /examples/shared/jaeger

Bumps jaegertracing/all-in-one from `12e96c7` to `3703087`.

---
updated-dependencies:
- dependency-name: jaegertracing/all-in-one
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] 
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 examples/shared/jaeger/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/shared/jaeger/Dockerfile b/examples/shared/jaeger/Dockerfile
index 5c671c6b6cad..27d9f94cafcf 100644
--- a/examples/shared/jaeger/Dockerfile
+++ b/examples/shared/jaeger/Dockerfile
@@ -1,4 +1,4 @@
-FROM jaegertracing/all-in-one@sha256:12e96c7396d758da7d300d162f2aab899c2f6cc51e037cc7bced8dbd6d3cfc5d
+FROM jaegertracing/all-in-one@sha256:37030876f8e4d42ed793c545b9420afebc46d9fb303affcec46c4b60b97e3c4a
 HEALTHCHECK \
     --interval=1s \
     --timeout=1s \

From de3ae4a6e996ef7e6356c62b44990a6cf01e3a1c Mon Sep 17 00:00:00 2001
From: jaychenatr <54647402+jaychenatr@users.noreply.github.com>
Date: Fri, 9 Jun 2023 12:43:45 -0500
Subject: [PATCH 228/228] api-csds: Propose a boolean field in
 ClientStatusRequest to indicate whether xds server should exclude detailed
 config(xds_config field in GenericXdsConfig) but keep the rest of fields in
 response (#27880)

Signed-off-by: jaychenatr 
---
 api/envoy/service/status/v3/csds.proto | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/api/envoy/service/status/v3/csds.proto b/api/envoy/service/status/v3/csds.proto
index 74b7005190d8..b764f1cc3a4f 100644
--- a/api/envoy/service/status/v3/csds.proto
+++ b/api/envoy/service/status/v3/csds.proto
@@ -85,6 +85,11 @@ message ClientStatusRequest {
 
   // The node making the csds request.
   config.core.v3.Node node = 2;
+
+  // If true, the server will not include the resource contents in the response
+  // (i.e., the generic_xds_configs.xds_config field will not be populated).
+  // [#not-implemented-hide:]
+  bool exclude_resource_contents = 3;
 }
 
 // Detailed config (per xDS) with status.