diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index d4454b618ba3..8f80098026a6 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -64,9 +64,6 @@ parameters: displayName: "Upload bazel run data to BES" type: boolean default: true -- name: envoyBuildFilterExample - type: string - default: "" - name: cacheTestResults displayName: "Cache test results" type: boolean @@ -224,7 +221,6 @@ steps: echo "##vso[task.setvariable variable=BAZEL_FAKE_SCM_REVISION]${BAZEL_FAKE_SCM_REVISION}" echo "##vso[task.setvariable variable=BAZEL_STARTUP_EXTRA_OPTIONS]${{ parameters.bazelStartupExtraOptions }}" echo "##vso[task.setvariable variable=CI_TARGET_BRANCH]${CI_TARGET_BRANCH}" - echo "##vso[task.setvariable variable=ENVOY_BUILD_FILTER_EXAMPLE]${{ parameters.envoyBuildFilterExample }}" echo "##vso[task.setvariable variable=ENVOY_DOCKER_BUILD_DIR]$(Build.StagingDirectory)" echo "##vso[task.setvariable variable=ENVOY_RBE]${ENVOY_RBE}" echo "##vso[task.setvariable variable=ENVOY_SHARED_TMP_DIR]${ENVOY_SHARED_TMP_DIR}" @@ -275,7 +271,6 @@ steps: - script: ci/run_envoy_docker.sh 'ci/do_ci.sh ${{ parameters.ciTarget }}' workingDirectory: $(Build.SourcesDirectory) env: - ENVOY_BUILD_FILTER_EXAMPLE: ${{ parameters.envoyBuildFilterExample }} ${{ each var in parameters.env }}: ${{ var.key }}: ${{ var.value }} displayName: "Run CI script ${{ parameters.ciTarget }}" diff --git a/.azure-pipelines/stage/checks.yml b/.azure-pipelines/stage/checks.yml index b4e650287a23..c5d7e22f58e2 100644 --- a/.azure-pipelines/stage/checks.yml +++ b/.azure-pipelines/stage/checks.yml @@ -47,12 +47,10 @@ jobs: CI_TARGET: "fuzz_coverage" compile_time_options: CI_TARGET: "compile_time_options" - ENVOY_FILTER_EXAMPLE: true tsan: CI_TARGET: "tsan" asan: CI_TARGET: "asan" - ENVOY_FILTER_EXAMPLE: true # Disabled due to https://github.com/envoyproxy/envoy/pull/18218 # api_compat: # CI_TARGET: "api_compat" @@ -60,7 +58,6 @@ jobs: CI_TARGET: "gcc" msan: CI_TARGET: "msan" - ENVOY_FILTER_EXAMPLE: true # # Temporarily disabled to facilitate release CI, should be resolved # as part of https://github.com/envoyproxy/envoy/issues/28566 @@ -81,7 +78,6 @@ jobs: parameters: ciTarget: $(CI_TARGET) cacheName: $(CI_TARGET) - envoyBuildFilterExample: $(ENVOY_FILTER_EXAMPLE) cacheTestResults: ${{ parameters.cacheTestResults }} diskspaceHack: true managedAgent: false diff --git a/.bazelrc b/.bazelrc index fdf86fa2a91b..0b7b3b892115 100644 --- a/.bazelrc +++ b/.bazelrc @@ -272,8 +272,7 @@ build:rbe-toolchain-clang-libc++ --action_env=CXXFLAGS=-stdlib=libc++ build:rbe-toolchain-clang-libc++ --action_env=LDFLAGS=-stdlib=libc++ build:rbe-toolchain-clang-libc++ --define force_libcpp=enabled -# Do not inherit from "clang-asan" to avoid picking up flags from local clang.bazelrc. -build:rbe-toolchain-asan --config=asan +build:rbe-toolchain-asan --config=clang-asan build:rbe-toolchain-asan --linkopt -fuse-ld=lld build:rbe-toolchain-asan --action_env=ENVOY_UBSAN_VPTR=1 build:rbe-toolchain-asan --copt=-fsanitize=vptr,function diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 29bf47cb5683..af8a14f0b4f2 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -54,13 +54,18 @@ jobs: cd bin/clang14 wget https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz tar -xf clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz --strip-components 1 - export PATH=bin/clang14/bin:$PATH - name: Build run: | bazel/setup_clang.sh bin/clang14 bazelisk shutdown - bazelisk build -c fastbuild --spawn_strategy=local --discard_analysis_cache --nouse_action_cache --config clang --config libc++ \ + bazel build \ + -c fastbuild \ + --spawn_strategy=local \ + --discard_analysis_cache \ + --nouse_action_cache \ + --config=clang-libc++ \ + --config=ci \ //source/common/http/... - name: Clean Artifacts diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index db6aa77f37a5..b2b1209cc0ed 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -85,7 +85,6 @@ jobs: cd bin/clang14 wget https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz tar -xf clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz --strip-components 1 - export PATH=bin/clang14/bin:$PATH - name: Build if: ${{ env.BUILD_TARGETS != '' }} @@ -97,8 +96,8 @@ jobs: --spawn_strategy=local \ --discard_analysis_cache \ --nouse_action_cache \ - --config clang \ - --config libc++ \ + --config=clang-libc++ \ + --config=ci \ $BUILD_TARGETS echo -e "Built targets...\n$BUILD_TARGETS" diff --git a/CODEOWNERS b/CODEOWNERS index 3a4a6091bc07..b5eab51e164a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -142,6 +142,7 @@ extensions/filters/common/original_src @klarose @mattklein123 /*/extensions/resource_monitors/common @eziskind @yanavlasov @nezdolik /*/extensions/resource_monitors/fixed_heap @eziskind @yanavlasov @nezdolik /*/extensions/resource_monitors/downstream_connections @nezdolik @mattklein123 +/*/extensions/resource_monitors/cpu_utilization @cancecen @kbaichoo /*/extensions/retry/priority @alyssawilk @mattklein123 /*/extensions/retry/priority/previous_priorities @alyssawilk @mattklein123 /*/extensions/retry/host @alyssawilk @mattklein123 diff --git a/README.md b/README.md index f2f383d5f001..7d323eb59ef3 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,13 @@ have prior experience. To get started: ## Community Meeting -The Envoy team meets twice per month on Tuesday at 9am PT. The public -Google calendar is here: https://goo.gl/PkDijT - -* Meeting minutes are [here](https://goo.gl/5Cergb) -* Recorded videos are posted [here](https://www.youtube.com/channel/UC5z5mvPgqMs1xo5VuIWzYTA) +The Envoy team has a scheduled meeting time twice per month on Tuesday at 9am PT. The public +Google calendar is [here](https://goo.gl/PkDijT). The meeting will only be held +if there are agenda items listed in the [meeting +minutes](https://goo.gl/5Cergb). Any member of the community should be able to +propose agenda items by adding to the minutes. The maintainers will either confirm +the additions to the agenda, or will cancel the meeting within 24 hours of the scheduled +date if there is no confirmed agenda. ## Security diff --git a/api/BUILD b/api/BUILD index 1fdfbcd1d0a0..12dafa02ee24 100644 --- a/api/BUILD +++ b/api/BUILD @@ -311,6 +311,7 @@ proto_library( "//envoy/extensions/rbac/matchers/upstream_ip_port/v3:pkg", "//envoy/extensions/regex_engines/v3:pkg", "//envoy/extensions/request_id/uuid/v3:pkg", + "//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg", "//envoy/extensions/resource_monitors/downstream_connections/v3:pkg", "//envoy/extensions/resource_monitors/fixed_heap/v3:pkg", "//envoy/extensions/resource_monitors/injected_resource/v3:pkg", diff --git a/api/envoy/extensions/resource_monitors/cpu_utilization/v3/BUILD b/api/envoy/extensions/resource_monitors/cpu_utilization/v3/BUILD new file mode 100644 index 000000000000..29ebf0741406 --- /dev/null +++ b/api/envoy/extensions/resource_monitors/cpu_utilization/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_xds//udpa/annotations:pkg"], +) diff --git a/api/envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.proto b/api/envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.proto new file mode 100644 index 000000000000..a8362e7b8d05 --- /dev/null +++ b/api/envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package envoy.extensions.resource_monitors.cpu_utilization.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.resource_monitors.cpu_utilization.v3"; +option java_outer_classname = "CpuUtilizationProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/cpu_utilization/v3;cpu_utilizationv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: CPU utilization] +// [#extension: envoy.resource_monitors.cpu_utilization] + +// The CPU utilization resource monitor reports the Envoy process the CPU Utilization of the entire host. +// Today, this only works on Linux and is calculated using the stats in the /proc/stat file. +message CpuUtilizationConfig { +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 98e2ec21f881..bfc572f7f3bd 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -250,6 +250,7 @@ proto_library( "//envoy/extensions/rbac/matchers/upstream_ip_port/v3:pkg", "//envoy/extensions/regex_engines/v3:pkg", "//envoy/extensions/request_id/uuid/v3:pkg", + "//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg", "//envoy/extensions/resource_monitors/downstream_connections/v3:pkg", "//envoy/extensions/resource_monitors/fixed_heap/v3:pkg", "//envoy/extensions/resource_monitors/injected_resource/v3:pkg", diff --git a/bazel/setup_clang.sh b/bazel/setup_clang.sh index 1b49ad94861d..ba17049fd060 100755 --- a/bazel/setup_clang.sh +++ b/bazel/setup_clang.sh @@ -15,11 +15,14 @@ fi LLVM_VERSION="$("${LLVM_CONFIG}" --version)" LLVM_LIBDIR="$("${LLVM_CONFIG}" --libdir)" LLVM_TARGET="$("${LLVM_CONFIG}" --host-target)" +PATH="$("${LLVM_CONFIG}" --bindir):${PATH}" RT_LIBRARY_PATH="${LLVM_LIBDIR}/clang/${LLVM_VERSION}/lib/${LLVM_TARGET}" cat < "${BAZELRC_FILE}" # Generated file, do not edit. If you want to disable clang, just delete this file. +build:clang --host_action_env=PATH=${PATH} --action_env=PATH=${PATH} + build:clang --action_env=LLVM_CONFIG=${LLVM_CONFIG} --host_action_env=LLVM_CONFIG=${LLVM_CONFIG} build:clang --repo_env=LLVM_CONFIG=${LLVM_CONFIG} build:clang --linkopt=-L${LLVM_LIBDIR} diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 1e13de922ca3..003cb25533f0 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -128,6 +128,11 @@ bug_fixes: the number of requests per I/O cycle is configured and an HTTP decoder filter that pauses filter chain is present. This behavior can be reverted by setting the runtime guard ``envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream`` to false. +- area: runtime + change: | + Fixed an inconsistency in how boolean values are loaded in RTDS, where they were previously converted to "1"/"0" + instead of "true"/"false". The correct string representation ("true"/"false") will now be used. This change can be + reverted by setting the runtime guard ``envoy.reloadable_features.boolean_to_string_fix`` to false. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` @@ -230,6 +235,11 @@ new_features: Added socket ``type`` field for specifying a socket type to apply the socket option to under :ref:`SocketOption `. If not specified, the socket option will be applied to all socket types. +- area: quic + change: | + QUIC server and client support certificate compression, which can in some cases reduce the number of round trips + required to setup a connection. This change temporarily disabled by setting the runtime flag + ``envoy.reloadable_features.quic_support_certificate_compression`` to ``false``. - area: tls change: | Added an extension point :ref:`custom_tls_certificate_selector @@ -307,6 +317,10 @@ new_features: change: | The :ref:`xff ` original IP detection method now supports using a list of trusted CIDRs when parsing ``x-forwarded-for``. +- area: resource_monitors + change: | + Added possibility to monitor CPU utilization in Linux based systems via :ref:`cpu utilization monitor + ` in overload manager. - area: lua change: | Added two new methods ``oidsPeerCertificate()`` and ``oidsLocalCertificate()`` to SSL diff --git a/ci/build_setup.sh b/ci/build_setup.sh index abdbea03859b..1ef213757975 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -33,8 +33,6 @@ fi export ENVOY_BUILD_ARCH } -export ENVOY_BUILD_FILTER_EXAMPLE="${ENVOY_BUILD_FILTER_EXAMPLE:-0}" - read -ra BAZEL_BUILD_EXTRA_OPTIONS <<< "${BAZEL_BUILD_EXTRA_OPTIONS:-}" read -ra BAZEL_EXTRA_TEST_OPTIONS <<< "${BAZEL_EXTRA_TEST_OPTIONS:-}" read -ra BAZEL_STARTUP_EXTRA_OPTIONS <<< "${BAZEL_STARTUP_EXTRA_OPTIONS:-}" @@ -119,10 +117,12 @@ export BAZEL_STARTUP_OPTION_LIST export BAZEL_BUILD_OPTION_LIST export BAZEL_GLOBAL_OPTION_LIST -if [[ -e "${LLVM_ROOT}" ]]; then - "${CURRENT_SCRIPT_DIR}/../bazel/setup_clang.sh" "${LLVM_ROOT}" -else - echo "LLVM_ROOT not found, not setting up llvm." +if [[ -z "${ENVOY_RBE}" ]]; then + if [[ -e "${LLVM_ROOT}" ]]; then + "${CURRENT_SCRIPT_DIR}/../bazel/setup_clang.sh" "${LLVM_ROOT}" + else + echo "LLVM_ROOT not found, not setting up llvm." + fi fi [[ "${BAZEL_EXPUNGE}" == "1" ]] && bazel clean "${BAZEL_BUILD_OPTIONS[@]}" --expunge @@ -155,11 +155,4 @@ mkdir -p "${ENVOY_FAILED_TEST_LOGS}" export ENVOY_BUILD_PROFILE="${ENVOY_BUILD_DIR}"/generated/build-profile mkdir -p "${ENVOY_BUILD_PROFILE}" -if [[ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "true" ]]; then - # shellcheck source=ci/filter_example_setup.sh - . "${CURRENT_SCRIPT_DIR}"/filter_example_setup.sh -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 43aa3f7a1ffd..2581a479c299 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -351,22 +351,19 @@ case $CI_TARGET in asan) setup_clang_toolchain + if [[ -n "$ENVOY_RBE" ]]; then + ASAN_CONFIG="--config=rbe-toolchain-asan" + else + ASAN_CONFIG="--config=clang-asan" + fi BAZEL_BUILD_OPTIONS+=( -c dbg - "--config=clang-asan" + "${ASAN_CONFIG}" "--build_tests_only" "--remote_download_minimal") echo "bazel ASAN/UBSAN debug build with tests" echo "Building and testing envoy tests ${TEST_TARGETS[*]}" bazel_with_collection test "${BAZEL_BUILD_OPTIONS[@]}" "${TEST_TARGETS[@]}" - if [ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "1" ]; then - echo "Building and testing envoy-filter-example tests..." - pushd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" - bazel_with_collection \ - test "${BAZEL_BUILD_OPTIONS[@]}" \ - "${ENVOY_FILTER_EXAMPLE_TESTS[@]}" - popd - fi # TODO(mattklein123): This part of the test is now flaky in CI and it's unclear why, possibly # due to sandboxing issue. Debug and enable it again. # if [ "${CI_SKIP_INTEGRATION_TEST_TRAFFIC_TAPPING}" != "1" ] ; then @@ -424,7 +421,6 @@ case $CI_TARGET in setup_clang_toolchain # This doesn't go into CI but is available for developer convenience. echo "bazel with different compiletime options build with tests..." - cd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" TEST_TARGETS=("${TEST_TARGETS[@]/#\/\//@envoy\/\/}") # Building all the dependencies from scratch to link them against libc++. echo "Building and testing with wasm=wamr: ${TEST_TARGETS[*]}" @@ -972,16 +968,6 @@ case $CI_TARGET in --build_tests_only \ --remote_download_minimal \ "${TEST_TARGETS[@]}" - if [ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "1" ]; then - echo "Building and testing envoy-filter-example tests..." - pushd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" - bazel_with_collection \ - test "${BAZEL_BUILD_OPTIONS[@]}" \ - -c dbg \ - --config=clang-tsan \ - "${ENVOY_FILTER_EXAMPLE_TESTS[@]}" - popd - fi ;; verify_distro) diff --git a/ci/filter_example_setup.sh b/ci/filter_example_setup.sh index be529e6f82d9..e2d6e1b434a9 100644 --- a/ci/filter_example_setup.sh +++ b/ci/filter_example_setup.sh @@ -29,6 +29,6 @@ cp -a "${ENVOY_SRCDIR}"/bazel/protoc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/bazel/ cp -f "${ENVOY_SRCDIR}"/.bazelrc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ rm -f "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/.bazelversion cp -f "${ENVOY_SRCDIR}"/.bazelversion "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ -cp -f "${ENVOY_SRCDIR}"/*.bazelrc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ +cp -f "${ENVOY_SRCDIR}"/*.bazelrc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ || : export FILTER_WORKSPACE_SET=1 diff --git a/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc b/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc index dc3415b4236f..305f2db8ed71 100644 --- a/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc +++ b/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc @@ -35,7 +35,7 @@ ClientSslAuthConfig::ClientSslAuthConfig( std::chrono::milliseconds(1000)), tls_(tls.allocateSlot()), stats_(generateStats(scope, config.stat_prefix())) { auto list_or_error = Network::Address::IpList::create(config.ip_white_list()); - THROW_IF_STATUS_NOT_OK(list_or_error, throw); + THROW_IF_NOT_OK_REF(list_or_error.status()); ip_allowlist_ = std::move(list_or_error.value()); if (!cm.clusters().hasCluster(remote_cluster_name_)) { diff --git a/contrib/golang/filters/http/source/golang_filter.cc b/contrib/golang/filters/http/source/golang_filter.cc index fa4a6ef35fa6..226a6656ec6f 100644 --- a/contrib/golang/filters/http/source/golang_filter.cc +++ b/contrib/golang/filters/http/source/golang_filter.cc @@ -19,6 +19,7 @@ #include "source/common/grpc/status.h" #include "source/common/http/headers.h" #include "source/common/http/http1/codec_impl.h" +#include "source/common/http/utility.h" #include "source/common/router/string_accessor_impl.h" #include "source/extensions/filters/common/expr/context.h" @@ -1377,16 +1378,13 @@ uint64_t Filter::getMergedConfigId() { Http::StreamFilterCallbacks* callbacks = decoding_state_.getFilterCallbacks(); // get all of the per route config - std::list route_config_list; - callbacks->traversePerFilterConfig( - [&route_config_list](const Router::RouteSpecificFilterConfig& cfg) { - route_config_list.push_back(dynamic_cast(&cfg)); - }); + auto route_config_list = Http::Utility::getAllPerFilterConfig(callbacks); ENVOY_LOG(debug, "golang filter route config list length: {}.", route_config_list.size()); auto id = config_->getConfigId(); for (auto it : route_config_list) { + ASSERT(it != nullptr, "route config should not be null"); auto route_config = *it; id = route_config.getPluginConfigId(id, config_->pluginName()); } diff --git a/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc b/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc index 95b77c071d5a..e9c0eca313f4 100644 --- a/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc +++ b/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc @@ -204,7 +204,7 @@ ClientPtr traClient(Event::Dispatcher& dispatcher, Server::Configuration::Factor .clusterManager() .grpcAsyncClientManager() .getOrCreateRawAsyncClient(grpc_service, context.scope(), true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); return std::make_unique( client_or_error.value(), dispatcher, timeout); } diff --git a/docs/root/configuration/http/http_filters/original_src_filter.rst b/docs/root/configuration/http/http_filters/original_src_filter.rst index 232f45a40a0c..b703ec0e3ab1 100644 --- a/docs/root/configuration/http/http_filters/original_src_filter.rst +++ b/docs/root/configuration/http/http_filters/original_src_filter.rst @@ -70,7 +70,7 @@ The following example configures Envoy to use the original source for all connec http_filters: - name: envoy.filters.http.original_src typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.listener.original_src.v3.OriginalSrc + "@type": type.googleapis.com/envoy.extensions.filters.http.original_src.v3.OriginalSrc mark: 123 - name: envoy.filters.http.router typed_config: diff --git a/docs/root/configuration/operations/overload_manager/_include/cpu_utilization_monitor_overload.yaml b/docs/root/configuration/operations/overload_manager/_include/cpu_utilization_monitor_overload.yaml new file mode 100644 index 000000000000..fa8ce6e18a8f --- /dev/null +++ b/docs/root/configuration/operations/overload_manager/_include/cpu_utilization_monitor_overload.yaml @@ -0,0 +1,55 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 8000 + 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 + stat_prefix: ingress_http + http_filters: + - name: envoy.filters.http.router + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - domains: + - '*' + name: local_service + routes: + - match: {prefix: "/"} + route: {cluster: default_service} + clusters: + - name: default_service + load_assignment: + cluster_name: default_service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10001 +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9901 + +overload_manager: + refresh_interval: 0.25s + resource_monitors: + - name: "envoy.resource_monitors.cpu_utilization" + typed_config: + "@type": type.googleapis.com/envoy.extensions.resource_monitors.cpu_utilization.v3.CpuUtilizationConfig + actions: + - name: "envoy.overload_actions.stop_accepting_requests" + triggers: + - name: "envoy.resource_monitors.cpu_utilization" + scaled: + scaling_threshold: 0.80 + saturation_threshold: 0.95 diff --git a/docs/root/configuration/operations/overload_manager/overload_manager.rst b/docs/root/configuration/operations/overload_manager/overload_manager.rst index 9b66b0d0b047..682e74b302a3 100644 --- a/docs/root/configuration/operations/overload_manager/overload_manager.rst +++ b/docs/root/configuration/operations/overload_manager/overload_manager.rst @@ -353,6 +353,28 @@ It's expected that the first few gradations shouldn't trigger anything, unless there's something seriously wrong e.g. in this example streams using ``>= 128MiB`` in buffers. +CPU Intensive Workload Brownout Protection +------------------------------------------ + +The ``envoy.overload_actions.stop_accepting_requests`` overload action can be used +to protect workloads from browning-out when an unexpected spike in the number of +requests the workload receives that causes the CPU to become saturated. This overload +action when used in conjunction with the ``envoy.resource_monitors.cpu_utilization`` +resource monitor can reduce the pressure on the CPU by cheaply rejecting new requests. +While the real mitigation for such request spikes are horizantally scaling the workload, +this overload action can be used to ensure the fleet does not get into a cascading failure +mode. +Some platform owners may choose to install this overload action by default to protect the fleet, +since it is easier to configure a target CPU utilization percentage than to configure a request rate per +workload. + +.. literalinclude:: _include/cpu_utilization_monitor_overload.yaml + :language: yaml + :lines: 43-55 + :emphasize-lines: 3-13 + :linenos: + :caption: :download:`cpu_utilization_monitor_overload.yaml <_include/cpu_utilization_monitor_overload.yaml>` + Statistics ---------- @@ -388,4 +410,3 @@ with the following statistics: scale_percent, Gauge, "Scaled value of the action as a percent (0-99=scaling, 100=saturated)" shed_load_count, Counter, "Total count the load is sheded" - diff --git a/docs/root/start/install.rst b/docs/root/start/install.rst index a04b04ff2c22..88a621a86fd1 100644 --- a/docs/root/start/install.rst +++ b/docs/root/start/install.rst @@ -10,54 +10,44 @@ If you are :ref:`installing on Mac OSX `, you can install Once you have installed Envoy, check out the :ref:`quick start ` guide for more information on getting your Envoy proxy up and running. -Install Envoy on Debian GNU/Linux -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can `install Envoy on Debian using packages created by Tetrate `_ -until `official packages exist `_. - -.. code-block:: console - - $ sudo apt update - $ sudo apt install debian-keyring debian-archive-keyring apt-transport-https curl lsb-release - $ curl -sL 'https://deb.dl.getenvoy.io/public/gpg.8115BA8E629CC074.key' | sudo gpg --dearmor -o /usr/share/keyrings/getenvoy-keyring.gpg - # Verify the keyring - this should yield "OK" - $ echo a077cb587a1b622e03aa4bf2f3689de14658a9497a9af2c427bba5f4cc3c4723 /usr/share/keyrings/getenvoy-keyring.gpg | sha256sum --check - $ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/getenvoy-keyring.gpg] https://deb.dl.getenvoy.io/public/deb/debian $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/getenvoy.list - $ sudo apt update - $ sudo apt install getenvoy-envoy - -Install Envoy on Ubuntu Linux -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can `install Envoy on Ubuntu using packages created by Tetrate `_ -until `official packages exist `_. - -.. code-block:: console - - $ sudo apt update - $ sudo apt install apt-transport-https gnupg2 curl lsb-release - $ curl -sL 'https://deb.dl.getenvoy.io/public/gpg.8115BA8E629CC074.key' | sudo gpg --dearmor -o /usr/share/keyrings/getenvoy-keyring.gpg - # Verify the keyring - this should yield "OK" - $ echo a077cb587a1b622e03aa4bf2f3689de14658a9497a9af2c427bba5f4cc3c4723 /usr/share/keyrings/getenvoy-keyring.gpg | sha256sum --check - $ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/getenvoy-keyring.gpg] https://deb.dl.getenvoy.io/public/deb/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/getenvoy.list - $ sudo apt update - $ sudo apt install -y getenvoy-envoy - -Install Envoy on RPM-based distros -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can install Envoy on Centos/Redhat Enterprise Linux (RHEL) using `packages created by Tetrate `_ -until `official packages exist `_. - -.. code-block:: console - - $ sudo yum install yum-utils - $ sudo rpm --import 'https://rpm.dl.getenvoy.io/public/gpg.CF716AF503183491.key' - $ curl -sL 'https://rpm.dl.getenvoy.io/public/config.rpm.txt?distro=el&codename=7' > /tmp/tetrate-getenvoy-rpm-stable.repo - $ sudo yum-config-manager --add-repo '/tmp/tetrate-getenvoy-rpm-stable.repo' - $ sudo yum makecache --disablerepo='*' --enablerepo='tetrate-getenvoy-rpm-stable' - $ sudo yum install getenvoy-envoy +Install Envoy on Debian-based Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + If you are using a different deb-based distribution to the ones shown below, you may still be able to use one of them. + +.. tabs:: + + .. code-tab:: console Debian bookworm + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bookworm main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version + + .. code-tab:: console Debian bullseye + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version + + .. code-tab:: console Ubuntu focal + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version + + .. code-tab:: console Ubuntu jammy + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io jammy main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version .. _start_install_macosx: diff --git a/envoy/common/exception.h b/envoy/common/exception.h index 0688b440dfbc..5734df1f6628 100644 --- a/envoy/common/exception.h +++ b/envoy/common/exception.h @@ -42,21 +42,14 @@ class EnvoyException : public std::runtime_error { } \ } while (0) +// Simple macro to handle bridging functions which return absl::StatusOr, and +// functions which throw errors. #define THROW_IF_NOT_OK(status_fn) \ do { \ const absl::Status status = (status_fn); \ THROW_IF_NOT_OK_REF(status); \ } while (0) -// Simple macro to handle bridging functions which return absl::StatusOr, and -// functions which throw errors. -// -// The completely unnecessary throw_action argument was just so 'throw' appears -// at the call site, so format checks about use of exceptions would be triggered. -// This didn't work, so the variable is no longer used and is not duplicated in -// the macros above. -#define THROW_IF_STATUS_NOT_OK(variable, throw_action) THROW_IF_NOT_OK_REF(variable.status()); - #define RETURN_IF_NOT_OK_REF(variable) \ if (const absl::Status& temp_status = variable; !temp_status.ok()) { \ return temp_status; \ @@ -69,7 +62,7 @@ class EnvoyException : public std::runtime_error { } template Type returnOrThrow(absl::StatusOr type_or_error) { - THROW_IF_STATUS_NOT_OK(type_or_error, throw); + THROW_IF_NOT_OK_REF(type_or_error.status()); return std::move(type_or_error.value()); } diff --git a/envoy/http/filter.h b/envoy/http/filter.h index f9cc5450c87b..749c5b0a4078 100644 --- a/envoy/http/filter.h +++ b/envoy/http/filter.h @@ -463,13 +463,11 @@ class StreamFilterCallbacks { virtual const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const PURE; /** - * Find all the available per route filter configs, invoking the callback with each config (if - * it is present). Iteration of the configs is in order of specificity. That means that the - * callback will be called first for a config on a Virtual host, then a route, and finally a route - * entry (weighted cluster). If a config is not present, the callback will not be invoked. + * Return all the available per route filter configs. The configs is in order of specificity. + * That means that the config from a route configuration will be first, then the config from a + * virtual host, then the config from a route. */ - virtual void traversePerFilterConfig( - std::function cb) const PURE; + virtual Router::RouteSpecificFilterConfigs perFilterConfigs() const PURE; /** * Return the HTTP/1 stream encoder options if applicable. If the stream is not HTTP/1 returns diff --git a/envoy/router/router.h b/envoy/router/router.h index 48ed169bcd40..09632aa82a0f 100644 --- a/envoy/router/router.h +++ b/envoy/router/router.h @@ -122,6 +122,7 @@ class RouteSpecificFilterConfig { virtual ~RouteSpecificFilterConfig() = default; }; using RouteSpecificFilterConfigConstSharedPtr = std::shared_ptr; +using RouteSpecificFilterConfigs = absl::InlinedVector; /** * CorsPolicy for Route and VirtualHost. @@ -686,18 +687,14 @@ class VirtualHost { * hierarchy (Route --> VirtualHost --> RouteConfiguration). Or nullptr if none of them exist. */ virtual const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const PURE; + mostSpecificPerFilterConfig(absl::string_view name) const PURE; /** - * Find all the available per route filter configs, invoking the callback with - * each config (if it is present). Iteration of the configs is in order of - * specificity. That means that the callback will be called first for a config on - * a route configuration, virtual host, route, and finally a route entry (weighted cluster). If - * a config is not present, the callback will not be invoked. + * Return all the available per route filter configs. The configs is in order of specificity. + * That means that the config from a route configuration will be first, then the config from a + * virtual host, then the config from a route. */ - virtual void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const PURE; + virtual Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view name) const PURE; /** * @return const envoy::config::core::v3::Metadata& return the metadata provided in the config for @@ -1248,17 +1245,14 @@ class Route { * hierarchy(Route --> VirtualHost --> RouteConfiguration). Or nullptr if none of them exist. */ virtual const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const PURE; + mostSpecificPerFilterConfig(absl::string_view name) const PURE; /** - * Find all the available per route filter configs, invoking the callback with each config (if - * it is present). Iteration of the configs is in order of specificity. That means that the - * callback will be called first for a config on a Virtual host, then a route, and finally a route - * entry (weighted cluster). If a config is not present, the callback will not be invoked. + * Return all the available per route filter configs. The configs is in order of specificity. + * That means that the config from a route configuration will be first, then the config from a + * virtual host, then the config from a route. */ - virtual void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const PURE; + virtual Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view name) const PURE; /** * @return const envoy::config::core::v3::Metadata& return the metadata provided in the config for diff --git a/mobile/test/swift/integration/CancelGRPCStreamTest.swift b/mobile/test/swift/integration/CancelGRPCStreamTest.swift index b878490af6ff..6b35c002f08c 100644 --- a/mobile/test/swift/integration/CancelGRPCStreamTest.swift +++ b/mobile/test/swift/integration/CancelGRPCStreamTest.swift @@ -11,6 +11,13 @@ final class CancelGRPCStreamTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testCancelGRPCStream() { let filterName = "cancel_validation_filter" diff --git a/mobile/test/swift/integration/CancelStreamTest.swift b/mobile/test/swift/integration/CancelStreamTest.swift index e6dd2dec4e16..a53f165b2c4b 100644 --- a/mobile/test/swift/integration/CancelStreamTest.swift +++ b/mobile/test/swift/integration/CancelStreamTest.swift @@ -11,6 +11,13 @@ final class CancelStreamTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testCancelStream() { let filterName = "cancel_validation_filter" diff --git a/mobile/test/swift/integration/EndToEndNetworkingTest.swift b/mobile/test/swift/integration/EndToEndNetworkingTest.swift index 18c1e5684e62..638eefc62333 100644 --- a/mobile/test/swift/integration/EndToEndNetworkingTest.swift +++ b/mobile/test/swift/integration/EndToEndNetworkingTest.swift @@ -10,6 +10,13 @@ final class EndToEndNetworkingTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testNetworkRequestReturnsHeadersAndData() { EnvoyTestServer.startHttp1PlaintextServer() EnvoyTestServer.setHeadersAndData( diff --git a/mobile/test/swift/integration/EngineApiTest.swift b/mobile/test/swift/integration/EngineApiTest.swift index 669269526817..22c8a5b68868 100644 --- a/mobile/test/swift/integration/EngineApiTest.swift +++ b/mobile/test/swift/integration/EngineApiTest.swift @@ -9,6 +9,13 @@ final class EngineApiTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testEngineApis() throws { let engineExpectation = self.expectation(description: "Engine Running") diff --git a/mobile/test/swift/integration/FilterResetIdleTest.swift b/mobile/test/swift/integration/FilterResetIdleTest.swift index b9ed4755ba9f..da7f5a528829 100644 --- a/mobile/test/swift/integration/FilterResetIdleTest.swift +++ b/mobile/test/swift/integration/FilterResetIdleTest.swift @@ -11,6 +11,13 @@ final class FilterResetIdleTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testFilterResetIdle() { let filterName = "reset_idle_test_filter" diff --git a/mobile/test/swift/integration/GRPCReceiveErrorTest.swift b/mobile/test/swift/integration/GRPCReceiveErrorTest.swift index 6713b185eb8b..a1266db281c7 100644 --- a/mobile/test/swift/integration/GRPCReceiveErrorTest.swift +++ b/mobile/test/swift/integration/GRPCReceiveErrorTest.swift @@ -11,6 +11,13 @@ final class GRPCReceiveErrorTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testReceiveError() { let filterName = "error_validation_filter" diff --git a/mobile/test/swift/integration/IdleTimeoutTest.swift b/mobile/test/swift/integration/IdleTimeoutTest.swift index 4f3d18440f28..95324f9195cd 100644 --- a/mobile/test/swift/integration/IdleTimeoutTest.swift +++ b/mobile/test/swift/integration/IdleTimeoutTest.swift @@ -11,6 +11,13 @@ final class IdleTimeoutTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testIdleTimeout() { let filterName = "reset_idle_test_filter" diff --git a/mobile/test/swift/integration/KeyValueStoreTest.swift b/mobile/test/swift/integration/KeyValueStoreTest.swift index b33204b2c52b..595bae134513 100644 --- a/mobile/test/swift/integration/KeyValueStoreTest.swift +++ b/mobile/test/swift/integration/KeyValueStoreTest.swift @@ -11,6 +11,13 @@ final class KeyValueStoreTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testKeyValueStore() { // swiftlint:disable:next line_length let kvStoreType = "type.googleapis.com/envoymobile.extensions.filters.http.test_kv_store.TestKeyValueStore" diff --git a/mobile/test/swift/integration/ReceiveDataTest.swift b/mobile/test/swift/integration/ReceiveDataTest.swift index 2e2855535508..483c947e7261 100644 --- a/mobile/test/swift/integration/ReceiveDataTest.swift +++ b/mobile/test/swift/integration/ReceiveDataTest.swift @@ -11,6 +11,13 @@ final class ReceiveDataTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testReceiveData() { let directResponseBody = "response_body" EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/ReceiveErrorTest.swift b/mobile/test/swift/integration/ReceiveErrorTest.swift index 24d9a2b0b194..cb8b408adcc6 100644 --- a/mobile/test/swift/integration/ReceiveErrorTest.swift +++ b/mobile/test/swift/integration/ReceiveErrorTest.swift @@ -10,6 +10,13 @@ final class ReceiveErrorTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testReceiveError() { let filterName = "error_validation_filter" @@ -59,9 +66,6 @@ final class ReceiveErrorTests: XCTestCase { .setLogger { _, msg in print(msg, terminator: "") } - .setLogger { _, msg in - print(msg, terminator: "") - } .addPlatformFilter( name: filterName, factory: { diff --git a/mobile/test/swift/integration/ResetConnectivityStateTest.swift b/mobile/test/swift/integration/ResetConnectivityStateTest.swift index e0c260feb690..ddeb5bb0590e 100644 --- a/mobile/test/swift/integration/ResetConnectivityStateTest.swift +++ b/mobile/test/swift/integration/ResetConnectivityStateTest.swift @@ -11,6 +11,13 @@ final class ResetConnectivityStateTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testResetConnectivityState() { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SendDataTest.swift b/mobile/test/swift/integration/SendDataTest.swift index 25c096e61a94..4a7b736b6f1a 100644 --- a/mobile/test/swift/integration/SendDataTest.swift +++ b/mobile/test/swift/integration/SendDataTest.swift @@ -11,6 +11,13 @@ final class SendDataTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSendData() throws { EnvoyTestServer.startHttp1PlaintextServer() EnvoyTestServer.setHeadersAndData("x-response-foo", header_value: "aaa", response_body: "data") diff --git a/mobile/test/swift/integration/SendHeadersTest.swift b/mobile/test/swift/integration/SendHeadersTest.swift index 6b5bc67fce73..46de840b92ef 100644 --- a/mobile/test/swift/integration/SendHeadersTest.swift +++ b/mobile/test/swift/integration/SendHeadersTest.swift @@ -11,6 +11,13 @@ final class SendHeadersTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSendHeaders() { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SendTrailersTest.swift b/mobile/test/swift/integration/SendTrailersTest.swift index e557756c0edb..5f1caa7a2404 100644 --- a/mobile/test/swift/integration/SendTrailersTest.swift +++ b/mobile/test/swift/integration/SendTrailersTest.swift @@ -11,6 +11,13 @@ final class SendTrailersTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSendTrailers() throws { // swiftlint:disable:next line_length let assertionFilterType = "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion" diff --git a/mobile/test/swift/integration/SetEventTrackerTest.swift b/mobile/test/swift/integration/SetEventTrackerTest.swift index a13e0ddfed56..beec655a1717 100644 --- a/mobile/test/swift/integration/SetEventTrackerTest.swift +++ b/mobile/test/swift/integration/SetEventTrackerTest.swift @@ -11,6 +11,13 @@ final class SetEventTrackerTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSetEventTracker() throws { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift b/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift index 78449f41f1e0..33f5035191e0 100644 --- a/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift +++ b/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift @@ -11,6 +11,13 @@ final class SetEventTrackerTestNoTracker: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testEmitEventWithoutSettingEventTracker() throws { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SetLoggerTest.swift b/mobile/test/swift/integration/SetLoggerTest.swift index afe3a8a1654c..96836ebf9dd0 100644 --- a/mobile/test/swift/integration/SetLoggerTest.swift +++ b/mobile/test/swift/integration/SetLoggerTest.swift @@ -11,6 +11,13 @@ final class LoggerTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSetLogger() throws { let engineExpectation = self.expectation(description: "Run started engine") let loggingExpectation = self.expectation(description: "Run used platform logger") @@ -24,16 +31,14 @@ final class LoggerTests: XCTestCase { .setLogLevel(.debug) .setLogger { _, msg in print(msg, terminator: "") + if msg.contains("starting main dispatch loop") { + loggingExpectation.fulfill() + } } .addNativeFilter( name: "test_logger", // swiftlint:disable:next line_length typedConfig: "[type.googleapis.com/envoymobile.extensions.filters.http.test_logger.TestLogger]{}") - .setLogger { _, msg in - if msg.contains("starting main dispatch loop") { - loggingExpectation.fulfill() - } - } .setOnEngineRunning { engineExpectation.fulfill() } diff --git a/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift b/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift index da80194d2ff3..67f3e215bb3f 100644 --- a/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift +++ b/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift @@ -12,6 +12,13 @@ final class HTTPRequestUsingProxyTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + private func executeRequest(engine: Engine, scheme: String, authority: String) -> String? { let responseHeadersExpectation = self.expectation(description: "Successful response headers received") diff --git a/source/common/buffer/BUILD b/source/common/buffer/BUILD index 0545b3b1558d..8236df805fdb 100644 --- a/source/common/buffer/BUILD +++ b/source/common/buffer/BUILD @@ -46,7 +46,6 @@ envoy_cc_library( envoy_cc_library( name = "buffer_util_lib", - srcs = ["buffer_util.cc"], hdrs = ["buffer_util.h"], deps = [ "//envoy/buffer:buffer_interface", diff --git a/source/common/buffer/buffer_util.cc b/source/common/buffer/buffer_util.cc deleted file mode 100644 index 849549714527..000000000000 --- a/source/common/buffer/buffer_util.cc +++ /dev/null @@ -1,45 +0,0 @@ -#include "source/common/buffer/buffer_util.h" - -#include -#include - -#include "source/common/common/macros.h" - -namespace Envoy { -namespace Buffer { - -void Util::serializeDouble(double number, Buffer::Instance& buffer) { - // Converting a double to a string: who would think it would be so complex? - // It's easy if you don't care about speed or accuracy :). Here we are measuring - // the speed with test/server/admin/stats_handler_speed_test --benchmark_filter=BM_HistogramsJson - // Here are some options: - // * absl::StrCat(number) -- fast (19ms on speed test) but loses precision (drops decimals). - // * absl::StrFormat("%.15g") -- works great but a bit slow (24ms on speed test) - // * `snprintf`(buf, sizeof(buf), "%.15g", ...) -- works but slow as molasses: 30ms. - // * fmt::format("{}") -- works great and is a little faster than absl::StrFormat: 21ms. - // * fmt::to_string -- works great and is a little faster than fmt::format: 19ms. - // * std::to_chars -- fast (16ms) and precise, but requires a few lines to - // generate the string_view, and does not work on all platforms yet. - // - // The accuracy is checked in buffer_util_test. -#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 14000 - // This version is awkward, and doesn't work on all platforms used in Envoy CI - // as of August 2023, but it is the fastest correct option on modern compilers. - char buf[100]; - std::to_chars_result result = std::to_chars(buf, buf + sizeof(buf), number); - ENVOY_BUG(result.ec == std::errc{}, std::make_error_code(result.ec).message()); - buffer.addFragments({absl::string_view(buf, result.ptr - buf)}); - - // Note: there is room to speed this up further by serializing the number directly - // into the buffer. However, buffer does not currently make it easy and fast - // to get (say) 100 characters of raw buffer to serialize into. -#else - // On older compilers, such as those found on Apple, and gcc, std::to_chars - // does not work with 'double', so we revert to the next fastest correct - // implementation. - buffer.addFragments({fmt::to_string(number)}); -#endif -} - -} // namespace Buffer -} // namespace Envoy diff --git a/source/common/buffer/buffer_util.h b/source/common/buffer/buffer_util.h index 9e8227fa1238..7a8e3aef3c07 100644 --- a/source/common/buffer/buffer_util.h +++ b/source/common/buffer/buffer_util.h @@ -1,7 +1,12 @@ #pragma once +#include +#include + #include "envoy/buffer/buffer.h" +#include "source/common/common/macros.h" + namespace Envoy { namespace Buffer { @@ -20,7 +25,38 @@ class Util { * @param number the number to convert. * @param buffer the buffer in which to write the double. */ - static void serializeDouble(double number, Buffer::Instance& buffer); + template static void serializeDouble(double number, Output& buffer) { + // Converting a double to a string: who would think it would be so complex? + // It's easy if you don't care about speed or accuracy :). Here we are measuring + // the speed with test/server/admin/stats_handler_speed_test + // --benchmark_filter=BM_HistogramsJson Here are some options: + // * absl::StrCat(number) -- fast (19ms on speed test) but loses precision (drops decimals). + // * absl::StrFormat("%.15g") -- works great but a bit slow (24ms on speed test) + // * `snprintf`(buf, sizeof(buf), "%.15g", ...) -- works but slow as molasses: 30ms. + // * fmt::format("{}") -- works great and is a little faster than absl::StrFormat: 21ms. + // * fmt::to_string -- works great and is a little faster than fmt::format: 19ms. + // * std::to_chars -- fast (16ms) and precise, but requires a few lines to + // generate the string_view, and does not work on all platforms yet. + // + // The accuracy is checked in buffer_util_test. +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 14000 + // This version is awkward, and doesn't work on all platforms used in Envoy CI + // as of August 2023, but it is the fastest correct option on modern compilers. + char buf[100]; + std::to_chars_result result = std::to_chars(buf, buf + sizeof(buf), number); + ENVOY_BUG(result.ec == std::errc{}, std::make_error_code(result.ec).message()); + buffer.add(absl::string_view(buf, result.ptr - buf)); + + // Note: there is room to speed this up further by serializing the number directly + // into the buffer. However, buffer does not currently make it easy and fast + // to get (say) 100 characters of raw buffer to serialize into. +#else + // On older compilers, such as those found on Apple, and gcc, std::to_chars + // does not work with 'double', so we revert to the next fastest correct + // implementation. + buffer.add(fmt::to_string(number)); +#endif + } }; } // namespace Buffer diff --git a/source/common/common/logger_delegates.cc b/source/common/common/logger_delegates.cc index cf3874d6a654..52975cd22129 100644 --- a/source/common/common/logger_delegates.cc +++ b/source/common/common/logger_delegates.cc @@ -15,7 +15,7 @@ FileSinkDelegate::FileSinkDelegate(const std::string& log_path, : SinkDelegate(log_sink) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, log_path}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); log_file_ = file_or_error.value(); setDelegate(); } diff --git a/source/common/formatter/http_specific_formatter.cc b/source/common/formatter/http_specific_formatter.cc index a46c9559c9f5..ab668bb60ac2 100644 --- a/source/common/formatter/http_specific_formatter.cc +++ b/source/common/formatter/http_specific_formatter.cc @@ -300,7 +300,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, @@ -308,7 +308,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, @@ -316,7 +316,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, @@ -364,7 +364,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h index efbceb7e93d7..e0dc6562b37e 100644 --- a/source/common/http/async_client_impl.h +++ b/source/common/http/async_client_impl.h @@ -257,8 +257,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const override { return nullptr; } - void traversePerFilterConfig( - std::function) const override {} + Router::RouteSpecificFilterConfigs perFilterConfigs() const override { return {}; } Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override { return {}; } OptRef downstreamCallbacks() override { return {}; } OptRef upstreamCallbacks() override { return {}; } diff --git a/source/common/http/filter_manager.cc b/source/common/http/filter_manager.cc index be2c9b7af44f..35066ddb8806 100644 --- a/source/common/http/filter_manager.cc +++ b/source/common/http/filter_manager.cc @@ -284,16 +284,13 @@ ActiveStreamFilterBase::mostSpecificPerFilterConfig() const { return current_route->mostSpecificPerFilterConfig(filter_context_.config_name); } -void ActiveStreamFilterBase::traversePerFilterConfig( - std::function cb) const { +Router::RouteSpecificFilterConfigs ActiveStreamFilterBase::perFilterConfigs() const { Router::RouteConstSharedPtr current_route = getRoute(); if (current_route == nullptr) { - return; + return {}; } - current_route->traversePerFilterConfig( - filter_context_.config_name, - [&cb](const Router::RouteSpecificFilterConfig& config) { cb(config); }); + return current_route->perFilterConfigs(filter_context_.config_name); } Http1StreamEncoderOptionsOptRef ActiveStreamFilterBase::http1StreamEncoderOptions() { diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index 82405f0cc4b2..105168585190 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -64,12 +64,9 @@ class LocalReplyOwnerObject : public StreamInfo::FilterState::Object { */ struct ActiveStreamFilterBase : public virtual StreamFilterCallbacks, Logger::Loggable { - ActiveStreamFilterBase(FilterManager& parent, bool is_encoder_decoder_filter, - FilterContext filter_context) + ActiveStreamFilterBase(FilterManager& parent, FilterContext filter_context) : parent_(parent), iteration_state_(IterationState::Continue), - filter_context_(std::move(filter_context)), iterate_from_current_filter_(false), - headers_continued_(false), continued_1xx_headers_(false), end_stream_(false), - is_encoder_decoder_filter_(is_encoder_decoder_filter), processed_headers_(false) {} + filter_context_(std::move(filter_context)) {} // Functions in the following block are called after the filter finishes processing // corresponding data. Those functions handle state updates and data storage (if needed) @@ -119,8 +116,7 @@ struct ActiveStreamFilterBase : public virtual StreamFilterCallbacks, void restoreContextOnContinue(ScopeTrackedObjectStack& tracked_object_stack) override; void resetIdleTimer() override; const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const override; - void traversePerFilterConfig( - std::function cb) const override; + Router::RouteSpecificFilterConfigs perFilterConfigs() const override; Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override; OptRef downstreamCallbacks() override; OptRef upstreamCallbacks() override; @@ -185,14 +181,13 @@ struct ActiveStreamFilterBase : public virtual StreamFilterCallbacks, // hasn't parsed data and trailers. As a result, the filter iteration should start with the // current filter instead of the next one. If true, filter iteration starts with the current // filter. Otherwise, starts with the next filter in the chain. - bool iterate_from_current_filter_ : 1; - bool headers_continued_ : 1; - bool continued_1xx_headers_ : 1; + bool iterate_from_current_filter_{}; + bool headers_continued_{}; + bool continued_1xx_headers_{}; // If true, end_stream is called for this filter. - bool end_stream_ : 1; - const bool is_encoder_decoder_filter_ : 1; + bool end_stream_{}; // If true, the filter has processed headers. - bool processed_headers_ : 1; + bool processed_headers_{}; }; /** @@ -202,9 +197,8 @@ struct ActiveStreamDecoderFilter : public ActiveStreamFilterBase, public StreamDecoderFilterCallbacks, LinkedObject { ActiveStreamDecoderFilter(FilterManager& parent, StreamDecoderFilterSharedPtr filter, - bool is_encoder_decoder_filter, FilterContext filter_context) - : ActiveStreamFilterBase(parent, is_encoder_decoder_filter, std::move(filter_context)), - handle_(std::move(filter)) { + FilterContext filter_context) + : ActiveStreamFilterBase(parent, std::move(filter_context)), handle_(std::move(filter)) { handle_->setDecoderFilterCallbacks(*this); } @@ -298,9 +292,8 @@ struct ActiveStreamEncoderFilter : public ActiveStreamFilterBase, public StreamEncoderFilterCallbacks, LinkedObject { ActiveStreamEncoderFilter(FilterManager& parent, StreamEncoderFilterSharedPtr filter, - bool is_encoder_decoder_filter, FilterContext filter_context) - : ActiveStreamFilterBase(parent, is_encoder_decoder_filter, std::move(filter_context)), - handle_(std::move(filter)) { + FilterContext filter_context) + : ActiveStreamFilterBase(parent, std::move(filter_context)), handle_(std::move(filter)) { handle_->setEncoderFilterCallbacks(*this); } @@ -720,30 +713,16 @@ class FilterManager : public ScopeTrackedObject, std::list accessLogHandlers() { return access_log_handlers_; } void onStreamComplete() { - for (auto& filter : decoder_filters_) { - filter->handle_->onStreamComplete(); - } - - for (auto& filter : encoder_filters_) { - // Do not call onStreamComplete twice for dual registered filters. - if (!filter->is_encoder_decoder_filter_) { - filter->handle_->onStreamComplete(); - } + for (auto filter : filters_) { + filter->onStreamComplete(); } } void destroyFilters() { state_.destroyed_ = true; - for (auto& filter : decoder_filters_) { - filter->handle_->onDestroy(); - } - - for (auto& filter : encoder_filters_) { - // Do not call on destroy twice for dual registered filters. - if (!filter->is_encoder_decoder_filter_) { - filter->handle_->onDestroy(); - } + for (auto filter : filters_) { + filter->onDestroy(); } } @@ -884,50 +863,44 @@ class FilterManager : public ScopeTrackedObject, protected: struct State { - State() - : decoder_filter_chain_complete_(false), encoder_filter_chain_complete_(false), - observed_decode_end_stream_(false), observed_encode_end_stream_(false), - has_1xx_headers_(false), created_filter_chain_(false), is_head_request_(false), - is_grpc_request_(false), non_100_response_headers_encoded_(false), - under_on_local_reply_(false), decoder_filter_chain_aborted_(false), - encoder_filter_chain_aborted_(false), saw_downstream_reset_(false) {} + State() = default; uint32_t filter_call_state_{0}; // Set after decoder filter chain has completed iteration. Prevents further calls to decoder // filters. This flag is used to determine stream completion when the independent half-close is // enabled. - bool decoder_filter_chain_complete_ : 1; + bool decoder_filter_chain_complete_{}; // Set after encoder filter chain has completed iteration. Prevents further calls to encoder // filters. This flag is used to determine stream completion when the independent half-close is // enabled. - bool encoder_filter_chain_complete_ : 1; + bool encoder_filter_chain_complete_{}; // Set `true` when the filter manager observes end stream on the decoder path (from downstream // client) before iteration of the decoder filter chain begins. This flag is used for setting // end_stream value when resuming decoder filter chain iteration. - bool observed_decode_end_stream_ : 1; + bool observed_decode_end_stream_{}; // Set `true` when the filter manager observes end stream on the encoder path (from upstream // server or Envoy's local reply) before iteration of the encoder filter chain begins. This flag // is used for setting end_stream value when resuming encoder filter chain iteration. - bool observed_encode_end_stream_ : 1; + bool observed_encode_end_stream_{}; // By default, we will assume there are no 1xx. If encode1xxHeaders // is ever called, this is set to true so commonContinue resumes processing the 1xx. - bool has_1xx_headers_ : 1; - bool created_filter_chain_ : 1; + bool has_1xx_headers_{}; + bool created_filter_chain_{}; // These two are latched on initial header read, to determine if the original headers // constituted a HEAD or gRPC request, respectively. - bool is_head_request_ : 1; - bool is_grpc_request_ : 1; + bool is_head_request_{}; + bool is_grpc_request_{}; // Tracks if headers other than 100-Continue have been encoded to the codec. - bool non_100_response_headers_encoded_ : 1; + bool non_100_response_headers_encoded_{}; // True under the stack of onLocalReply, false otherwise. - bool under_on_local_reply_ : 1; + bool under_on_local_reply_{}; // True when the filter chain iteration was aborted with local reply. - bool decoder_filter_chain_aborted_ : 1; - bool encoder_filter_chain_aborted_ : 1; - bool saw_downstream_reset_ : 1; + bool decoder_filter_chain_aborted_{}; + bool encoder_filter_chain_aborted_{}; + bool saw_downstream_reset_{}; // The following 3 members are booleans rather than part of the space-saving bitfield as they // are passed as arguments to functions expecting bools. Extend State using the bitfield @@ -952,14 +925,14 @@ class FilterManager : public ScopeTrackedObject, void addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr filter) override { manager_.addStreamFilterBase(filter.get()); - manager_.addStreamDecoderFilter(std::make_unique( - manager_, std::move(filter), false, context_)); + manager_.addStreamDecoderFilter( + std::make_unique(manager_, std::move(filter), context_)); } void addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr filter) override { manager_.addStreamFilterBase(filter.get()); - manager_.addStreamEncoderFilter(std::make_unique( - manager_, std::move(filter), false, context_)); + manager_.addStreamEncoderFilter( + std::make_unique(manager_, std::move(filter), context_)); } void addStreamFilter(Http::StreamFilterSharedPtr filter) override { @@ -967,9 +940,9 @@ class FilterManager : public ScopeTrackedObject, manager_.addStreamFilterBase(decoder_filter); manager_.addStreamDecoderFilter( - std::make_unique(manager_, filter, true, context_)); + std::make_unique(manager_, filter, context_)); manager_.addStreamEncoderFilter( - std::make_unique(manager_, std::move(filter), true, context_)); + std::make_unique(manager_, std::move(filter), context_)); } void addAccessLogHandler(AccessLog::InstanceSharedPtr handler) override { diff --git a/source/common/http/headers.h b/source/common/http/headers.h index b1368b060ea3..17550b4a0b62 100644 --- a/source/common/http/headers.h +++ b/source/common/http/headers.h @@ -350,6 +350,7 @@ class HeaderValues { struct { const std::string EnvoyHealthChecker{"Envoy/HC"}; + const std::string GoBrowser{"Go-browser"}; } UserAgentValues; struct { diff --git a/source/common/http/null_route_impl.h b/source/common/http/null_route_impl.h index 672dcc207d9a..5da6b8789f77 100644 --- a/source/common/http/null_route_impl.h +++ b/source/common/http/null_route_impl.h @@ -64,12 +64,12 @@ struct NullVirtualHost : public Router::VirtualHost { bool includeIsTimeoutRetryHeader() const override { return false; } uint32_t retryShadowBufferLimit() const override { return std::numeric_limits::max(); } const Router::RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string&) const override { + mostSpecificPerFilterConfig(absl::string_view) const override { return nullptr; } - void traversePerFilterConfig( - const std::string&, - std::function) const override {} + Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override { + return {}; + } const envoy::config::core::v3::Metadata& metadata() const override { return Router::DefaultRouteMetadataPack::get().proto_metadata_; } @@ -225,12 +225,12 @@ struct NullRouteImpl : public Router::Route { const Router::Decorator* decorator() const override { return nullptr; } const Router::RouteTracing* tracingConfig() const override { return nullptr; } const Router::RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string&) const override { + mostSpecificPerFilterConfig(absl::string_view) const override { return nullptr; } - void traversePerFilterConfig( - const std::string&, - std::function) const override {} + Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override { + return {}; + } const envoy::config::core::v3::Metadata& metadata() const override { return Router::DefaultRouteMetadataPack::get().proto_metadata_; } diff --git a/source/common/http/utility.h b/source/common/http/utility.h index 57cd2ebad0a5..d1b2d0d09376 100644 --- a/source/common/http/utility.h +++ b/source/common/http/utility.h @@ -563,43 +563,6 @@ const ConfigType* resolveMostSpecificPerFilterConfig(const Http::StreamFilterCal return dynamic_cast(callbacks->mostSpecificPerFilterConfig()); } -/** - * Merge all the available per route filter configs into one. To perform the merge, - * the reduce function will be called on each two configs until a single merged config is left. - * - * @param reduce The first argument for this function will be the config from the previous level - * and the second argument is the config from the current level (the more specific one). The - * function should merge the second argument into the first argument. - * - * @return The merged config. - */ -template -absl::optional -getMergedPerFilterConfig(const Http::StreamFilterCallbacks* callbacks, - std::function reduce) { - static_assert(std::is_copy_constructible::value, - "ConfigType must be copy constructible"); - ASSERT(callbacks != nullptr); - - absl::optional merged; - - callbacks->traversePerFilterConfig([&reduce, - &merged](const Router::RouteSpecificFilterConfig& cfg) { - const ConfigType* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg == nullptr) { - ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); - return; - } - if (!merged) { - merged.emplace(*typed_cfg); - } else { - reduce(merged.value(), *typed_cfg); - } - }); - - return merged; -} - /** * Return all the available per route filter configs. * @@ -609,20 +572,20 @@ getMergedPerFilterConfig(const Http::StreamFilterCallbacks* callbacks, * and their lifetime is the same as the matched route. */ template -absl::InlinedVector +absl::InlinedVector getAllPerFilterConfig(const Http::StreamFilterCallbacks* callbacks) { ASSERT(callbacks != nullptr); - absl::InlinedVector all_configs; - callbacks->traversePerFilterConfig([&all_configs](const Router::RouteSpecificFilterConfig& cfg) { - const ConfigType* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg == nullptr) { + absl::InlinedVector all_configs; + + for (const auto* config : callbacks->perFilterConfigs()) { + const ConfigType* typed_config = dynamic_cast(config); + if (typed_config == nullptr) { ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); - return; + continue; } - - all_configs.push_back(typed_cfg); - }); + all_configs.push_back(typed_config); + } return all_configs; } diff --git a/source/common/json/json_streamer.h b/source/common/json/json_streamer.h index 97d7ef424d54..ae18b7a38699 100644 --- a/source/common/json/json_streamer.h +++ b/source/common/json/json_streamer.h @@ -39,7 +39,9 @@ namespace Json { #define ASSERT_LEVELS_EMPTY ASSERT(this->levels_.empty()) #endif -// Simple abstraction that provide a output buffer for streaming JSON output. +// Buffer wrapper that implements the necessary abstraction for the template +// StreamerBase. +// This could be used to stream JSON output of StreamerBase to a Buffer. class BufferOutput { public: void add(absl::string_view a) { buffer_.addFragments({a}); } @@ -51,24 +53,41 @@ class BufferOutput { Buffer::Instance& buffer_; }; +// String wrapper that implements the necessary abstraction for the template +// StreamerBase. +// This could be used to stream JSON output of StreamerBase to a single string. +class StringOutput { +public: + void add(absl::string_view a) { buffer_.append(a); } + void add(absl::string_view a, absl::string_view b, absl::string_view c) { + absl::StrAppend(&buffer_, a, b, c); + } + explicit StringOutput(std::string& output) : buffer_(output) {} + + std::string& buffer_; +}; + /** * Provides an API for streaming JSON output, as an alternative to populating a * JSON structure with an image of what you want to serialize, or using a * protobuf with reflection. The advantage of this approach is that it does not * require building an intermediate data structure with redundant copies of all * strings, maps, and arrays. + * + * NOTE: This template take a type that can be used to stream output. This is either + * BufferOutput, StringOutput or any other types that have implemented + * add(absl::string_view) and + * add(absl::string_view, absl::string_view, absl::string_view) methods. */ -class Streamer { +template class StreamerBase { public: - using Value = absl::variant; + using Value = absl::variant; /** - * @param response The buffer in which to stream output. Note: this buffer can - * be flushed during population; it is not necessary to hold - * the entire json structure in memory before streaming it to - * the network. + * @param response The buffer in which to stream output. + * NOTE: The response must could be used to construct instance of OutputBufferType. */ - explicit Streamer(Buffer::Instance& response) : response_(response) {} + template explicit StreamerBase(T& response) : response_(response) {} class Array; using ArrayPtr = std::unique_ptr; @@ -81,15 +100,15 @@ class Streamer { */ class Level { public: - Level(Streamer& streamer, absl::string_view opener, absl::string_view closer) + Level(StreamerBase& streamer, absl::string_view opener, absl::string_view closer) : streamer_(streamer), closer_(closer) { - streamer_.addConstantString(opener); + streamer_.addWithoutSanitizing(opener); #ifndef NDEBUG streamer_.push(this); #endif } virtual ~Level() { - streamer_.addConstantString(closer_); + streamer_.addWithoutSanitizing(closer_); #ifndef NDEBUG streamer_.pop(this); #endif @@ -171,6 +190,18 @@ class Streamer { streamer_.addBool(b); } + /** + * Adds a null constant value to the current array or map. It's a programming + * error to call this method on a map or array that's not the top level. + * It's also a programming error to call this on map that isn't expecting + * a value. You must call Map::addKey prior to calling this. + */ + void addNull() { + ASSERT_THIS_IS_TOP_LEVEL; + nextField(); + streamer_.addNull(); + } + protected: /** * Initiates a new field, serializing a comma separator if this is not the @@ -180,7 +211,7 @@ class Streamer { if (is_first_) { is_first_ = false; } else { - streamer_.addConstantString(","); + streamer_.addWithoutSanitizing(","); } } @@ -192,42 +223,45 @@ class Streamer { * @param Value the value to render. */ void addValue(const Value& value) { - static_assert(absl::variant_size_v == 5, "Value must be a variant with 5 types"); + static_assert(absl::variant_size_v == 6, "Value must be a variant with 6 types"); switch (value.index()) { case 0: - static_assert(std::is_same(value)), const absl::string_view&>::value, + static_assert(std::is_same_v, absl::string_view>, "value at index 0 must be an absl::string_vlew"); addString(absl::get(value)); break; case 1: - static_assert(std::is_same(value)), const double&>::value, + static_assert(std::is_same_v, double>, "value at index 1 must be a double"); addNumber(absl::get(value)); break; case 2: - static_assert(std::is_same(value)), const uint64_t&>::value, + static_assert(std::is_same_v, uint64_t>, "value at index 2 must be a uint64_t"); addNumber(absl::get(value)); break; case 3: - static_assert(std::is_same(value)), const int64_t&>::value, + static_assert(std::is_same_v, int64_t>, "value at index 3 must be an int64_t"); addNumber(absl::get(value)); break; case 4: - static_assert(std::is_same(value)), const bool&>::value, + static_assert(std::is_same_v, bool>, "value at index 4 must be a bool"); addBool(absl::get(value)); break; + case 5: + static_assert(std::is_same_v, absl::monostate>, + "value at index 5 must be an absl::monostate"); + addNull(); + break; } } - private: - friend Streamer; - + protected: bool is_first_{true}; // Used to control whether a comma-separator is added for a new entry. - Streamer& streamer_; + StreamerBase& streamer_; absl::string_view closer_; }; using LevelPtr = std::unique_ptr; @@ -241,7 +275,7 @@ class Streamer { using NameValue = std::pair; using Entries = absl::Span; - Map(Streamer& streamer) : Level(streamer, "{", "}") {} + Map(StreamerBase& streamer) : Level(streamer, "{", "}") {} /** * Initiates a new map key. This must be followed by rendering a value, @@ -292,7 +326,7 @@ class Streamer { */ class Array : public Level { public: - Array(Streamer& streamer) : Level(streamer, "[", "]") {} + Array(StreamerBase& streamer) : Level(streamer, "[", "]") {} using Entries = absl::Span; /** @@ -333,11 +367,6 @@ class Streamer { return std::make_unique(*this); } -private: - friend Level; - friend Map; - friend Array; - /** * Takes a raw string, sanitizes it using JSON syntax, surrounds it * with a prefix and suffix, and streams it out. @@ -361,7 +390,7 @@ class Streamer { if (std::isnan(d)) { response_.add(Constants::Null); } else { - Buffer::Util::serializeDouble(d, response_.buffer_); + Buffer::Util::serializeDouble(d, response_); } } void addNumber(uint64_t u) { response_.add(absl::StrCat(u)); } @@ -373,10 +402,16 @@ class Streamer { void addBool(bool b) { response_.add(b ? Constants::True : Constants::False); } /** - * Adds a constant string to the output stream. The string must outlive the - * Streamer object, and is intended for literal strings such as punctuation. + * Serializes a null to the output stream. */ - void addConstantString(absl::string_view str) { response_.add(str); } + void addNull() { response_.add(Constants::Null); } + +private: + /** + * Adds a string to the output stream without sanitizing it. This is only used to push + * the delimiters to output buffer. + */ + void addWithoutSanitizing(absl::string_view str) { response_.add(str); } #ifndef NDEBUG /** @@ -399,7 +434,7 @@ class Streamer { #endif - BufferOutput response_; + OutputBufferType response_; std::string sanitize_buffer_; #ifndef NDEBUG @@ -409,5 +444,10 @@ class Streamer { #endif }; +/** + * A Streamer that streams to a Buffer::Instance. + */ +using Streamer = StreamerBase; + } // namespace Json } // namespace Envoy diff --git a/source/common/listener_manager/listener_impl.cc b/source/common/listener_manager/listener_impl.cc index 5924d2deec86..a82bf3a8d375 100644 --- a/source/common/listener_manager/listener_impl.cc +++ b/source/common/listener_manager/listener_impl.cc @@ -236,7 +236,7 @@ std::string listenerStatsScope(const envoy::config::listener::v3::Listener& conf return absl::StrCat("envoy_internal_", config.name()); } auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); return address_or_error.value()->asString(); } } // namespace @@ -324,7 +324,7 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, // All the addresses should be same socket type, so get the first address's socket type is // enough. auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); auto address = std::move(address_or_error.value()); checkIpv4CompatAddress(address, config.address()); addresses_.emplace_back(address); @@ -340,7 +340,7 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, } auto addresses_or_error = Network::Address::resolveProtoAddress(config.additional_addresses(i).address()); - THROW_IF_STATUS_NOT_OK(addresses_or_error, throw); + THROW_IF_NOT_OK_REF(addresses_or_error.status()); auto additional_address = std::move(addresses_or_error.value()); checkIpv4CompatAddress(address, config.additional_addresses(i).address()); addresses_.emplace_back(additional_address); diff --git a/source/common/protobuf/utility.cc b/source/common/protobuf/utility.cc index e9b5003b9061..2bf646a6b907 100644 --- a/source/common/protobuf/utility.cc +++ b/source/common/protobuf/utility.cc @@ -936,7 +936,7 @@ void MessageUtil::loadFromFile(const std::string& path, Protobuf::Message& messa ProtobufMessage::ValidationVisitor& validation_visitor, Api::Api& api) { auto file_or_error = api.fileSystem().fileReadToEnd(path); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const std::string contents = file_or_error.value(); // If the filename ends with .pb, attempt to parse it as a binary proto. if (absl::EndsWithIgnoreCase(path, FileExtensions::get().ProtoBinary)) { diff --git a/source/common/quic/BUILD b/source/common/quic/BUILD index 884ce2714010..8a91e57052e4 100644 --- a/source/common/quic/BUILD +++ b/source/common/quic/BUILD @@ -116,7 +116,9 @@ envoy_cc_library( name = "envoy_quic_proof_source_lib", srcs = ["envoy_quic_proof_source.cc"], hdrs = ["envoy_quic_proof_source.h"], - external_deps = ["ssl"], + external_deps = [ + "ssl", + ], tags = ["nofips"], deps = [ ":envoy_quic_proof_source_base_lib", @@ -124,6 +126,7 @@ envoy_cc_library( ":quic_io_handle_wrapper_lib", ":quic_transport_socket_factory_lib", "//envoy/ssl:tls_certificate_config_interface", + "//source/common/quic:cert_compression_lib", "//source/common/quic:quic_server_transport_socket_factory_lib", "//source/common/stream_info:stream_info_lib", "//source/server:listener_stats", @@ -500,6 +503,7 @@ envoy_cc_library( "//envoy/ssl:context_config_interface", "//source/common/common:assert_lib", "//source/common/network:transport_socket_options_lib", + "//source/common/quic:cert_compression_lib", "//source/common/tls:client_ssl_socket_lib", "//source/common/tls:context_config_lib", "@com_github_google_quiche//:quic_core_crypto_crypto_handshake_lib", @@ -714,3 +718,18 @@ envoy_cc_library( "@com_github_google_quiche//:quic_core_types_lib", ], ) + +envoy_cc_library( + name = "cert_compression_lib", + srcs = ["cert_compression.cc"], + hdrs = ["cert_compression.h"], + external_deps = [ + "ssl", + "zlib", + ], + deps = [ + "//source/common/common:assert_lib", + "//source/common/common:logger_lib", + "//source/common/runtime:runtime_lib", + ], +) diff --git a/source/common/quic/cert_compression.cc b/source/common/quic/cert_compression.cc new file mode 100644 index 000000000000..90acde1e2694 --- /dev/null +++ b/source/common/quic/cert_compression.cc @@ -0,0 +1,122 @@ +#include "source/common/quic/cert_compression.h" + +#include "source/common/common/assert.h" +#include "source/common/runtime/runtime_features.h" + +#include "openssl/tls1.h" + +#define ZLIB_CONST +#include "zlib.h" + +namespace Envoy { +namespace Quic { + +namespace { + +class ScopedZStream { +public: + using CleanupFunc = int (*)(z_stream*); + + ScopedZStream(z_stream& z, CleanupFunc cleanup) : z_(z), cleanup_(cleanup) {} + ~ScopedZStream() { cleanup_(&z_); } + +private: + z_stream& z_; + CleanupFunc cleanup_; +}; + +} // namespace + +void CertCompression::registerSslContext(SSL_CTX* ssl_ctx) { + if (Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.quic_support_certificate_compression")) { + auto ret = SSL_CTX_add_cert_compression_alg(ssl_ctx, TLSEXT_cert_compression_zlib, compressZlib, + decompressZlib); + ASSERT(ret == 1); + } +} + +int CertCompression::compressZlib(SSL*, CBB* out, const uint8_t* in, size_t in_len) { + + z_stream z = {}; + int rv = deflateInit(&z, Z_DEFAULT_COMPRESSION); + if (rv != Z_OK) { + IS_ENVOY_BUG(fmt::format("Cert compression failure in deflateInit: {}", rv)); + return FAILURE; + } + + ScopedZStream deleter(z, deflateEnd); + + const auto upper_bound = deflateBound(&z, in_len); + + uint8_t* out_buf = nullptr; + if (!CBB_reserve(out, &out_buf, upper_bound)) { + IS_ENVOY_BUG(fmt::format("Cert compression failure in allocating output CBB buffer of size {}", + upper_bound)); + return FAILURE; + } + + z.next_in = in; + z.avail_in = in_len; + z.next_out = out_buf; + z.avail_out = upper_bound; + + rv = deflate(&z, Z_FINISH); + if (rv != Z_STREAM_END) { + IS_ENVOY_BUG(fmt::format( + "Cert compression failure in deflate: {}, z.total_out {}, in_len {}, z.avail_in {}", rv, + z.avail_in, in_len, z.avail_in)); + return FAILURE; + } + + if (!CBB_did_write(out, z.total_out)) { + IS_ENVOY_BUG("CBB_did_write failed"); + return FAILURE; + } + + ENVOY_LOG(trace, "Cert compression successful"); + + return SUCCESS; +} + +int CertCompression::decompressZlib(SSL*, CRYPTO_BUFFER** out, size_t uncompressed_len, + const uint8_t* in, size_t in_len) { + z_stream z = {}; + int rv = inflateInit(&z); + if (rv != Z_OK) { + IS_ENVOY_BUG(fmt::format("Cert decompression failure in inflateInit: {}", rv)); + return FAILURE; + } + + ScopedZStream deleter(z, inflateEnd); + + z.next_in = in; + z.avail_in = in_len; + bssl::UniquePtr decompressed_data( + CRYPTO_BUFFER_alloc(&z.next_out, uncompressed_len)); + z.avail_out = uncompressed_len; + + rv = inflate(&z, Z_FINISH); + if (rv != Z_STREAM_END) { + ENVOY_LOG_PERIODIC(error, std::chrono::seconds(10), + "Cert decompression failure in inflate, possibly caused by invalid " + "compressed cert from peer: {}, z.total_out {}, uncompressed_len {}", + rv, z.total_out, uncompressed_len); + return FAILURE; + } + + if (z.total_out != uncompressed_len) { + ENVOY_LOG_PERIODIC(error, std::chrono::seconds(10), + "Decompression length did not match peer provided uncompressed length, " + "caused by either invalid peer handshake data or decompression error."); + return FAILURE; + } + + ENVOY_LOG(trace, "Cert decompression successful"); + + *out = decompressed_data.release(); + return SUCCESS; +} + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/cert_compression.h b/source/common/quic/cert_compression.h new file mode 100644 index 000000000000..65be63cb8fde --- /dev/null +++ b/source/common/quic/cert_compression.h @@ -0,0 +1,31 @@ +#pragma once + +#include "source/common/common/logger.h" + +#include "openssl/ssl.h" + +namespace Envoy { +namespace Quic { + +/** + * Support for certificate compression and decompression in QUIC TLS handshakes. This often + * needed for the ServerHello to fit in the initial response and not need an additional round trip + * between client and server. + */ +class CertCompression : protected Logger::Loggable { +public: + // Registers compression and decompression functions on `ssl_ctx` if enabled. + static void registerSslContext(SSL_CTX* ssl_ctx); + + // Callbacks for `SSL_CTX_add_cert_compression_alg`. + static int compressZlib(SSL* ssl, CBB* out, const uint8_t* in, size_t in_len); + static int decompressZlib(SSL*, CRYPTO_BUFFER** out, size_t uncompressed_len, const uint8_t* in, + size_t in_len); + + // Defined return values for callbacks from `SSL_CTX_add_cert_compression_alg`. + static constexpr int SUCCESS = 1; + static constexpr int FAILURE = 0; +}; + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/envoy_quic_proof_source.cc b/source/common/quic/envoy_quic_proof_source.cc index e5457e953ad9..4d696753e013 100644 --- a/source/common/quic/envoy_quic_proof_source.cc +++ b/source/common/quic/envoy_quic_proof_source.cc @@ -4,6 +4,7 @@ #include "envoy/ssl/tls_certificate_config.h" +#include "source/common/quic/cert_compression.h" #include "source/common/quic/envoy_quic_utils.h" #include "source/common/quic/quic_io_handle_wrapper.h" #include "source/common/runtime/runtime_features.h" @@ -211,5 +212,9 @@ void EnvoyQuicProofSource::updateFilterChainManager( filter_chain_manager_ = &filter_chain_manager; } +void EnvoyQuicProofSource::OnNewSslCtx(SSL_CTX* ssl_ctx) { + CertCompression::registerSslContext(ssl_ctx); +} + } // namespace Quic } // namespace Envoy diff --git a/source/common/quic/envoy_quic_proof_source.h b/source/common/quic/envoy_quic_proof_source.h index e950b982445b..1d8bf461f948 100644 --- a/source/common/quic/envoy_quic_proof_source.h +++ b/source/common/quic/envoy_quic_proof_source.h @@ -19,6 +19,7 @@ class EnvoyQuicProofSource : public EnvoyQuicProofSourceBase { ~EnvoyQuicProofSource() override = default; // quic::ProofSource + void OnNewSslCtx(SSL_CTX* ssl_ctx) override; quiche::QuicheReferenceCountedPointer GetCertChain(const quic::QuicSocketAddress& server_address, const quic::QuicSocketAddress& client_address, const std::string& hostname, diff --git a/source/common/quic/quic_client_transport_socket_factory.cc b/source/common/quic/quic_client_transport_socket_factory.cc index e7b2febc8f75..0ec580f830b0 100644 --- a/source/common/quic/quic_client_transport_socket_factory.cc +++ b/source/common/quic/quic_client_transport_socket_factory.cc @@ -4,6 +4,7 @@ #include "envoy/extensions/transport_sockets/quic/v3/quic_transport.pb.validate.h" +#include "source/common/quic/cert_compression.h" #include "source/common/quic/envoy_quic_proof_verifier.h" #include "source/common/runtime/runtime_features.h" #include "source/common/tls/context_config_impl.h" @@ -86,6 +87,8 @@ std::shared_ptr QuicClientTransportSocketFactory:: tls_config.crypto_config_ = std::make_shared( std::make_unique(std::move(context), accept_untrusted), std::make_unique()); + + CertCompression::registerSslContext(tls_config.crypto_config_->ssl_ctx()); } // Return the latest crypto config. return tls_config.crypto_config_; diff --git a/source/common/router/config_impl.cc b/source/common/router/config_impl.cc index 0d4b12862985..7c70a5f42e54 100644 --- a/source/common/router/config_impl.cc +++ b/source/common/router/config_impl.cc @@ -1510,15 +1510,15 @@ absl::optional RouteEntryImplBase::filterDisabled(absl::string_view config return vhost_->filterDisabled(config_name); } -void RouteEntryImplBase::traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const { - vhost_->traversePerFilterConfig(filter_name, cb); +RouteSpecificFilterConfigs +RouteEntryImplBase::perFilterConfigs(absl::string_view filter_name) const { + auto result = vhost_->perFilterConfigs(filter_name); - auto maybe_route_config = per_filter_configs_->get(filter_name); + const auto* maybe_route_config = per_filter_configs_->get(filter_name); if (maybe_route_config != nullptr) { - cb(*maybe_route_config); + result.push_back(maybe_route_config); } + return result; } const envoy::config::core::v3::Metadata& RouteEntryImplBase::metadata() const { @@ -1598,15 +1598,15 @@ Http::HeaderTransforms RouteEntryImplBase::WeightedClusterEntry::responseHeaderT return transforms; } -void RouteEntryImplBase::WeightedClusterEntry::traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const { - DynamicRouteEntry::traversePerFilterConfig(filter_name, cb); +RouteSpecificFilterConfigs +RouteEntryImplBase::WeightedClusterEntry::perFilterConfigs(absl::string_view filter_name) const { + auto result = DynamicRouteEntry::perFilterConfigs(filter_name); const auto* cfg = per_filter_configs_->get(filter_name); - if (cfg) { - cb(*cfg); + if (cfg != nullptr) { + result.push_back(cfg); } + return result; } UriTemplateMatcherRouteEntryImpl::UriTemplateMatcherRouteEntryImpl( @@ -1910,23 +1910,25 @@ absl::optional CommonVirtualHostImpl::filterDisabled(absl::string_view con } const RouteSpecificFilterConfig* -CommonVirtualHostImpl::mostSpecificPerFilterConfig(const std::string& name) const { +CommonVirtualHostImpl::mostSpecificPerFilterConfig(absl::string_view name) const { auto* per_filter_config = per_filter_configs_->get(name); return per_filter_config != nullptr ? per_filter_config : global_route_config_->perFilterConfig(name); } -void CommonVirtualHostImpl::traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const { +RouteSpecificFilterConfigs +CommonVirtualHostImpl::perFilterConfigs(absl::string_view filter_name) const { + RouteSpecificFilterConfigs result; + // Parent first. if (auto* maybe_rc_config = global_route_config_->perFilterConfig(filter_name); maybe_rc_config != nullptr) { - cb(*maybe_rc_config); + result.push_back(maybe_rc_config); } if (auto* maybe_vhost_config = per_filter_configs_->get(filter_name); maybe_vhost_config != nullptr) { - cb(*maybe_vhost_config); + result.push_back(maybe_vhost_config); } + return result; } const envoy::config::core::v3::Metadata& CommonVirtualHostImpl::metadata() const { @@ -2491,7 +2493,7 @@ PerFilterConfigs::PerFilterConfigs( } } -const RouteSpecificFilterConfig* PerFilterConfigs::get(const std::string& name) const { +const RouteSpecificFilterConfig* PerFilterConfigs::get(absl::string_view name) const { auto it = configs_.find(name); return it == configs_.end() ? nullptr : it->second.config_.get(); } diff --git a/source/common/router/config_impl.h b/source/common/router/config_impl.h index 36b0e26dc6f4..c8dce5ceec36 100644 --- a/source/common/router/config_impl.h +++ b/source/common/router/config_impl.h @@ -93,7 +93,7 @@ class PerFilterConfigs : public Logger::Loggable { bool disabled_{}; }; - const RouteSpecificFilterConfig* get(const std::string& name) const; + const RouteSpecificFilterConfig* get(absl::string_view name) const; /** * @return true if the filter is explicitly disabled for this route or virtual host, false @@ -148,13 +148,11 @@ class SslRedirectRoute : public Route { const RouteEntry* routeEntry() const override { return nullptr; } const Decorator* decorator() const override { return nullptr; } const RouteTracing* tracingConfig() const override { return nullptr; } - const RouteSpecificFilterConfig* mostSpecificPerFilterConfig(const std::string&) const override { + const RouteSpecificFilterConfig* mostSpecificPerFilterConfig(absl::string_view) const override { return nullptr; } absl::optional filterDisabled(absl::string_view) const override { return {}; } - void traversePerFilterConfig( - const std::string&, - std::function) const override {} + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override { return {}; } const envoy::config::core::v3::Metadata& metadata() const override { return metadata_; } const Envoy::Config::TypedMetadata& typedMetadata() const override { return typed_metadata_; } const std::string& routeName() const override { return EMPTY_STRING; } @@ -290,7 +288,7 @@ class CommonVirtualHostImpl : public VirtualHost, Logger::Loggable cb) const override; + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override; const envoy::config::core::v3::Metadata& metadata() const override; const Envoy::Config::TypedMetadata& typedMetadata() const override; const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const override { @@ -831,13 +827,11 @@ class RouteEntryImplBase : public RouteEntryAndRoute, const RouteTracing* tracingConfig() const override { return route_tracing_.get(); } absl::optional filterDisabled(absl::string_view config_name) const override; const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { auto* config = per_filter_configs_->get(name); return config ? config : vhost_->mostSpecificPerFilterConfig(name); } - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override; + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override; const std::string& routeName() const override { return route_name_; } // Sanitizes the |path| before passing it to PathMatcher, if configured, this method makes the @@ -965,13 +959,11 @@ class RouteEntryImplBase : public RouteEntryAndRoute, return parent_->filterDisabled(config_name); } const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { return parent_->mostSpecificPerFilterConfig(name); } - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override { - parent_->traversePerFilterConfig(filter_name, cb); + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view filter_name) const override { + return parent_->perFilterConfigs(filter_name); }; const std::string& routeName() const override { return parent_->routeName(); } @@ -1058,14 +1050,11 @@ class RouteEntryImplBase : public RouteEntryAndRoute, return DynamicRouteEntry::filterDisabled(config_name); } const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { auto* config = per_filter_configs_->get(name); return config ? config : DynamicRouteEntry::mostSpecificPerFilterConfig(name); } - - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override; + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override; const Http::LowerCaseString& clusterHeaderName() const { return cluster_header_name_; } @@ -1613,7 +1602,7 @@ class CommonConfigImpl : public CommonConfig { return HeaderParser::defaultParser(); } - const RouteSpecificFilterConfig* perFilterConfig(const std::string& name) const { + const RouteSpecificFilterConfig* perFilterConfig(absl::string_view name) const { return per_filter_configs_->get(name); } absl::optional filterDisabled(absl::string_view config_name) const { diff --git a/source/common/router/delegating_route_impl.h b/source/common/router/delegating_route_impl.h index 36deb173c7f9..a0218a636310 100644 --- a/source/common/router/delegating_route_impl.h +++ b/source/common/router/delegating_route_impl.h @@ -28,13 +28,11 @@ class DelegatingRoute : public Router::Route { const Router::RouteTracing* tracingConfig() const override; const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { return base_route_->mostSpecificPerFilterConfig(name); } - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override { - base_route_->traversePerFilterConfig(filter_name, cb); + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view filter_name) const override { + return base_route_->perFilterConfigs(filter_name); } const envoy::config::core::v3::Metadata& metadata() const override { diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 7f0378342a27..860aaf353e56 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -30,6 +30,7 @@ // 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_alt_svc_for_ips); +RUNTIME_GUARD(envoy_reloadable_features_boolean_to_string_fix); RUNTIME_GUARD(envoy_reloadable_features_check_switch_protocol_websocket_handshake); RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle); RUNTIME_GUARD(envoy_reloadable_features_consistent_header_validation); @@ -80,6 +81,7 @@ RUNTIME_GUARD(envoy_reloadable_features_quic_receive_ecn); // Ignore the automated "remove this flag" issue: we should keep this for 1 year. Confirm with // @danzh2010 or @RyanTheOptimist before removing. RUNTIME_GUARD(envoy_reloadable_features_quic_send_server_preferred_address_to_all_clients); +RUNTIME_GUARD(envoy_reloadable_features_quic_support_certificate_compression); RUNTIME_GUARD(envoy_reloadable_features_quic_upstream_reads_fixed_number_packets); RUNTIME_GUARD(envoy_reloadable_features_quic_upstream_socket_use_address_cache_for_read); RUNTIME_GUARD(envoy_reloadable_features_reject_invalid_yaml); diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc index 917ef6e655a1..24b1f1ff04c2 100644 --- a/source/common/runtime/runtime_impl.cc +++ b/source/common/runtime/runtime_impl.cc @@ -375,7 +375,13 @@ SnapshotImpl::Entry SnapshotImpl::createEntry(const ProtobufWkt::Value& value, 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()); + if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.boolean_to_string_fix")) { + // Convert boolean to "true"/"false" + entry.raw_string_value_ = value.bool_value() ? "true" : "false"; + } else { + // Use absl::StrCat for backward compatibility, which converts to "1"/"0" + entry.raw_string_value_ = absl::StrCat(value.bool_value()); + } } break; case ProtobufWkt::Value::kStructValue: diff --git a/source/common/secret/sds_api.cc b/source/common/secret/sds_api.cc index 620bffb4972d..1f88e78babc1 100644 --- a/source/common/secret/sds_api.cc +++ b/source/common/secret/sds_api.cc @@ -210,7 +210,7 @@ SdsApi::FileContentMap SdsApi::loadFiles() { FileContentMap files; for (auto const& filename : getDataSourceFilenames()) { auto file_or_error = api_.fileSystem().fileReadToEnd(filename); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); files[filename] = file_or_error.value(); } return files; diff --git a/source/common/tcp_proxy/tcp_proxy.h b/source/common/tcp_proxy/tcp_proxy.h index 66a53e64aec3..b528b87cf164 100644 --- a/source/common/tcp_proxy/tcp_proxy.h +++ b/source/common/tcp_proxy/tcp_proxy.h @@ -545,6 +545,7 @@ class Filter : public Network::ReadFilter, const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const override { return nullptr; } + Router::RouteSpecificFilterConfigs perFilterConfigs() const override { return {}; } Buffer::BufferMemoryAccountSharedPtr account() const override { return nullptr; } void setUpstreamOverrideHost(Upstream::LoadBalancerContext::OverrideHost) override {} absl::optional @@ -555,8 +556,6 @@ class Filter : public Network::ReadFilter, void restoreContextOnContinue(ScopeTrackedObjectStack& tracked_object_stack) override { tracked_object_stack.add(*this); } - void traversePerFilterConfig( - std::function) const override {} Http::Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override { return {}; } OptRef downstreamCallbacks() override { return {}; } OptRef upstreamCallbacks() override { return {}; } diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index 6c16ac21db73..fcdef2ad85cf 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -844,7 +844,7 @@ bool ClusterManagerImpl::addOrUpdateCluster(const envoy::config::cluster::v3::Cl // before destroy to avoid early initialization complete. auto status_or_cluster = loadCluster(cluster, new_hash, version_info, /*added_via_api=*/true, /*required_for_ads=*/false, warming_clusters_); - THROW_IF_STATUS_NOT_OK(status_or_cluster, throw); + THROW_IF_NOT_OK_REF(status_or_cluster.status()); const ClusterDataPtr previous_cluster = std::move(status_or_cluster.value()); auto& cluster_entry = warming_clusters_.at(cluster_name); cluster_entry->cluster_->info()->configUpdateStats().warming_state_.set(1); diff --git a/source/common/upstream/health_checker_event_logger.h b/source/common/upstream/health_checker_event_logger.h index 38bd0ed9d0a6..1039f78493f8 100644 --- a/source/common/upstream/health_checker_event_logger.h +++ b/source/common/upstream/health_checker_event_logger.h @@ -34,7 +34,7 @@ class HealthCheckEventLoggerImpl : public HealthCheckEventLogger { auto file_or_error = context.serverFactoryContext().accessLogManager().createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, health_check_config.event_log_path()}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } for (const auto& config : health_check_config.event_logger()) { diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index b1b219263584..c12503b2169c 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -372,7 +372,7 @@ HdsCluster::HdsCluster(Server::Configuration::ServerFactoryContext& server_conte const LocalityEndpointTuple endpoint_key = {locality_endpoints.locality(), host}; // Initialize an endpoint host object. auto address_or_error = Network::Address::resolveProtoAddress(host.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); HostSharedPtr endpoint = std::make_shared( info_, "", std::move(address_or_error.value()), nullptr, nullptr, 1, locality_endpoints.locality(), host.endpoint().health_check_config(), 0, @@ -487,7 +487,7 @@ void HdsCluster::updateHosts( // We do not have this endpoint saved, so create a new one. auto address_or_error = Network::Address::resolveProtoAddress(endpoint.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); host = std::make_shared(info_, "", std::move(address_or_error.value()), nullptr, nullptr, 1, endpoints.locality(), endpoint.endpoint().health_check_config(), 0, @@ -560,7 +560,7 @@ void HdsCluster::initHealthchecks() { for (auto& health_check : cluster_.health_checks()) { auto health_checker_or_error = Upstream::HealthCheckerFactory::create(health_check, *this, server_context_); - THROW_IF_STATUS_NOT_OK(health_checker_or_error, throw); + THROW_IF_NOT_OK_REF(health_checker_or_error.status()); auto health_checker = health_checker_or_error.value(); health_checkers_.push_back(health_checker); diff --git a/source/common/upstream/outlier_detection_impl.h b/source/common/upstream/outlier_detection_impl.h index bf74a3d6b8c1..4eea999121a5 100644 --- a/source/common/upstream/outlier_detection_impl.h +++ b/source/common/upstream/outlier_detection_impl.h @@ -498,7 +498,7 @@ class EventLoggerImpl : public EventLogger { : time_source_(time_source) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, file_name}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index b75c0898e622..805ceb849c70 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -2546,7 +2546,7 @@ Network::Address::InstanceConstSharedPtr resolveHealthCheckAddress( const auto& port_value = health_check_config.port_value(); if (health_check_config.has_address()) { auto address_or_error = Network::Address::resolveProtoAddress(health_check_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); auto address = address_or_error.value(); health_check_address = port_value == 0 ? address : Network::Utility::getAddressWithPort(*address, port_value); diff --git a/source/extensions/access_loggers/common/file_access_log_impl.cc b/source/extensions/access_loggers/common/file_access_log_impl.cc index 4ec65df5a0fa..fa7b85554190 100644 --- a/source/extensions/access_loggers/common/file_access_log_impl.cc +++ b/source/extensions/access_loggers/common/file_access_log_impl.cc @@ -10,7 +10,7 @@ FileAccessLog::FileAccessLog(const Filesystem::FilePathAndType& access_log_file_ AccessLog::AccessLogManager& log_manager) : ImplBase(std::move(filter)), formatter_(std::move(formatter)) { auto file_or_error = log_manager.createAccessLog(access_log_file_info); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); log_file_ = file_or_error.value(); } diff --git a/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc b/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc index b1838fe56f9a..790c000aa24a 100644 --- a/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc +++ b/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc @@ -63,7 +63,7 @@ GrpcAccessLoggerImpl::SharedPtr GrpcAccessLoggerCacheImpl::createLogger( // the main thread if necessary. auto factory_or_error = async_client_manager_.factoryForGrpcService(config.grpc_service(), scope_, true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); return std::make_shared( factory_or_error.value()->createUncachedRawAsyncClient(), config, dispatcher, local_info_, scope_); diff --git a/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc b/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc index d6100a807b60..c180f28aa564 100644 --- a/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc +++ b/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc @@ -116,7 +116,7 @@ GrpcAccessLoggerImpl::SharedPtr GrpcAccessLoggerCacheImpl::createLogger( // the main thread if necessary to ensure it does not throw here. auto factory_or_error = async_client_manager_.factoryForGrpcService( config.common_config().grpc_service(), scope_, true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); auto client = factory_or_error.value()->createUncachedRawAsyncClient(); return std::make_shared(std::move(client), config, dispatcher, local_info_, scope_); diff --git a/source/extensions/common/wasm/remote_async_datasource.cc b/source/extensions/common/wasm/remote_async_datasource.cc index 4ed28651c564..b3e8989e7a9a 100644 --- a/source/extensions/common/wasm/remote_async_datasource.cc +++ b/source/extensions/common/wasm/remote_async_datasource.cc @@ -32,7 +32,7 @@ RemoteAsyncDataProvider::RemoteAsyncDataProvider( auto strategy_or_error = Config::Utility::prepareJitteredExponentialBackOffStrategy( source, random, RetryInitialDelayMilliseconds, RetryMaxDelayMilliseconds); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); backoff_strategy_ = std::move(strategy_or_error.value()); retry_timer_ = dispatcher.createTimer([this]() -> void { start(); }); diff --git a/source/extensions/compression/zstd/common/dictionary_manager.h b/source/extensions/compression/zstd/common/dictionary_manager.h index 85d161c73559..99be8fc15fff 100644 --- a/source/extensions/compression/zstd/common/dictionary_manager.h +++ b/source/extensions/compression/zstd/common/dictionary_manager.h @@ -94,7 +94,7 @@ template class void onDictionaryUpdate(unsigned origin_id, const std::string& filename) { auto file_or_error = api_.fileSystem().fileReadToEnd(filename); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const auto data = file_or_error.value(); if (!data.empty()) { auto dictionary = DictionarySharedPtr(builder_(data.data(), data.length())); diff --git a/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc b/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc index 9468f1d32c2e..fb2b82033b7a 100644 --- a/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc +++ b/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc @@ -20,15 +20,15 @@ SubscriptionPtr DeltaGrpcCollectionConfigSubscriptionFactory::create( auto strategy_or_error = Utility::prepareJitteredExponentialBackOffStrategy( api_config_source, data.api_.randomGenerator(), SubscriptionFactory::RetryInitialDelayMs, SubscriptionFactory::RetryMaxDelayMs); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); JitteredExponentialBackOffStrategyPtr backoff_strategy = std::move(strategy_or_error.value()); auto factory_primary_or_error = Config::Utility::factoryForGrpcApiConfigSource( data.cm_.grpcAsyncClientManager(), api_config_source, data.scope_, true, 0); - THROW_IF_STATUS_NOT_OK(factory_primary_or_error, throw); + THROW_IF_NOT_OK_REF(factory_primary_or_error.status()); absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(api_config_source); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ factory_primary_or_error.value()->createUncachedRawAsyncClient(), /*failover_async_client_=*/nullptr, diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc index ba038b140955..4317cdca1a2c 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc @@ -48,7 +48,7 @@ bool isXdsTpWildcard(const std::string& resource_name) { std::string convertToWildcard(const std::string& resource_name) { ASSERT(XdsResourceIdentifier::hasXdsTpScheme(resource_name)); auto resource_or_error = XdsResourceIdentifier::decodeUrn(resource_name); - THROW_IF_STATUS_NOT_OK(resource_or_error, throw); + THROW_IF_NOT_OK_REF(resource_or_error.status()); xds::core::v3::ResourceName xdstp_resource = resource_or_error.value(); const auto pos = xdstp_resource.id().find_last_of('/'); xdstp_resource.set_id( @@ -445,7 +445,7 @@ void GrpcMuxImpl::processDiscoveryResources(const std::vectorname())) { // Sort the context params of an xdstp resource, so we can compare them easily. auto resource_or_error = XdsResourceIdentifier::decodeUrn(resource->name()); - THROW_IF_STATUS_NOT_OK(resource_or_error, throw); + THROW_IF_NOT_OK_REF(resource_or_error.status()); xds::core::v3::ResourceName xdstp_resource = resource_or_error.value(); XdsResourceIdentifier::EncodeOptions options; options.sort_context_params_ = true; @@ -631,7 +631,7 @@ class GrpcMuxFactory : public MuxFactory { XdsResourcesDelegateOptRef xds_resources_delegate, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client_=*/std::move(failover_async_client), diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.h b/source/extensions/config_subscription/grpc/grpc_mux_impl.h index c6d6df79dc6d..885942f3fb2a 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.h @@ -169,7 +169,7 @@ class GrpcMuxImpl : public GrpcMux, [this](const std::string& resource_name) -> std::string { if (XdsResourceIdentifier::hasXdsTpScheme(resource_name)) { auto xdstp_resource_or_error = XdsResourceIdentifier::decodeUrn(resource_name); - THROW_IF_STATUS_NOT_OK(xdstp_resource_or_error, throw); + THROW_IF_NOT_OK_REF(xdstp_resource_or_error.status()); auto xdstp_resource = xdstp_resource_or_error.value(); if (subscription_options_.add_xdstp_node_context_params_) { const auto context = XdsContextParams::encodeResource( diff --git a/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc b/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc index da174b438ce7..a93fb9b4544a 100644 --- a/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc +++ b/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc @@ -23,15 +23,15 @@ GrpcConfigSubscriptionFactory::create(ConfigSubscriptionFactory::SubscriptionDat auto strategy_or_error = Utility::prepareJitteredExponentialBackOffStrategy( api_config_source, data.api_.randomGenerator(), SubscriptionFactory::RetryInitialDelayMs, SubscriptionFactory::RetryMaxDelayMs); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); JitteredExponentialBackOffStrategyPtr backoff_strategy = std::move(strategy_or_error.value()); auto factory_primary_or_error = Utility::factoryForGrpcApiConfigSource( data.cm_.grpcAsyncClientManager(), api_config_source, data.scope_, true, 0); - THROW_IF_STATUS_NOT_OK(factory_primary_or_error, throw); + THROW_IF_NOT_OK_REF(factory_primary_or_error.status()); absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(api_config_source); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/factory_primary_or_error.value()->createUncachedRawAsyncClient(), /*failover_async_client_=*/nullptr, // Failover is only supported for ADS. @@ -72,15 +72,15 @@ DeltaGrpcConfigSubscriptionFactory::create(ConfigSubscriptionFactory::Subscripti auto strategy_or_error = Utility::prepareJitteredExponentialBackOffStrategy( api_config_source, data.api_.randomGenerator(), SubscriptionFactory::RetryInitialDelayMs, SubscriptionFactory::RetryMaxDelayMs); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); JitteredExponentialBackOffStrategyPtr backoff_strategy = std::move(strategy_or_error.value()); auto factory_primary_or_error = Utility::factoryForGrpcApiConfigSource( data.cm_.grpcAsyncClientManager(), api_config_source, data.scope_, true, 0); - THROW_IF_STATUS_NOT_OK(factory_primary_or_error, throw); + THROW_IF_NOT_OK_REF(factory_primary_or_error.status()); absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(api_config_source); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/factory_primary_or_error.value()->createUncachedRawAsyncClient(), /*failover_async_client_=*/nullptr, // Failover is only supported for ADS. diff --git a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc index 15efac2b82d5..1a47a63572c7 100644 --- a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc @@ -262,7 +262,7 @@ void NewGrpcMuxImpl::updateWatch(const std::string& type_url, Watch* watch, for (const auto& resource : resources) { if (XdsResourceIdentifier::hasXdsTpScheme(resource)) { auto xdstp_resource_or_error = XdsResourceIdentifier::decodeUrn(resource); - THROW_IF_STATUS_NOT_OK(xdstp_resource_or_error, throw); + THROW_IF_NOT_OK_REF(xdstp_resource_or_error.status()); auto xdstp_resource = xdstp_resource_or_error.value(); if (options.add_xdstp_node_context_params_) { const auto context = XdsContextParams::encodeResource( @@ -420,7 +420,7 @@ class NewGrpcMuxFactory : public MuxFactory { OptRef, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client_=*/std::move(failover_async_client), diff --git a/source/extensions/config_subscription/grpc/watch_map.cc b/source/extensions/config_subscription/grpc/watch_map.cc index 88bbf01125de..5b40d625fadb 100644 --- a/source/extensions/config_subscription/grpc/watch_map.cc +++ b/source/extensions/config_subscription/grpc/watch_map.cc @@ -96,7 +96,7 @@ absl::flat_hash_set WatchMap::watchesInterestedIn(const std::string& res // operations, but this implementation provides a reference for later optimization while we // adopt xdstp://. auto resource_or_error = XdsResourceIdentifier::decodeUrn(resource_name); - THROW_IF_STATUS_NOT_OK(resource_or_error, throw); + THROW_IF_NOT_OK_REF(resource_or_error.status()); xdstp_resource = resource_or_error.value(); } auto watches_interested = watch_interest_.find( diff --git a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc index 9269df1d37df..273fb0081040 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc @@ -167,7 +167,7 @@ void GrpcMuxImpl::updateWatch(const std::string& type_url, Watch* for (const auto& resource : resources) { if (XdsResourceIdentifier::hasXdsTpScheme(resource)) { auto xdstp_resource_or_error = XdsResourceIdentifier::decodeUrn(resource); - THROW_IF_STATUS_NOT_OK(xdstp_resource_or_error, throw); + THROW_IF_NOT_OK_REF(xdstp_resource_or_error.status()); auto xdstp_resource = xdstp_resource_or_error.value(); if (options.add_xdstp_node_context_params_) { const auto context = XdsContextParams::encodeResource( @@ -456,7 +456,7 @@ class DeltaGrpcMuxFactory : public MuxFactory { XdsResourcesDelegateOptRef, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client=*/std::move(failover_async_client), @@ -495,7 +495,7 @@ class SotwGrpcMuxFactory : public MuxFactory { XdsResourcesDelegateOptRef, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client_=*/std::move(failover_async_client), diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index 8c1175d929a7..e8ddaf2a8bb7 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -248,6 +248,7 @@ EXTENSIONS = { "envoy.resource_monitors.fixed_heap": "//source/extensions/resource_monitors/fixed_heap:config", "envoy.resource_monitors.injected_resource": "//source/extensions/resource_monitors/injected_resource:config", "envoy.resource_monitors.global_downstream_max_connections": "//source/extensions/resource_monitors/downstream_connections:config", + "envoy.resource_monitors.cpu_utilization": "//source/extensions/resource_monitors/cpu_utilization:config", # # Stat sinks diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 894d9939c149..8bde25426929 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -1077,6 +1077,13 @@ envoy.request_id.uuid: status: stable type_urls: - envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig +envoy.resource_monitors.cpu_utilization: + categories: + - envoy.resource_monitors + security_posture: data_plane_agnostic + status: alpha + type_urls: + - envoy.extensions.resource_monitors.cpu_utilization.v3.CpuUtilizationConfig envoy.resource_monitors.global_downstream_max_connections: categories: - envoy.resource_monitors diff --git a/source/extensions/filters/common/ratelimit/ratelimit_impl.cc b/source/extensions/filters/common/ratelimit/ratelimit_impl.cc index a72fa1b81661..3350e132562a 100644 --- a/source/extensions/filters/common/ratelimit/ratelimit_impl.cc +++ b/source/extensions/filters/common/ratelimit/ratelimit_impl.cc @@ -132,7 +132,7 @@ ClientPtr rateLimitClient(Server::Configuration::FactoryContext& context, .clusterManager() .grpcAsyncClientManager() .getOrCreateRawAsyncClientWithHashKey(config_with_hash_key, context.scope(), true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); return std::make_unique(client_or_error.value(), timeout); } diff --git a/source/extensions/filters/http/common/jwks_fetcher.cc b/source/extensions/filters/http/common/jwks_fetcher.cc index 70cdbbc4c77b..fa281f973520 100644 --- a/source/extensions/filters/http/common/jwks_fetcher.cc +++ b/source/extensions/filters/http/common/jwks_fetcher.cc @@ -57,6 +57,7 @@ class JwksFetcherImpl : public JwksFetcher, Http::RequestMessagePtr message = Http::Utility::prepareHeaders(remote_jwks_.http_uri()); message->headers().setReferenceMethod(Http::Headers::get().MethodValues.Get); + message->headers().setReferenceUserAgent(Http::Headers::get().UserAgentValues.GoBrowser); ENVOY_LOG(debug, "fetch pubkey from [uri = {}]: start", remote_jwks_.http_uri().uri()); auto options = Http::AsyncClient::RequestOptions() .setTimeout(std::chrono::milliseconds( diff --git a/source/extensions/filters/http/composite/action.cc b/source/extensions/filters/http/composite/action.cc index 27cfe9e6f28e..9d70c9c10671 100644 --- a/source/extensions/filters/http/composite/action.cc +++ b/source/extensions/filters/http/composite/action.cc @@ -115,7 +115,7 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createStaticActionFactoryCb if (context.factory_context_.has_value()) { auto callback_or_status = factory.createFilterFactoryFromProto( *message, context.stat_prefix_, context.factory_context_.value()); - THROW_IF_STATUS_NOT_OK(callback_or_status, throw); + THROW_IF_NOT_OK_REF(callback_or_status.status()); callback = callback_or_status.value(); } @@ -146,7 +146,7 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createStaticActionFactoryCb if (context.upstream_factory_context_.has_value()) { auto callback_or_status = factory.createFilterFactoryFromProto( *message, context.stat_prefix_, context.upstream_factory_context_.value()); - THROW_IF_STATUS_NOT_OK(callback_or_status, throw); + THROW_IF_NOT_OK_REF(callback_or_status.status()); callback = callback_or_status.value(); } diff --git a/source/extensions/filters/http/cors/BUILD b/source/extensions/filters/http/cors/BUILD index 1896cc73c5d9..60b5e0d42aae 100644 --- a/source/extensions/filters/http/cors/BUILD +++ b/source/extensions/filters/http/cors/BUILD @@ -27,6 +27,7 @@ envoy_cc_library( "//source/common/common:enum_to_int", "//source/common/http:header_map_lib", "//source/common/http:headers_lib", + "//source/common/http:utility_lib", ], ) diff --git a/source/extensions/filters/http/cors/cors_filter.cc b/source/extensions/filters/http/cors/cors_filter.cc index 4cc33d7d116e..98ecb2a17c02 100644 --- a/source/extensions/filters/http/cors/cors_filter.cc +++ b/source/extensions/filters/http/cors/cors_filter.cc @@ -10,6 +10,7 @@ #include "source/common/common/enum_to_int.h" #include "source/common/http/header_map_impl.h" #include "source/common/http/headers.h" +#include "source/common/http/utility.h" namespace Envoy { namespace Extensions { @@ -53,14 +54,9 @@ CorsFilterConfig::CorsFilterConfig(const std::string& stats_prefix, Stats::Scope CorsFilter::CorsFilter(CorsFilterConfigSharedPtr config) : config_(std::move(config)) {} void CorsFilter::initializeCorsPolicies() { - decoder_callbacks_->traversePerFilterConfig([this](const Router::RouteSpecificFilterConfig& cfg) { - const auto* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg != nullptr) { - policies_.push_back(typed_cfg); - } - }); + policies_ = Http::Utility::getAllPerFilterConfig(decoder_callbacks_); - // The 'traversePerFilterConfig' will handle cors policy of virtual host first. So, we need + // The 'perFilterConfigs' will handle cors policy of virtual host first. So, we need // reverse the 'policies_' to make sure the cors policy of route entry to be first item in the // 'policies_'. if (policies_.size() >= 2) { diff --git a/source/extensions/filters/http/cors/cors_filter.h b/source/extensions/filters/http/cors/cors_filter.h index 4e0187a5e902..0c8cf535a9c6 100644 --- a/source/extensions/filters/http/cors/cors_filter.h +++ b/source/extensions/filters/http/cors/cors_filter.h @@ -83,9 +83,7 @@ class CorsFilter : public Http::StreamFilter { encoder_callbacks_ = &callbacks; }; - const absl::InlinedVector& policiesForTest() const { - return policies_; - } + const auto& policiesForTest() const { return policies_; } private: friend class CorsFilterTest; @@ -104,7 +102,7 @@ class CorsFilter : public Http::StreamFilter { Http::StreamDecoderFilterCallbacks* decoder_callbacks_{}; Http::StreamEncoderFilterCallbacks* encoder_callbacks_{}; - absl::InlinedVector policies_; + absl::InlinedVector policies_; bool is_cors_request_{}; std::string latched_origin_; diff --git a/source/extensions/filters/http/custom_response/custom_response_filter.cc b/source/extensions/filters/http/custom_response/custom_response_filter.cc index 7e58ad4bbfc4..d133c8b75315 100644 --- a/source/extensions/filters/http/custom_response/custom_response_filter.cc +++ b/source/extensions/filters/http/custom_response/custom_response_filter.cc @@ -48,18 +48,18 @@ Http::FilterHeadersStatus CustomResponseFilter::encodeHeaders(Http::ResponseHead // policy. Note that since the traversal is least to most specific, we can't // return early when a match is found. PolicySharedPtr policy; - decoder_callbacks_->traversePerFilterConfig( - [&policy, &headers, this](const Router::RouteSpecificFilterConfig& config) { - const FilterConfig* typed_config = dynamic_cast(&config); - if (typed_config) { - // Check if a match is found first to avoid overwriting policy with an - // empty shared_ptr. - auto maybe_policy = typed_config->getPolicy(headers, encoder_callbacks_->streamInfo()); - if (maybe_policy) { - policy = maybe_policy; - } - } - }); + for (const auto* typed_config : + Http::Utility::getAllPerFilterConfig(encoder_callbacks_)) { + ASSERT(typed_config != nullptr); + + // Check if a match is found first to avoid overwriting policy with an + // empty shared_ptr. + auto maybe_policy = typed_config->getPolicy(headers, encoder_callbacks_->streamInfo()); + if (maybe_policy) { + policy = maybe_policy; + } + } + if (!policy) { policy = config_->getPolicy(headers, encoder_callbacks_->streamInfo()); } diff --git a/source/extensions/filters/http/ext_authz/config.cc b/source/extensions/filters/http/ext_authz/config.cc index 949d3f4654db..bfdab7fe36f2 100644 --- a/source/extensions/filters/http/ext_authz/config.cc +++ b/source/extensions/filters/http/ext_authz/config.cc @@ -54,7 +54,7 @@ Http::FilterFactoryCb ExtAuthzFilterConfig::createFilterFactoryFromProtoWithServ .grpcAsyncClientManager() .getOrCreateRawAsyncClientWithHashKey( config_with_hash_key, server_context.scope(), true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); auto client = std::make_unique( client_or_error.value(), std::chrono::milliseconds(timeout_ms)); callbacks.addStreamFilter(std::make_shared(filter_config, std::move(client))); diff --git a/source/extensions/filters/http/ext_authz/ext_authz.cc b/source/extensions/filters/http/ext_authz/ext_authz.cc index d301d12689c8..92bde93d3758 100644 --- a/source/extensions/filters/http/ext_authz/ext_authz.cc +++ b/source/extensions/filters/http/ext_authz/ext_authz.cc @@ -1,3 +1,4 @@ +#include "ext_authz.h" #include "source/extensions/filters/http/ext_authz/ext_authz.h" #include @@ -175,11 +176,16 @@ void Filter::initiateCall(const Http::RequestHeaderMap& headers) { return; } - auto&& maybe_merged_per_route_config = - Http::Utility::getMergedPerFilterConfig( - decoder_callbacks_, [](FilterConfigPerRoute& cfg_base, const FilterConfigPerRoute& cfg) { - cfg_base.merge(cfg); - }); + absl::optional maybe_merged_per_route_config; + for (const auto* cfg : + Http::Utility::getAllPerFilterConfig(decoder_callbacks_)) { + ASSERT(cfg != nullptr); + if (maybe_merged_per_route_config.has_value()) { + maybe_merged_per_route_config.value().merge(*cfg); + } else { + maybe_merged_per_route_config = *cfg; + } + } Protobuf::Map context_extensions; if (maybe_merged_per_route_config) { diff --git a/source/extensions/filters/http/ext_proc/client_impl.cc b/source/extensions/filters/http/ext_proc/client_impl.cc index 8bfc80bc5908..fef44968dc5d 100644 --- a/source/extensions/filters/http/ext_proc/client_impl.cc +++ b/source/extensions/filters/http/ext_proc/client_impl.cc @@ -18,7 +18,7 @@ ExternalProcessorStreamPtr ExternalProcessorClientImpl::start( Http::StreamFilterSidestreamWatermarkCallbacks& sidestream_watermark_callbacks) { auto client_or_error = client_manager_.getOrCreateRawAsyncClientWithHashKey(config_with_hash_key, scope_, true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); Grpc::AsyncClient grpcClient(client_or_error.value()); return ExternalProcessorStreamImpl::create(std::move(grpcClient), callbacks, options, sidestream_watermark_callbacks); diff --git a/source/extensions/filters/http/ext_proc/config.cc b/source/extensions/filters/http/ext_proc/config.cc index bd184557e191..134fa8d190b2 100644 --- a/source/extensions/filters/http/ext_proc/config.cc +++ b/source/extensions/filters/http/ext_proc/config.cc @@ -23,8 +23,8 @@ ExternalProcessingFilterConfig::createFilterFactoryFromProtoTyped( dual_info.scope, stats_prefix, dual_info.is_upstream, Envoy::Extensions::Filters::Common::Expr::getBuilder(context), context); - return [filter_config, grpc_service = proto_config.grpc_service(), &context, - dual_info](Http::FilterChainFactoryCallbacks& callbacks) { + return [filter_config = std::move(filter_config), grpc_service = proto_config.grpc_service(), + &context, dual_info](Http::FilterChainFactoryCallbacks& callbacks) { auto client = std::make_unique( context.clusterManager().grpcAsyncClientManager(), dual_info.scope); @@ -54,7 +54,7 @@ ExternalProcessingFilterConfig::createFilterFactoryFromProtoWithServerContextTyp server_context.scope(), stats_prefix, false, Envoy::Extensions::Filters::Common::Expr::getBuilder(server_context), server_context); - return [filter_config, grpc_service = proto_config.grpc_service(), + return [filter_config = std::move(filter_config), grpc_service = proto_config.grpc_service(), &server_context](Http::FilterChainFactoryCallbacks& callbacks) { auto client = std::make_unique( server_context.clusterManager().grpcAsyncClientManager(), server_context.scope()); diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 7e8f4f138652..8af46dc4da98 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -1279,20 +1279,15 @@ void Filter::mergePerRouteConfig() { route_config_merged_ = true; absl::optional merged_config; - - decoder_callbacks_->traversePerFilterConfig([&merged_config]( - const Router::RouteSpecificFilterConfig& cfg) { - const FilterConfigPerRoute* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg == nullptr) { - ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); - return; - } + for (const auto* typed_cfg : + Http::Utility::getAllPerFilterConfig(decoder_callbacks_)) { + ASSERT(typed_cfg != nullptr); if (!merged_config.has_value()) { merged_config.emplace(*typed_cfg); } else { merged_config.emplace(FilterConfigPerRoute(merged_config.value(), *typed_cfg)); } - }); + } if (!merged_config.has_value()) { return; diff --git a/source/extensions/filters/http/file_system_buffer/filter.cc b/source/extensions/filters/http/file_system_buffer/filter.cc index a4e5e38f4295..56764975b057 100644 --- a/source/extensions/filters/http/file_system_buffer/filter.cc +++ b/source/extensions/filters/http/file_system_buffer/filter.cc @@ -1,3 +1,4 @@ +#include "filter.h" #include "source/extensions/filters/http/file_system_buffer/filter.h" namespace Envoy { @@ -20,12 +21,13 @@ bool FileSystemBufferFilter::initPerRouteConfig() { auto route = request_callbacks_->route(); FilterConfigVector config_chain; if (route) { - route->traversePerFilterConfig( - FileSystemBufferFilter::filterName(), - [&config_chain](const Router::RouteSpecificFilterConfig& route_cfg) { - auto cfg = dynamic_cast(&route_cfg); - config_chain.emplace_back(*cfg); - }); + // TODO(wbpcode): fix this to use the callbacks to get the route specific configs. + for (const auto* cfg : route->perFilterConfigs(FileSystemBufferFilter::filterName())) { + auto typed_cfg = dynamic_cast(cfg); + if (typed_cfg) { + config_chain.emplace_back(*typed_cfg); + } + } } config_chain.emplace_back(*base_config_); config_.emplace(config_chain); diff --git a/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc b/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc index 63be1f6fe24a..2ffc80e63720 100644 --- a/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc +++ b/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc @@ -124,7 +124,7 @@ JsonTranscoderConfig::JsonTranscoderConfig( case envoy::extensions::filters::http::grpc_json_transcoder::v3::GrpcJsonTranscoder:: DescriptorSetCase::kProtoDescriptor: { auto file_or_error = api.fileSystem().fileReadToEnd(proto_config.proto_descriptor()); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); if (!descriptor_set.ParseFromString(file_or_error.value())) { throw EnvoyException("transcoding_filter: Unable to parse proto descriptor"); } diff --git a/source/extensions/filters/http/header_mutation/header_mutation.h b/source/extensions/filters/http/header_mutation/header_mutation.h index 6701a4b219d1..5286d8340471 100644 --- a/source/extensions/filters/http/header_mutation/header_mutation.h +++ b/source/extensions/filters/http/header_mutation/header_mutation.h @@ -82,7 +82,7 @@ class HeaderMutation : public Http::PassThroughFilter, public Logger::Loggable route_configs_{}; + absl::InlinedVector route_configs_{}; }; } // namespace HeaderMutation diff --git a/source/extensions/filters/http/rate_limit_quota/client_impl.cc b/source/extensions/filters/http/rate_limit_quota/client_impl.cc index 92390ea8a302..7d886a49e7b3 100644 --- a/source/extensions/filters/http/rate_limit_quota/client_impl.cc +++ b/source/extensions/filters/http/rate_limit_quota/client_impl.cc @@ -9,7 +9,7 @@ namespace RateLimitQuota { Grpc::RawAsyncClientSharedPtr getOrThrow(absl::StatusOr client_or_error) { - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); return client_or_error.value(); } diff --git a/source/extensions/filters/network/ext_authz/config.cc b/source/extensions/filters/network/ext_authz/config.cc index b4d62365d02f..ab0560664863 100644 --- a/source/extensions/filters/network/ext_authz/config.cc +++ b/source/extensions/filters/network/ext_authz/config.cc @@ -34,7 +34,7 @@ Network::FilterFactoryCb ExtAuthzConfigFactory::createFilterFactoryFromProtoType .clusterManager() .grpcAsyncClientManager() .factoryForGrpcService(grpc_service, context.scope(), true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); auto client = std::make_unique( factory_or_error.value()->createUncachedRawAsyncClient(), std::chrono::milliseconds(timeout_ms)); diff --git a/source/extensions/filters/network/mongo_proxy/proxy.cc b/source/extensions/filters/network/mongo_proxy/proxy.cc index 87f9b6a073d6..fd56c5caa8a7 100644 --- a/source/extensions/filters/network/mongo_proxy/proxy.cc +++ b/source/extensions/filters/network/mongo_proxy/proxy.cc @@ -39,7 +39,7 @@ AccessLog::AccessLog(const std::string& file_name, Envoy::AccessLog::AccessLogMa : time_source_(time_source) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, file_name}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } diff --git a/source/extensions/filters/network/redis_proxy/config.cc b/source/extensions/filters/network/redis_proxy/config.cc index ebae3bee724a..9e45c04a3d4f 100644 --- a/source/extensions/filters/network/redis_proxy/config.cc +++ b/source/extensions/filters/network/redis_proxy/config.cc @@ -111,7 +111,7 @@ Network::FilterFactoryCb RedisProxyFilterConfigFactory::createFilterFactoryFromP .clusterManager() .grpcAsyncClientManager() .factoryForGrpcService(grpc_service, context.scope(), true); - THROW_IF_STATUS_NOT_OK(auth_client_factory_or_error, throw); + THROW_IF_NOT_OK_REF(auth_client_factory_or_error.status()); auth_client = std::make_unique( auth_client_factory_or_error.value()->createUncachedRawAsyncClient(), 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 af3407c3d727..fd6f87d7d200 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 @@ -22,7 +22,7 @@ ProxyFilterConfig::ProxyFilterConfig( : port_(static_cast(proto_config.port_value())), dns_cache_manager_(cache_manager_factory.get()) { auto cache_or_error = dns_cache_manager_->getCache(proto_config.dns_cache_config()); - THROW_IF_STATUS_NOT_OK(cache_or_error, throw); + THROW_IF_NOT_OK_REF(cache_or_error.status()); dns_cache_ = std::move(cache_or_error.value()); } diff --git a/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc b/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc index 00cd4298aa4a..abfd730e61a4 100644 --- a/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc +++ b/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc @@ -36,7 +36,7 @@ ProxyFilterConfig::ProxyFilterConfig( DefaultMaxBufferedBytes) : DefaultMaxBufferedBytes) { auto cache_or_error = dns_cache_manager_->getCache(config.dns_cache_config()); - THROW_IF_STATUS_NOT_OK(cache_or_error, throw); + THROW_IF_NOT_OK_REF(cache_or_error.status()); dns_cache_ = std::move(cache_or_error.value()); } 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 index b2e51da4f778..712e0fe2964f 100644 --- a/source/extensions/health_check/event_sinks/file/file_sink_impl.h +++ b/source/extensions/health_check/event_sinks/file/file_sink_impl.h @@ -16,7 +16,7 @@ class HealthCheckEventFileSink : public HealthCheckEventSink { AccessLog::AccessLogManager& log_manager) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, config.event_log_path()}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } diff --git a/source/extensions/health_checkers/http/health_checker_impl.cc b/source/extensions/health_checkers/http/health_checker_impl.cc index 88c02582abdd..bcbed8bd861e 100644 --- a/source/extensions/health_checkers/http/health_checker_impl.cc +++ b/source/extensions/health_checkers/http/health_checker_impl.cc @@ -76,7 +76,7 @@ HttpHealthCheckerImpl::HttpHealthCheckerImpl( // TODO(boteng): introduce additional validation for the authority and path headers // based on the default UHV when it is available. auto bytes_or_error = PayloadMatcher::loadProtoBytes(config.http_health_check().receive()); - THROW_IF_STATUS_NOT_OK(bytes_or_error, throw); + THROW_IF_NOT_OK_REF(bytes_or_error.status()); receive_bytes_ = bytes_or_error.value(); if (config.http_health_check().has_service_name_matcher()) { service_name_matcher_.emplace(config.http_health_check().service_name_matcher(), diff --git a/source/extensions/health_checkers/tcp/health_checker_impl.cc b/source/extensions/health_checkers/tcp/health_checker_impl.cc index 585df883a571..d1c75e45531b 100644 --- a/source/extensions/health_checkers/tcp/health_checker_impl.cc +++ b/source/extensions/health_checkers/tcp/health_checker_impl.cc @@ -55,7 +55,7 @@ TcpHealthCheckerImpl::TcpHealthCheckerImpl(const Cluster& cluster, send_repeated.Add()->CopyFrom(config.tcp_health_check().send()); } auto bytes_or_error = PayloadMatcher::loadProtoBytes(send_repeated); - THROW_IF_STATUS_NOT_OK(bytes_or_error, throw); + THROW_IF_NOT_OK_REF(bytes_or_error.status()); return bytes_or_error.value(); }()), proxy_protocol_config_(config.tcp_health_check().has_proxy_protocol_config() @@ -63,7 +63,7 @@ TcpHealthCheckerImpl::TcpHealthCheckerImpl(const Cluster& cluster, config.tcp_health_check().proxy_protocol_config()) : nullptr) { auto bytes_or_error = PayloadMatcher::loadProtoBytes(config.tcp_health_check().receive()); - THROW_IF_STATUS_NOT_OK(bytes_or_error, throw); + THROW_IF_NOT_OK_REF(bytes_or_error.status()); receive_bytes_ = bytes_or_error.value(); } diff --git a/source/extensions/key_value/file_based/config.cc b/source/extensions/key_value/file_based/config.cc index 195f07f6c0ed..0822c6a71c2e 100644 --- a/source/extensions/key_value/file_based/config.cc +++ b/source/extensions/key_value/file_based/config.cc @@ -17,7 +17,7 @@ FileBasedKeyValueStore::FileBasedKeyValueStore(Event::Dispatcher& dispatcher, return; } auto file_or_error = file_system_.fileReadToEnd(filename_); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const std::string contents = file_or_error.value(); if (!parseContents(contents)) { ENVOY_LOG(warn, "Failed to parse key value store file {}", filename); diff --git a/source/extensions/resource_monitors/cpu_utilization/BUILD b/source/extensions/resource_monitors/cpu_utilization/BUILD new file mode 100644 index 000000000000..c629250fa278 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/BUILD @@ -0,0 +1,59 @@ +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 = "cpu_utilization_monitor", + srcs = ["cpu_utilization_monitor.cc"], + hdrs = [ + "cpu_stats_reader.h", + "cpu_utilization_monitor.h", + ], + tags = ["skip_on_windows"], + deps = [ + "//envoy/common:exception_lib", + "//envoy/server:resource_monitor_config_interface", + "//source/common/runtime:runtime_features_lib", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) + +envoy_cc_library( + name = "linux_cpu_stats_reader", + srcs = ["linux_cpu_stats_reader.cc"], + hdrs = [ + "cpu_stats_reader.h", + "cpu_utilization_monitor.h", + "linux_cpu_stats_reader.h", + ], + tags = ["skip_on_windows"], + deps = [ + "//source/common/common:logger_lib", + "@com_google_absl//absl/strings", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + tags = ["skip_on_windows"], + deps = [ + ":cpu_utilization_monitor", + ":linux_cpu_stats_reader", + "//envoy/registry", + "//envoy/server:resource_monitor_config_interface", + "//source/common/common:logger_lib", + "//source/extensions/resource_monitors/common:factory_base_lib", + "//source/server:configuration_lib", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/resource_monitors/cpu_utilization/config.cc b/source/extensions/resource_monitors/cpu_utilization/config.cc new file mode 100644 index 000000000000..f04efa9187d6 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/config.cc @@ -0,0 +1,32 @@ +#include "source/extensions/resource_monitors/cpu_utilization/config.h" + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.validate.h" +#include "envoy/registry/registry.h" + +#include "source/common/protobuf/utility.h" +#include "source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h" +#include "source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +Server::ResourceMonitorPtr CpuUtilizationMonitorFactory::createResourceMonitorFromProtoTyped( + const envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig& config, + Server::Configuration::ResourceMonitorFactoryContext& /*unused_context*/) { + // In the future, the below can be configurable based on the operating system. + auto cpu_stats_reader = std::make_unique(); + return std::make_unique(config, std::move(cpu_stats_reader)); +} + +/** + * Static registration for the cpu resource monitor factory. @see RegistryFactory. + */ +REGISTER_FACTORY(CpuUtilizationMonitorFactory, Server::Configuration::ResourceMonitorFactory); + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/config.h b/source/extensions/resource_monitors/cpu_utilization/config.h new file mode 100644 index 000000000000..fb7ec2dbda9e --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/config.h @@ -0,0 +1,29 @@ +#pragma once + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.validate.h" +#include "envoy/server/resource_monitor_config.h" + +#include "source/extensions/resource_monitors/common/factory_base.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +class CpuUtilizationMonitorFactory + : public Common::FactoryBase< + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig> { +public: + CpuUtilizationMonitorFactory() : FactoryBase("envoy.resource_monitors.cpu_utilization") {} + +private: + Server::ResourceMonitorPtr createResourceMonitorFromProtoTyped( + const envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig& config, + Server::Configuration::ResourceMonitorFactoryContext& context) override; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h b/source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h new file mode 100644 index 000000000000..60aff11e13e8 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#include "source/common/common/logger.h" + +#include "absl/strings/str_split.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +struct CpuTimes { + bool is_valid; + uint64_t work_time; + uint64_t total_time; +}; + +class CpuStatsReader { +public: + CpuStatsReader() = default; + virtual ~CpuStatsReader() = default; + virtual CpuTimes getCpuTimes() = 0; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.cc b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.cc new file mode 100644 index 000000000000..6ff035430bd1 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.cc @@ -0,0 +1,72 @@ +#include "source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "source/common/common/fmt.h" + +#include "absl/strings/str_split.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +// The dampening alpha value used for EWMA calculation. +// The value is chosen to be very small to give past calculations higher priority. +// This helps in reducing the impact of sudden spikes or drops in CPU utilization. +constexpr double DAMPENING_ALPHA = 0.05; + +CpuUtilizationMonitor::CpuUtilizationMonitor( + const envoy::extensions::resource_monitors::cpu_utilization::v3:: + CpuUtilizationConfig& /*config*/, + std::unique_ptr cpu_stats_reader) + : utilization_(0.0), cpu_stats_reader_(std::move(cpu_stats_reader)) { + previous_cpu_times_ = cpu_stats_reader_->getCpuTimes(); +} + +void CpuUtilizationMonitor::updateResourceUsage(Server::ResourceUpdateCallbacks& callbacks) { + CpuTimes cpu_times = cpu_stats_reader_->getCpuTimes(); + if (!cpu_times.is_valid) { + const auto& error = EnvoyException("Can't open file to read CPU utilization"); + callbacks.onFailure(error); + return; + } + + const int64_t work_over_period = cpu_times.work_time - previous_cpu_times_.work_time; + const int64_t total_over_period = cpu_times.total_time - previous_cpu_times_.total_time; + if (work_over_period < 0 || total_over_period <= 0) { + const auto& error = EnvoyException( + fmt::format("Erroneous CPU stats calculation. Work_over_period='{}' cannot " + "be a negative number and total_over_period='{}' must be a positive number.", + work_over_period, total_over_period)); + callbacks.onFailure(error); + return; + } + const double current_utilization = static_cast(work_over_period) / total_over_period; + ENVOY_LOG_MISC(trace, "Prev work={}, Cur work={}, Prev Total={}, Cur Total={}", + previous_cpu_times_.work_time, cpu_times.work_time, previous_cpu_times_.total_time, + cpu_times.total_time); + // The new utilization is calculated/smoothed using EWMA + utilization_ = current_utilization * DAMPENING_ALPHA + (1 - DAMPENING_ALPHA) * utilization_; + + Server::ResourceUsage usage; + usage.resource_pressure_ = utilization_; + + callbacks.onSuccess(usage); + + previous_cpu_times_ = cpu_times; +} + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h new file mode 100644 index 000000000000..c23197695457 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/server/resource_monitor.h" + +#include "source/common/runtime/runtime_features.h" +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +class CpuUtilizationMonitor : public Server::ResourceMonitor { +public: + CpuUtilizationMonitor( + const envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig& config, + std::unique_ptr cpu_stats_reader); + + void updateResourceUsage(Server::ResourceUpdateCallbacks& callbacks) override; + +private: + double utilization_; + CpuTimes previous_cpu_times_; + std::unique_ptr cpu_stats_reader_; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.cc b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.cc new file mode 100644 index 000000000000..c5a9e75ea20f --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.cc @@ -0,0 +1,53 @@ +#include "source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h" + +#include +#include + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +constexpr uint64_t NUMBER_OF_CPU_TIMES_TO_PARSE = + 4; // we are interested in user, nice, system and idle times. + +LinuxCpuStatsReader::LinuxCpuStatsReader(const std::string& cpu_stats_filename) + : cpu_stats_filename_(cpu_stats_filename) {} + +CpuTimes LinuxCpuStatsReader::getCpuTimes() { + std::ifstream cpu_stats_file; + cpu_stats_file.open(cpu_stats_filename_); + if (!cpu_stats_file.is_open()) { + ENVOY_LOG_MISC(error, "Can't open linux cpu stats file {}", cpu_stats_filename_); + return {false, 0, 0}; + } + + // The first 5 bytes should be 'cpu ' without a cpu index. + std::string buffer(5, '\0'); + cpu_stats_file.read(buffer.data(), 5); + const std::string target = "cpu "; + if (!cpu_stats_file || buffer != target) { + ENVOY_LOG_MISC(error, "Unexpected format in linux cpu stats file {}", cpu_stats_filename_); + return {false, 0, 0}; + } + + std::array times; + for (uint64_t time, i = 0; i < NUMBER_OF_CPU_TIMES_TO_PARSE; ++i) { + cpu_stats_file >> time; + if (!cpu_stats_file) { + ENVOY_LOG_MISC(error, "Unexpected format in linux cpu stats file {}", cpu_stats_filename_); + return {false, 0, 0}; + } + times[i] = time; + } + + uint64_t work_time, total_time; + work_time = times[0] + times[1] + times[2]; // user + nice + system + total_time = work_time + times[3]; // idle + return {true, work_time, total_time}; +} + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h new file mode 100644 index 000000000000..4b6b7b5801a8 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +static const std::string LINUX_CPU_STATS_FILE = "/proc/stat"; + +class LinuxCpuStatsReader : public CpuStatsReader { +public: + LinuxCpuStatsReader(const std::string& cpu_stats_filename = LINUX_CPU_STATS_FILE); + CpuTimes getCpuTimes() override; + +private: + const std::string cpu_stats_filename_; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc b/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc index 8b02e398431d..589652b7e77c 100644 --- a/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc +++ b/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc @@ -31,7 +31,7 @@ void InjectedResourceMonitor::updateResourceUsage(Server::ResourceUpdateCallback file_changed_ = false; TRY_ASSERT_MAIN_THREAD { auto file_or_error = api_.fileSystem().fileReadToEnd(filename_); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const std::string contents = file_or_error.value(); double pressure; if (absl::SimpleAtod(contents, &pressure)) { diff --git a/source/extensions/stat_sinks/common/statsd/statsd.cc b/source/extensions/stat_sinks/common/statsd/statsd.cc index 25872589ca74..48f76c620821 100644 --- a/source/extensions/stat_sinks/common/statsd/statsd.cc +++ b/source/extensions/stat_sinks/common/statsd/statsd.cc @@ -197,7 +197,7 @@ TcpStatsdSink::TcpStatsdSink(const LocalInfo::LocalInfo& local_info, THROW_IF_NOT_OK(Config::Utility::checkLocalInfo("tcp statsd", local_info)); const auto cluster_or_error = Config::Utility::checkCluster("tcp statsd", cluster_name, cluster_manager); - THROW_IF_STATUS_NOT_OK(cluster_or_error, throw); + THROW_IF_NOT_OK_REF(cluster_or_error.status()); const auto cluster = cluster_or_error.value(); cluster_info_ = cluster->get().info(); tls_->set([this](Event::Dispatcher& dispatcher) -> ThreadLocal::ThreadLocalObjectSharedPtr { diff --git a/source/extensions/stat_sinks/dog_statsd/config.cc b/source/extensions/stat_sinks/dog_statsd/config.cc index 78c39f20d914..a3fd1941cbe1 100644 --- a/source/extensions/stat_sinks/dog_statsd/config.cc +++ b/source/extensions/stat_sinks/dog_statsd/config.cc @@ -23,7 +23,7 @@ DogStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, MessageUtil::downcastAndValidate( config, server.messageValidationContext().staticValidationVisitor()); auto address_or_error = Network::Address::resolveProtoAddress(sink_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "dog_statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; diff --git a/source/extensions/stat_sinks/graphite_statsd/config.cc b/source/extensions/stat_sinks/graphite_statsd/config.cc index 93322442900d..1afd0a8846c3 100644 --- a/source/extensions/stat_sinks/graphite_statsd/config.cc +++ b/source/extensions/stat_sinks/graphite_statsd/config.cc @@ -26,7 +26,7 @@ GraphiteStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, case envoy::extensions::stat_sinks::graphite_statsd::v3::GraphiteStatsdSink::StatsdSpecifierCase:: kAddress: { auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; diff --git a/source/extensions/stat_sinks/metrics_service/config.cc b/source/extensions/stat_sinks/metrics_service/config.cc index 791f81508f31..1463b8e943af 100644 --- a/source/extensions/stat_sinks/metrics_service/config.cc +++ b/source/extensions/stat_sinks/metrics_service/config.cc @@ -30,7 +30,7 @@ MetricsServiceSinkFactory::createStatsSink(const Protobuf::Message& config, auto client_or_error = server.clusterManager().grpcAsyncClientManager().getOrCreateRawAsyncClient( grpc_service, server.scope(), false); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); std::shared_ptr> grpc_metrics_streamer = diff --git a/source/extensions/stat_sinks/open_telemetry/config.cc b/source/extensions/stat_sinks/open_telemetry/config.cc index 2dc66d339aef..4b7e806fd018 100644 --- a/source/extensions/stat_sinks/open_telemetry/config.cc +++ b/source/extensions/stat_sinks/open_telemetry/config.cc @@ -29,7 +29,7 @@ OpenTelemetrySinkFactory::createStatsSink(const Protobuf::Message& config, auto client_or_error = server.clusterManager().grpcAsyncClientManager().getOrCreateRawAsyncClient( grpc_service, server.scope(), false); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); std::shared_ptr grpc_metrics_exporter = std::make_shared(otlp_options, client_or_error.value()); diff --git a/source/extensions/stat_sinks/statsd/config.cc b/source/extensions/stat_sinks/statsd/config.cc index ae76707892a0..47b26bbc6834 100644 --- a/source/extensions/stat_sinks/statsd/config.cc +++ b/source/extensions/stat_sinks/statsd/config.cc @@ -24,7 +24,7 @@ StatsdSinkFactory::createStatsSink(const Protobuf::Message& config, switch (statsd_sink.statsd_specifier_case()) { case envoy::config::metrics::v3::StatsdSink::StatsdSpecifierCase::kAddress: { auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); return std::make_unique(server.threadLocal(), std::move(address), diff --git a/source/extensions/tracers/datadog/tracer.cc b/source/extensions/tracers/datadog/tracer.cc index 280647595558..ae5b510f9c0f 100644 --- a/source/extensions/tracers/datadog/tracer.cc +++ b/source/extensions/tracers/datadog/tracer.cc @@ -63,9 +63,9 @@ Tracer::Tracer(const std::string& collector_cluster, const std::string& collecto thread_local_slot_( ThreadLocal::TypedSlot::makeUnique(thread_local_slot_allocator)) { const bool allow_added_via_api = true; - THROW_IF_STATUS_NOT_OK(Config::Utility::checkCluster("envoy.tracers.datadog", collector_cluster, - cluster_manager, allow_added_via_api), - throw); + THROW_IF_NOT_OK_REF(Config::Utility::checkCluster("envoy.tracers.datadog", collector_cluster, + cluster_manager, allow_added_via_api) + .status()); thread_local_slot_->set([&logger = ENVOY_LOGGER(), collector_cluster, collector_reference_host, config, &tracer_stats = tracer_stats_, &cluster_manager, diff --git a/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc b/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc index d3fe8624c65d..5d9a9ed7b62e 100644 --- a/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc +++ b/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc @@ -92,7 +92,7 @@ Driver::Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetr auto factory_or_error = factory_context.clusterManager().grpcAsyncClientManager().factoryForGrpcService( opentelemetry_config.grpc_service(), factory_context.scope(), true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); Grpc::AsyncClientFactoryPtr&& factory = std::move(factory_or_error.value()); const Grpc::RawAsyncClientSharedPtr& async_client_shared_ptr = factory->createUncachedRawAsyncClient(); diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc index d312b83f707d..5e73f32fe942 100644 --- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc +++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc @@ -38,7 +38,7 @@ Driver::Driver(const envoy::config::trace::v3::SkyWalkingConfig& proto_config, auto factory_or_error = factory_context.clusterManager().grpcAsyncClientManager().factoryForGrpcService( proto_config.grpc_service(), factory_context.scope(), true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); TracerPtr tracer = std::make_unique(std::make_unique( std::move(factory_or_error.value()), dispatcher, factory_context.api().randomGenerator(), tracing_stats_, config_.delayed_buffer_size(), config_.token())); diff --git a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc index 2fda60aca87d..88b0f5d57325 100644 --- a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc +++ b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc @@ -77,10 +77,10 @@ Driver::Driver(const envoy::config::trace::v3::ZipkinConfig& zipkin_config, POOL_COUNTER_PREFIX(scope, "tracing.zipkin."))}, tls_(tls.allocateSlot()), runtime_(runtime), local_info_(local_info), time_source_(time_source) { - THROW_IF_STATUS_NOT_OK(Config::Utility::checkCluster("envoy.tracers.zipkin", - zipkin_config.collector_cluster(), cm_, - /* allow_added_via_api */ true), - throw); + THROW_IF_NOT_OK_REF(Config::Utility::checkCluster("envoy.tracers.zipkin", + zipkin_config.collector_cluster(), cm_, + /* allow_added_via_api */ true) + .status()); cluster_ = zipkin_config.collector_cluster(); hostname_ = !zipkin_config.collector_hostname().empty() ? zipkin_config.collector_hostname() : zipkin_config.collector_cluster(); diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index b19238c8226b..ac23e376900d 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -102,7 +102,7 @@ void ValidationInstance::initialize(const Options& options, auto producer_or_error = Stats::TagProducerImpl::createTagProducer(bootstrap_.stats_config(), options_.statsTags()); - THROW_IF_STATUS_NOT_OK(producer_or_error, throw); + THROW_IF_NOT_OK_REF(producer_or_error.status()); if (!bootstrap_.node().user_agent_build_version().has_version()) { *bootstrap_.mutable_node()->mutable_user_agent_build_version() = VersionInfo::buildVersion(); } diff --git a/source/server/server.cc b/source/server/server.cc index a8fbc195549e..6b3418bb84e6 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -828,7 +828,7 @@ void InstanceBase::onRuntimeReady() { // HDS does not support xDS-Failover. auto factory_or_error = Config::Utility::factoryForGrpcApiConfigSource( *async_client_manager_, hds_config, *stats_store_.rootScope(), false, 0); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); hds_delegate_ = std::make_unique( serverFactoryContext(), *stats_store_.rootScope(), factory_or_error.value()->createUncachedRawAsyncClient(), stats_store_, diff --git a/test/common/http/async_client_impl_test.cc b/test/common/http/async_client_impl_test.cc index dab5f185d3dc..0885eb927d3a 100644 --- a/test/common/http/async_client_impl_test.cc +++ b/test/common/http/async_client_impl_test.cc @@ -2221,7 +2221,7 @@ class AsyncClientImplUnitTest : public AsyncClientImplTest { auto policy_or_error = Router::RetryPolicyImpl::create(proto_policy, ProtobufMessage::getNullValidationVisitor(), factory_context, client_.factory_context_); - THROW_IF_STATUS_NOT_OK(policy_or_error, throw); + THROW_IF_NOT_OK_REF(policy_or_error.status()); retry_policy_ = std::move(policy_or_error.value()); EXPECT_TRUE(retry_policy_.get()); @@ -2259,7 +2259,7 @@ class AsyncClientImplUnitTest : public AsyncClientImplTest { auto policy_or_error = Router::RetryPolicyImpl::create(proto_policy, ProtobufMessage::getNullValidationVisitor(), factory_context, client_.factory_context_); - THROW_IF_STATUS_NOT_OK(policy_or_error, throw); + THROW_IF_NOT_OK_REF(policy_or_error.status()); retry_policy_ = std::move(policy_or_error.value()); EXPECT_TRUE(retry_policy_.get()); diff --git a/test/common/http/conn_manager_impl_test_base.cc b/test/common/http/conn_manager_impl_test_base.cc index daa753103766..0b70e2057938 100644 --- a/test/common/http/conn_manager_impl_test_base.cc +++ b/test/common/http/conn_manager_impl_test_base.cc @@ -394,21 +394,15 @@ void HttpConnectionManagerImplMixin::expectOnDestroy(bool deferred) { for (auto filter : decoder_filters_) { EXPECT_CALL(*filter, onStreamComplete()); } - { - auto setup_filter_expect = [](MockStreamEncoderFilter* filter) { - EXPECT_CALL(*filter, onStreamComplete()); - }; - std::for_each(encoder_filters_.rbegin(), encoder_filters_.rend(), setup_filter_expect); + for (auto filter : encoder_filters_) { + EXPECT_CALL(*filter, onStreamComplete()); } for (auto filter : decoder_filters_) { EXPECT_CALL(*filter, onDestroy()); } - { - auto setup_filter_expect = [](MockStreamEncoderFilter* filter) { - EXPECT_CALL(*filter, onDestroy()); - }; - std::for_each(encoder_filters_.rbegin(), encoder_filters_.rend(), setup_filter_expect); + for (auto filter : encoder_filters_) { + EXPECT_CALL(*filter, onDestroy()); } if (deferred) { diff --git a/test/common/http/filter_manager_test.cc b/test/common/http/filter_manager_test.cc index d310d73873db..417de64780df 100644 --- a/test/common/http/filter_manager_test.cc +++ b/test/common/http/filter_manager_test.cc @@ -461,24 +461,18 @@ TEST_F(FilterManagerTest, GetRouteLevelFilterConfig) { EXPECT_EQ(nullptr, decoder_filter->callbacks_->mostSpecificPerFilterConfig()); // Get a valid config by the custom filter name. - EXPECT_CALL(*route, traversePerFilterConfig(testing::Eq("custom-name"), _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(*route_config); + EXPECT_CALL(*route, perFilterConfigs(testing::Eq("custom-name"))) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {route_config.get()}; })); - decoder_filter->callbacks_->traversePerFilterConfig( - [&](const Router::RouteSpecificFilterConfig& config) { - EXPECT_EQ(route_config.get(), &config); - }); + auto route_config_result = decoder_filter->callbacks_->perFilterConfigs(); + EXPECT_EQ(route_config.get(), route_config_result[0]); // Get nothing by the custom filter name. - EXPECT_CALL(*route, traversePerFilterConfig(testing::Eq("custom-name"), _)) - .WillOnce(Invoke([&](const std::string&, - std::function) {})); - decoder_filter->callbacks_->traversePerFilterConfig( - [&](const Router::RouteSpecificFilterConfig& config) { - EXPECT_EQ(route_config.get(), &config); - }); + EXPECT_CALL(*route, perFilterConfigs(testing::Eq("custom-name"))) + .WillOnce(Invoke([](absl::string_view) -> Router::RouteSpecificFilterConfigs { return {}; })); + route_config_result = decoder_filter->callbacks_->perFilterConfigs(); + EXPECT_TRUE(route_config_result.empty()); filter_manager_->destroyFilters(); }; @@ -507,8 +501,7 @@ TEST_F(FilterManagerTest, GetRouteLevelFilterConfigForNullRoute) { decoder_filter->callbacks_->mostSpecificPerFilterConfig(); EXPECT_CALL(downstream_callbacks, route(_)).WillOnce(Return(nullptr)); - decoder_filter->callbacks_->traversePerFilterConfig( - [](const Router::RouteSpecificFilterConfig&) {}); + decoder_filter->callbacks_->perFilterConfigs(); filter_manager_->destroyFilters(); } diff --git a/test/common/http/utility_test.cc b/test/common/http/utility_test.cc index 74a5f963a697..69e63853b79e 100644 --- a/test/common/http/utility_test.cc +++ b/test/common/http/utility_test.cc @@ -1237,58 +1237,6 @@ TEST(HttpUtility, ResolveMostSpecificPerFilterConfigNilRoute) { EXPECT_EQ(nullptr, Utility::resolveMostSpecificPerFilterConfig(&filter_callbacks)); } -// Verify that merging works as expected and we get back the merged result. -TEST(HttpUtility, GetMergedPerFilterConfig) { - TestConfig baseTestConfig, routeTestConfig; - - baseTestConfig.state_ = 1; - routeTestConfig.state_ = 1; - - NiceMock filter_callbacks; - - EXPECT_CALL(*filter_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(baseTestConfig); - cb(routeTestConfig); - })); - - // merge the configs - auto merged_cfg = Utility::getMergedPerFilterConfig( - &filter_callbacks, - [&](TestConfig& base_cfg, const TestConfig& route_cfg) { base_cfg.merge(route_cfg); }); - - // make sure that the callback was called (which means that the dynamic_cast worked.) - ASSERT_TRUE(merged_cfg.has_value()); - EXPECT_EQ(2, merged_cfg.value().state_); -} - -class BadConfig { -public: - int state_; - void merge(const BadConfig& other) { state_ += other.state_; } -}; - -// Verify that merging result is empty as expected when the bad config is provided. -TEST(HttpUtility, GetMergedPerFilterBadConfig) { - TestConfig testConfig; - NiceMock filter_callbacks; - - EXPECT_CALL(*filter_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(testConfig); - })); - - EXPECT_LOG_CONTAINS( - "debug", "Failed to retrieve the correct type of route specific filter config", - auto merged_cfg = Utility::getMergedPerFilterConfig( - &filter_callbacks, - [&](BadConfig& base_cfg, const BadConfig& route_cfg) { base_cfg.merge(route_cfg); }); - // Dynamic_cast failed, so merged_cfg is not set. - ASSERT_FALSE(merged_cfg.has_value());); -} - TEST(HttpUtility, CheckIsIpAddress) { std::array>, 15> patterns{ std::make_tuple(true, "1.2.3.4", "1.2.3.4", absl::nullopt), diff --git a/test/common/json/json_streamer_test.cc b/test/common/json/json_streamer_test.cc index 231fc33d1ba7..8bf9913101c2 100644 --- a/test/common/json/json_streamer_test.cc +++ b/test/common/json/json_streamer_test.cc @@ -11,124 +11,183 @@ namespace Envoy { namespace Json { namespace { -class JsonStreamerTest : public testing::Test { -protected: - Buffer::OwnedImpl buffer_; - Json::Streamer streamer_{buffer_}; +class BufferOutputWrapper { +public: + using Type = BufferOutput; + std::string toString() { return underlying_buffer_.toString(); } + void clear() { underlying_buffer_.drain(underlying_buffer_.length()); } + Buffer::OwnedImpl underlying_buffer_; }; -TEST_F(JsonStreamerTest, Empty) { EXPECT_EQ("", buffer_.toString()); } +class StringOutputWrapper { +public: + using Type = StringOutput; + std::string toString() { return underlying_buffer_; } + void clear() { underlying_buffer_.clear(); } + std::string underlying_buffer_; +}; + +template class JsonStreamerTest : public testing::Test { +public: + T buffer_; + Json::StreamerBase streamer_{this->buffer_.underlying_buffer_}; +}; -TEST_F(JsonStreamerTest, EmptyMap) { - streamer_.makeRootMap(); - EXPECT_EQ("{}", buffer_.toString()); +using OutputBufferTypes = ::testing::Types; +TYPED_TEST_SUITE(JsonStreamerTest, OutputBufferTypes); + +TYPED_TEST(JsonStreamerTest, Empty) { EXPECT_EQ("", this->buffer_.toString()); } + +TYPED_TEST(JsonStreamerTest, EmptyMap) { + this->streamer_.makeRootMap(); + EXPECT_EQ("{}", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneDouble) { +TYPED_TEST(JsonStreamerTest, MapOneDouble) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", 3.141592654}}); } - EXPECT_EQ(R"EOF({"a":3.141592654})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":3.141592654})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoDoubles) { +TYPED_TEST(JsonStreamerTest, MapTwoDoubles) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", -989282.1087}, {"b", 1.23456789012345e+67}}); } - EXPECT_EQ(R"EOF({"a":-989282.1087,"b":1.23456789012345e+67})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":-989282.1087,"b":1.23456789012345e+67})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneUInt) { +TYPED_TEST(JsonStreamerTest, MapOneUInt) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", static_cast(0xffffffffffffffff)}}); } - EXPECT_EQ(R"EOF({"a":18446744073709551615})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":18446744073709551615})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoInts) { +TYPED_TEST(JsonStreamerTest, MapTwoInts) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", static_cast(0x7fffffffffffffff)}, {"b", static_cast(0x8000000000000000)}}); } - EXPECT_EQ(R"EOF({"a":9223372036854775807,"b":-9223372036854775808})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":9223372036854775807,"b":-9223372036854775808})EOF", + this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneString) { +TYPED_TEST(JsonStreamerTest, MapOneString) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", "b"}}); } - EXPECT_EQ(R"EOF({"a":"b"})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":"b"})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneBool) { +TYPED_TEST(JsonStreamerTest, MapOneBool) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", true}}); } - EXPECT_EQ(R"EOF({"a":true})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":true})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoBools) { +TYPED_TEST(JsonStreamerTest, MapTwoBools) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", true}, {"b", false}}); } - EXPECT_EQ(R"EOF({"a":true,"b":false})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":true,"b":false})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneSanitized) { +TYPED_TEST(JsonStreamerTest, MapOneSanitized) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addKey("a"); map->addString("\b\001"); } - EXPECT_EQ(R"EOF({"a":"\b\u0001"})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":"\b\u0001"})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoSanitized) { +TYPED_TEST(JsonStreamerTest, MapTwoSanitized) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addKey("a"); map->addString("\b\001"); map->addKey("b"); map->addString("\r\002"); } - EXPECT_EQ(R"EOF({"a":"\b\u0001","b":"\r\u0002"})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":"\b\u0001","b":"\r\u0002"})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, SubArray) { - Streamer::MapPtr map = streamer_.makeRootMap(); +TYPED_TEST(JsonStreamerTest, SubArray) { + auto map = this->streamer_.makeRootMap(); map->addKey("a"); - Streamer::ArrayPtr array = map->addArray(); + auto array = map->addArray(); array->addEntries({1.0, "two", 3.5, true, false, std::nan("")}); array.reset(); map->addEntries({{"embedded\"quote", "value"}}); map.reset(); EXPECT_EQ(R"EOF({"a":[1,"two",3.5,true,false,null],"embedded\"quote":"value"})EOF", - buffer_.toString()); + this->buffer_.toString()); } -TEST_F(JsonStreamerTest, TopArray) { +TYPED_TEST(JsonStreamerTest, TopArray) { { - Streamer::ArrayPtr array = streamer_.makeRootArray(); - array->addEntries({1.0, "two", 3.5, true, false, std::nan("")}); + auto array = this->streamer_.makeRootArray(); + array->addEntries({1.0, "two", 3.5, true, false, std::nan(""), absl::monostate{}}); } - EXPECT_EQ(R"EOF([1,"two",3.5,true,false,null])EOF", buffer_.toString()); + EXPECT_EQ(R"EOF([1,"two",3.5,true,false,null,null])EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, SubMap) { - Streamer::MapPtr map = streamer_.makeRootMap(); +TYPED_TEST(JsonStreamerTest, SubMap) { + auto map = this->streamer_.makeRootMap(); map->addKey("a"); - Streamer::MapPtr sub_map = map->addMap(); + auto sub_map = map->addMap(); sub_map->addEntries({{"one", 1.0}, {"three.5", 3.5}}); sub_map.reset(); map.reset(); - EXPECT_EQ(R"EOF({"a":{"one":1,"three.5":3.5}})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":{"one":1,"three.5":3.5}})EOF", this->buffer_.toString()); +} + +TYPED_TEST(JsonStreamerTest, SimpleDirectCall) { + { + this->streamer_.addBool(true); + EXPECT_EQ("true", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addBool(false); + EXPECT_EQ("false", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addString("hello"); + EXPECT_EQ(R"EOF("hello")EOF", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + uint64_t value = 1; + this->streamer_.addNumber(value); + EXPECT_EQ("1", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addNumber(1.5); + EXPECT_EQ("1.5", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addNull(); + EXPECT_EQ("null", this->buffer_.toString()); + this->buffer_.clear(); + } } } // namespace diff --git a/test/common/quic/BUILD b/test/common/quic/BUILD index dc2df66c3174..938238aafdf4 100644 --- a/test/common/quic/BUILD +++ b/test/common/quic/BUILD @@ -395,6 +395,15 @@ envoy_cc_test( ]), ) +envoy_cc_test( + name = "cert_compression_test", + srcs = ["cert_compression_test.cc"], + deps = [ + "//source/common/quic:cert_compression_lib", + "//test/test_common:logging_lib", + ], +) + envoy_proto_library( name = "envoy_quic_h3_fuzz_proto", srcs = ["envoy_quic_h3_fuzz.proto"], diff --git a/test/common/quic/cert_compression_test.cc b/test/common/quic/cert_compression_test.cc new file mode 100644 index 000000000000..767b13df1bf3 --- /dev/null +++ b/test/common/quic/cert_compression_test.cc @@ -0,0 +1,46 @@ +#include "source/common/quic/cert_compression.h" + +#include "test/test_common/logging.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Quic { + +TEST(CertCompressionZlibTest, DecompressBadData) { + EXPECT_LOG_CONTAINS( + "error", + "Cert decompression failure in inflate, possibly caused by invalid compressed cert from peer", + { + CRYPTO_BUFFER* out = nullptr; + const uint8_t bad_compressed_data = 1; + EXPECT_EQ(CertCompression::FAILURE, + CertCompression::decompressZlib(nullptr, &out, 100, &bad_compressed_data, + sizeof(bad_compressed_data))); + }); +} + +TEST(CertCompressionZlibTest, DecompressBadLength) { + constexpr uint8_t the_data[] = {1, 2, 3, 4, 5, 6}; + constexpr size_t uncompressed_len = 6; + bssl::ScopedCBB compressed; + ASSERT_EQ(1, CBB_init(compressed.get(), 0)); + ASSERT_EQ(CertCompression::SUCCESS, + CertCompression::compressZlib(nullptr, compressed.get(), the_data, uncompressed_len)); + const auto compressed_len = CBB_len(compressed.get()); + EXPECT_NE(0, compressed_len); + + EXPECT_LOG_CONTAINS("error", + "Decompression length did not match peer provided uncompressed length, " + "caused by either invalid peer handshake data or decompression error.", + { + CRYPTO_BUFFER* out = nullptr; + EXPECT_EQ(CertCompression::FAILURE, + CertCompression::decompressZlib( + nullptr, &out, + uncompressed_len + 1 /* intentionally incorrect */, + CBB_data(compressed.get()), compressed_len)); + }); +} +} // namespace Quic +} // namespace Envoy diff --git a/test/common/quic/envoy_quic_client_stream_test.cc b/test/common/quic/envoy_quic_client_stream_test.cc index 4ba077ead61d..e8fd682cadd6 100644 --- a/test/common/quic/envoy_quic_client_stream_test.cc +++ b/test/common/quic/envoy_quic_client_stream_test.cc @@ -153,7 +153,7 @@ class EnvoyQuicClientStreamTest : public testing::Test { EXPECT_EQ("200", headers->getStatusValue()); EXPECT_EQ(capsule_protocol[0]->value().getStringView(), "?1"); }); - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; response_headers["capsule-protocol"] = "?1"; std::string payload = spdyHeaderToHttp3StreamPayload(response_headers); @@ -189,8 +189,8 @@ class EnvoyQuicClientStreamTest : public testing::Test { std::string host_{"www.abc.com"}; Http::TestRequestHeaderMapImpl request_headers_; Http::TestRequestTrailerMapImpl request_trailers_; - spdy::Http2HeaderBlock spdy_response_headers_; - spdy::Http2HeaderBlock spdy_trailers_; + quiche::HttpHeaderBlock spdy_response_headers_; + quiche::HttpHeaderBlock spdy_trailers_; Buffer::OwnedImpl request_body_{"Hello world"}; std::string response_body_{"OK\n"}; #ifdef ENVOY_ENABLE_HTTP_DATAGRAMS @@ -346,7 +346,7 @@ TEST_F(EnvoyQuicClientStreamTest, PostRequestAnd1xx) { // Receive several 10x headers, only the first 100 Continue header should be // delivered. for (const std::string status : {"100", "199", "100"}) { - spdy::Http2HeaderBlock continue_header; + quiche::HttpHeaderBlock continue_header; continue_header[":status"] = status; continue_header["i"] = absl::StrCat("", i++); std::string data = spdyHeaderToHttp3StreamPayload(continue_header); @@ -365,7 +365,7 @@ TEST_F(EnvoyQuicClientStreamTest, ResetUpon101SwitchProtocol) { EXPECT_CALL(stream_callbacks_, onResetStream(Http::StreamResetReason::ProtocolError, _)); // Receive several 10x headers, only the first 100 Continue header should be // delivered. - spdy::Http2HeaderBlock continue_header; + quiche::HttpHeaderBlock continue_header; continue_header[":status"] = "101"; std::string data = spdyHeaderToHttp3StreamPayload(continue_header); quic::QuicStreamFrame frame(stream_id_, false, 0u, data); diff --git a/test/common/quic/envoy_quic_h3_fuzz_helper.cc b/test/common/quic/envoy_quic_h3_fuzz_helper.cc index a129446aaf31..6897306effac 100644 --- a/test/common/quic/envoy_quic_h3_fuzz_helper.cc +++ b/test/common/quic/envoy_quic_h3_fuzz_helper.cc @@ -25,7 +25,7 @@ class Delegate : public quic::QpackEncoder::DecoderStreamErrorDelegate { void OnDecoderStreamError(quic::QuicErrorCode, absl::string_view) override{}; }; -static std::string encodeHeaders(const spdy::Http2HeaderBlock& headers) { +static std::string encodeHeaders(const quiche::HttpHeaderBlock& headers) { static Delegate delegate; quic::QpackEncoder encoder(&delegate, quic::HuffmanEncoding::kEnabled, quic::CookieCrumbling::kEnabled); @@ -96,7 +96,7 @@ std::string H3Serializer::serialize(bool unidirectional, uint32_t type, uint32_t } case H3Frame::kHeaders: { const auto& f = h3frame.headers(); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; for (const auto& hdr : f.headers().headers()) { headers.AppendValueOrAddHeader(hdr.key(), hdr.value()); } @@ -120,7 +120,7 @@ std::string H3Serializer::serialize(bool unidirectional, uint32_t type, uint32_t case H3Frame::kPushPromise: { const auto& f = h3frame.push_promise(); uint64_t push_id = f.push_id(); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; for (auto& hdr : f.headers().headers()) { headers.AppendValueOrAddHeader(hdr.key(), hdr.value()); } diff --git a/test/common/quic/envoy_quic_server_stream_test.cc b/test/common/quic/envoy_quic_server_stream_test.cc index 68d1346efbe8..1027ad4351ac 100644 --- a/test/common/quic/envoy_quic_server_stream_test.cc +++ b/test/common/quic/envoy_quic_server_stream_test.cc @@ -128,7 +128,7 @@ class EnvoyQuicServerStreamTest : public testing::Test { EXPECT_FALSE(capsule_protocol.empty()); EXPECT_EQ(capsule_protocol[0]->value().getStringView(), "?1"); })); - spdy::Http2HeaderBlock request_headers; + quiche::HttpHeaderBlock request_headers; request_headers[":authority"] = host_; request_headers[":method"] = "CONNECT"; request_headers[":protocol"] = "connect-udp"; @@ -232,10 +232,10 @@ class EnvoyQuicServerStreamTest : public testing::Test { EnvoyQuicServerStream* quic_stream_; Http::MockRequestDecoder stream_decoder_; Http::MockStreamCallbacks stream_callbacks_; - spdy::Http2HeaderBlock spdy_request_headers_; + quiche::HttpHeaderBlock spdy_request_headers_; Http::TestResponseHeaderMapImpl response_headers_; Http::TestResponseTrailerMapImpl response_trailers_; - spdy::Http2HeaderBlock spdy_trailers_; + quiche::HttpHeaderBlock spdy_trailers_; std::string host_{"www.abc.com"}; std::string request_body_{"Hello world"}; #ifdef ENVOY_ENABLE_HTTP_DATAGRAMS @@ -263,7 +263,7 @@ TEST_F(EnvoyQuicServerStreamTest, GetRequestAndResponse) { headers->get(Http::Headers::get().Cookie)[0]->value().getStringView()); })); EXPECT_CALL(stream_decoder_, decodeData(BufferStringEqual(""), /*end_stream=*/true)); - spdy::Http2HeaderBlock spdy_headers; + quiche::HttpHeaderBlock spdy_headers; spdy_headers[":authority"] = host_; spdy_headers[":method"] = "GET"; spdy_headers[":path"] = "/"; @@ -710,7 +710,7 @@ TEST_F(EnvoyQuicServerStreamTest, RequestHeaderTooLarge) { EXPECT_CALL(quic_session_, MaybeSendStopSendingFrame(_, _)); EXPECT_CALL(quic_session_, MaybeSendRstStreamFrame(_, _, _)); EXPECT_CALL(stream_callbacks_, onResetStream(Http::StreamResetReason::LocalReset, _)); - spdy::Http2HeaderBlock spdy_headers; + quiche::HttpHeaderBlock spdy_headers; spdy_headers[":authority"] = host_; spdy_headers[":method"] = "POST"; spdy_headers[":path"] = "/"; @@ -734,7 +734,7 @@ TEST_F(EnvoyQuicServerStreamTest, RequestTrailerTooLarge) { EXPECT_CALL(quic_session_, MaybeSendStopSendingFrame(_, _)); EXPECT_CALL(quic_session_, MaybeSendRstStreamFrame(_, _, _)); EXPECT_CALL(stream_callbacks_, onResetStream(Http::StreamResetReason::LocalReset, _)); - spdy::Http2HeaderBlock spdy_trailers; + quiche::HttpHeaderBlock spdy_trailers; // This header exceeds max header size limit and should cause stream reset. spdy_trailers["long_header"] = std::string(16 * 1024 + 1, 'a'); std::string payload = spdyHeaderToHttp3StreamPayload(spdy_trailers); @@ -896,7 +896,7 @@ TEST_F(EnvoyQuicServerStreamTest, DecodeHttp3Datagram) { #endif TEST_F(EnvoyQuicServerStreamTest, RegularHeaderBeforePseudoHeader) { - spdy::Http2HeaderBlock spdy_headers; + quiche::HttpHeaderBlock spdy_headers; spdy_headers["foo"] = "bar"; spdy_headers[":authority"] = host_; spdy_headers[":method"] = "GET"; diff --git a/test/common/quic/envoy_quic_utils_test.cc b/test/common/quic/envoy_quic_utils_test.cc index def41145ad1d..3fbfe54e07f4 100644 --- a/test/common/quic/envoy_quic_utils_test.cc +++ b/test/common/quic/envoy_quic_utils_test.cc @@ -45,7 +45,7 @@ class MockServerHeaderValidator : public HeaderValidator { }; TEST(EnvoyQuicUtilsTest, HeadersConversion) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -118,7 +118,7 @@ TEST(EnvoyQuicUtilsTest, HeadersConversion) { } TEST(EnvoyQuicUtilsTest, HeadersSizeBounds) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -139,7 +139,7 @@ TEST(EnvoyQuicUtilsTest, HeadersSizeBounds) { } TEST(EnvoyQuicUtilsTest, TrailersSizeBounds) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -158,7 +158,7 @@ TEST(EnvoyQuicUtilsTest, TrailersSizeBounds) { } TEST(EnvoyQuicUtilsTest, TrailerCharacters) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -244,7 +244,7 @@ TEST(EnvoyQuicUtilsTest, HeaderMapMaxSizeLimit) { EXPECT_EQ(response_header->maxHeadersCount(), 100); EXPECT_EQ(response_header->maxHeadersKb(), 60); - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; diff --git a/test/common/quic/test_utils.h b/test/common/quic/test_utils.h index b19ede56a8bd..c9c1d04a7045 100644 --- a/test/common/quic/test_utils.h +++ b/test/common/quic/test_utils.h @@ -274,7 +274,7 @@ void setQuicConfigWithDefaultValues(quic::QuicConfig* config) { config, quic::kMinimumFlowControlSendWindow); } -std::string spdyHeaderToHttp3StreamPayload(const spdy::Http2HeaderBlock& header) { +std::string spdyHeaderToHttp3StreamPayload(const quiche::HttpHeaderBlock& header) { quic::test::NoopQpackStreamSenderDelegate encoder_stream_sender_delegate; quic::NoopDecoderStreamErrorDelegate decoder_stream_error_delegate; auto qpack_encoder = std::make_unique(&decoder_stream_error_delegate, diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index 8cc2795e4613..b400e04b62f5 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -10644,11 +10644,11 @@ class PerFilterConfigsTest : public testing::Test, public ConfigImplTestBase { check(dynamic_cast( route->mostSpecificPerFilterConfig(route_config_name)), expected_most_specific_config, "most specific config"); - route->traversePerFilterConfig( - route_config_name, [&](const Router::RouteSpecificFilterConfig& cfg) { - auto* typed_cfg = dynamic_cast(&cfg); - traveled_cfg.push_back(typed_cfg->config_.seconds()); - }); + for (const auto* cfg : route->perFilterConfigs(route_config_name)) { + auto* typed_cfg = dynamic_cast(cfg); + traveled_cfg.push_back(typed_cfg->config_.seconds()); + } + ASSERT_EQ(expected_traveled_config, traveled_cfg); } @@ -10666,11 +10666,10 @@ class PerFilterConfigsTest : public testing::Test, public ConfigImplTestBase { absl::InlinedVector traveled_cfg; EXPECT_EQ(nullptr, route->mostSpecificPerFilterConfig(route_config_name)); - route->traversePerFilterConfig( - route_config_name, [&](const Router::RouteSpecificFilterConfig& cfg) { - auto* typed_cfg = dynamic_cast(&cfg); - traveled_cfg.push_back(typed_cfg->config_.seconds()); - }); + for (const auto* cfg : route->perFilterConfigs(route_config_name)) { + auto* typed_cfg = dynamic_cast(cfg); + traveled_cfg.push_back(typed_cfg->config_.seconds()); + } EXPECT_EQ(0, traveled_cfg.size()); } diff --git a/test/common/router/delegating_route_impl_test.cc b/test/common/router/delegating_route_impl_test.cc index 5bd579dfa874..c717c4a96a16 100644 --- a/test/common/router/delegating_route_impl_test.cc +++ b/test/common/router/delegating_route_impl_test.cc @@ -34,8 +34,7 @@ TEST(DelegatingRoute, DelegatingRouteTest) { std::string name; TEST_METHOD(mostSpecificPerFilterConfig, name); - std::function cb; - TEST_METHOD(traversePerFilterConfig, name, cb); + TEST_METHOD(perFilterConfigs, name); } // Verify that DelegatingRouteEntry class forwards all calls to internal base route. diff --git a/test/common/router/header_formatter_test.cc b/test/common/router/header_formatter_test.cc index 324492f2e689..0e27b66d6939 100644 --- a/test/common/router/header_formatter_test.cc +++ b/test/common/router/header_formatter_test.cc @@ -217,7 +217,7 @@ TEST(HeaderParserTest, TestParse) { if (test_case.expected_exception_) { EXPECT_FALSE(test_case.expected_output_); - EXPECT_THROW(THROW_IF_STATUS_NOT_OK(HeaderParser::configure(to_add), throw), EnvoyException); + EXPECT_THROW(THROW_IF_NOT_OK_REF(HeaderParser::configure(to_add).status()), EnvoyException); continue; } diff --git a/test/common/runtime/runtime_impl_test.cc b/test/common/runtime/runtime_impl_test.cc index 37540ce90d29..16d1ea5a2ef7 100644 --- a/test/common/runtime/runtime_impl_test.cc +++ b/test/common/runtime/runtime_impl_test.cc @@ -32,6 +32,7 @@ #ifdef ENVOY_ENABLE_QUIC #include "quiche/common/platform/api/quiche_flags.h" #endif +ABSL_DECLARE_FLAG(bool, envoy_reloadable_features_boolean_to_string_fix); ABSL_DECLARE_FLAG(bool, envoy_reloadable_features_reject_invalid_yaml); using testing::_; @@ -1314,6 +1315,40 @@ TEST_F(RtdsLoaderImplTest, BadConfigSource) { "bad config"); } +TEST_F(RtdsLoaderImplTest, BooleanToStringConversionWhenFlagEnabled) { + setup(); + + absl::SetFlag(&FLAGS_envoy_reloadable_features_boolean_to_string_fix, true); + + auto runtime = TestUtility::parseYaml(R"EOF( + name: some_resource + layer: + toggle: true + )EOF"); + + EXPECT_CALL(rtds_init_callback_, Call()); + doOnConfigUpdateVerifyNoThrow(runtime); + + EXPECT_EQ("true", loader_->snapshot().get("toggle").value().get()); +} + +TEST_F(RtdsLoaderImplTest, BooleanToStringConversionWhenFlagDisabled) { + setup(); + + absl::SetFlag(&FLAGS_envoy_reloadable_features_boolean_to_string_fix, false); + + auto runtime = TestUtility::parseYaml(R"EOF( + name: some_resource + layer: + toggle: true + )EOF"); + + EXPECT_CALL(rtds_init_callback_, Call()); + doOnConfigUpdateVerifyNoThrow(runtime); + + EXPECT_EQ("1", loader_->snapshot().get("toggle").value().get()); // Assuming previous behavior +} + } // namespace } // namespace Runtime } // namespace Envoy diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index b7c23e96f2ae..3ef5cef66f7f 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -75,7 +75,7 @@ class UpstreamImplTestBase { ClusterFactoryContext& context) { StaticClusterFactory factory; auto status_or_cluster = factory.createClusterImpl(cluster, context); - THROW_IF_STATUS_NOT_OK(status_or_cluster, throw); + THROW_IF_NOT_OK_REF(status_or_cluster.status()); return std::dynamic_pointer_cast(status_or_cluster->first); } diff --git a/test/extensions/clusters/original_dst/original_dst_cluster_test.cc b/test/extensions/clusters/original_dst/original_dst_cluster_test.cc index 301860fb6811..d0e1cd8e82f7 100644 --- a/test/extensions/clusters/original_dst/original_dst_cluster_test.cc +++ b/test/extensions/clusters/original_dst/original_dst_cluster_test.cc @@ -85,7 +85,7 @@ class OriginalDstClusterTest : public Event::TestUsingSimulatedTime, public test OriginalDstClusterFactory factory; auto status_or_pair = factory.createClusterImpl(cluster_config, factory_context); - THROW_IF_STATUS_NOT_OK(status_or_pair, throw); + THROW_IF_NOT_OK_REF(status_or_pair.status()); cluster_ = std::dynamic_pointer_cast(status_or_pair.value().first); priority_update_cb_ = cluster_->prioritySet().addPriorityUpdateCb( 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 a39c18d30433..fd3a4819cf10 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 @@ -60,7 +60,7 @@ class DnsCacheImplTest : public testing::Test, public Event::TestUsingSimulatedT EXPECT_CALL(dns_resolver_factory_, createDnsResolver(_, _, _)) .WillRepeatedly(Return(resolver_)); auto status_or_cache = DnsCacheImpl::createDnsCacheImpl(context_, config_); - THROW_IF_STATUS_NOT_OK(status_or_cache, throw); + THROW_IF_NOT_OK_REF(status_or_cache.status()); dns_cache_ = status_or_cache.value(); update_callbacks_handle_ = dns_cache_->addUpdateCallbacks(update_callbacks_); } diff --git a/test/extensions/filters/http/common/fuzz/uber_filter.cc b/test/extensions/filters/http/common/fuzz/uber_filter.cc index 514379e66792..d4ada699261d 100644 --- a/test/extensions/filters/http/common/fuzz/uber_filter.cc +++ b/test/extensions/filters/http/common/fuzz/uber_filter.cc @@ -81,7 +81,7 @@ void UberFilterFuzzer::fuzz( // Clean-up config with filter-specific logic before it runs through validations. cleanFuzzedConfig(proto_config.name(), message.get()); auto cb_or = factory.createFilterFactoryFromProto(*message, "stats", factory_context_); - THROW_IF_STATUS_NOT_OK(cb_or, throw); + THROW_IF_NOT_OK_REF(cb_or.status()); cb_ = cb_or.value(); cb_(filter_callback_); } catch (const EnvoyException& e) { diff --git a/test/extensions/filters/http/common/jwks_fetcher_test.cc b/test/extensions/filters/http/common/jwks_fetcher_test.cc index 59184dda5b0e..571b61e23208 100644 --- a/test/extensions/filters/http/common/jwks_fetcher_test.cc +++ b/test/extensions/filters/http/common/jwks_fetcher_test.cc @@ -81,6 +81,28 @@ TEST_F(JwksFetcherTest, TestGetSuccess) { fetcher_->fetch(parent_span_, receiver); } +TEST_F(JwksFetcherTest, TestMessageHeader) { + // Setup + setupFetcher(config); + MockUpstream mock_pubkey(mock_factory_ctx_.server_factory_context_.cluster_manager_, "200", + publicKey); + MockJwksReceiver receiver; + + // Expectations for message + EXPECT_CALL(mock_factory_ctx_.server_factory_context_.cluster_manager_.thread_local_cluster_ + .async_client_, + send_(_, _, _)) + .WillOnce(Invoke([](Http::RequestMessagePtr& message, Http::AsyncClient::Callbacks&, + const Http::AsyncClient::RequestOptions&) -> Http::AsyncClient::Request* { + EXPECT_EQ(message->headers().getUserAgentValue(), + Http::Headers::get().UserAgentValues.GoBrowser); + return nullptr; + })); + + // Act + fetcher_->fetch(parent_span_, receiver); +} + TEST_F(JwksFetcherTest, TestGet400) { // Setup setupFetcher(config); diff --git a/test/extensions/filters/http/cors/cors_filter_test.cc b/test/extensions/filters/http/cors/cors_filter_test.cc index 3206df3017c1..c699fe543e68 100644 --- a/test/extensions/filters/http/cors/cors_filter_test.cc +++ b/test/extensions/filters/http/cors/cors_filter_test.cc @@ -55,12 +55,10 @@ class CorsFilterTest : public testing::Test { cors_policy_->allow_private_network_access_ = true; cors_policy_->max_age_ = "0"; - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of virtual host. - cb(*cors_policy_); // Cors policy of route entry. - })); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([this]() -> Router::RouteSpecificFilterConfigs { + return {cors_policy_.get(), cors_policy_.get()}; + })); filter_.setDecoderFilterCallbacks(decoder_callbacks_); filter_.setEncoderFilterCallbacks(encoder_callbacks_); @@ -99,11 +97,9 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { filter_.setDecoderFilterCallbacks(decoder_callbacks_); filter_.setEncoderFilterCallbacks(encoder_callbacks_); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of virtual host. - })); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke( + [this]() -> Router::RouteSpecificFilterConfigs { return {cors_policy_.get()}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); @@ -120,9 +116,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_CALL(decoder_callbacks_.route_->route_entry_, corsPolicy()).WillOnce(Return(nullptr)); EXPECT_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()).WillOnce(Return(nullptr)); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); @@ -139,9 +134,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { .WillOnce(Return(cors_policy_.get())); EXPECT_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()).WillOnce(Return(nullptr)); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); @@ -158,9 +152,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()) .WillOnce(Return(cors_policy_.get())); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false)); EXPECT_EQ(false, isCorsRequest()); @@ -715,8 +708,8 @@ TEST_F(CorsFilterTest, NoCorsEntry) { {":method", "OPTIONS"}, {"origin", "localhost"}, {"access-control-request-method", "GET"}}; // No cors policy in the 'typed_per_filter_config'. - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault(Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); // No cors policy in route entry or virtual host. ON_CALL(decoder_callbacks_.route_->route_entry_, corsPolicy()).WillByDefault(Return(nullptr)); ON_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()).WillByDefault(Return(nullptr)); @@ -741,11 +734,9 @@ TEST_F(CorsFilterTest, NoRouteCorsEntry) { Http::TestRequestHeaderMapImpl request_headers{ {":method", "OPTIONS"}, {"origin", "localhost"}, {"access-control-request-method", "GET"}}; - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + ON_CALL(decoder_callbacks_, perFilterConfigs()) .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of route entry. - })); + Invoke([this]() -> Router::RouteSpecificFilterConfigs { return {cors_policy_.get()}; })); Http::TestResponseHeaderMapImpl response_headers{ {":status", "200"}, @@ -775,11 +766,9 @@ TEST_F(CorsFilterTest, NoVHostCorsEntry) { cors_policy_->allow_methods_ = ""; - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + ON_CALL(decoder_callbacks_, perFilterConfigs()) .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of route entry. - })); + Invoke([this]() -> Router::RouteSpecificFilterConfigs { return {cors_policy_.get()}; })); Http::TestResponseHeaderMapImpl response_headers{ {":status", "200"}, diff --git a/test/extensions/filters/http/ext_authz/ext_authz_test.cc b/test/extensions/filters/http/ext_authz/ext_authz_test.cc index 7559128d07cf..fab44855d8aa 100644 --- a/test/extensions/filters/http/ext_authz/ext_authz_test.cc +++ b/test/extensions/filters/http/ext_authz/ext_authz_test.cc @@ -2605,11 +2605,9 @@ TEST_P(HttpFilterTestParam, ContextExtensions) { EXPECT_CALL(*decoder_filter_callbacks_.route_, mostSpecificPerFilterConfig(_)) .WillOnce(Return(&auth_per_route)); - EXPECT_CALL(*decoder_filter_callbacks_.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(auth_per_vhost); - cb(auth_per_route); + EXPECT_CALL(*decoder_filter_callbacks_.route_, perFilterConfigs(_)) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {&auth_per_vhost, &auth_per_route}; })); prepareCheck(); diff --git a/test/extensions/filters/http/ext_proc/filter_test.cc b/test/extensions/filters/http/ext_proc/filter_test.cc index 6fd45bff4495..008974567edc 100644 --- a/test/extensions/filters/http/ext_proc/filter_test.cc +++ b/test/extensions/filters/http/ext_proc/filter_test.cc @@ -2675,11 +2675,9 @@ TEST_F(HttpFilterTest, ProcessingModeResponseHeadersOnlyWithoutCallingDecodeHead route_proto.mutable_overrides()->mutable_grpc_service()->mutable_envoy_grpc()->set_cluster_name( "cluster_1"); FilterConfigPerRoute route_config(route_proto); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); final_expected_grpc_service_.emplace(route_proto.overrides().grpc_service()); config_with_hash_key_.setConfig(route_proto.overrides().grpc_service()); @@ -3473,11 +3471,9 @@ TEST_F(HttpFilterTest, MetadataOptionsOverride) { FilterConfigPerRoute route_config(override_cfg); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); response_headers_.addCopy(LowerCaseString(":status"), "200"); response_headers_.addCopy(LowerCaseString("content-type"), "text/plain"); @@ -3537,11 +3533,9 @@ TEST_F(HttpFilterTest, MetadataOptionsNoOverride) { FilterConfigPerRoute route_config(override_cfg); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); response_headers_.addCopy(LowerCaseString(":status"), "200"); response_headers_.addCopy(LowerCaseString("content-type"), "text/plain"); @@ -4469,11 +4463,9 @@ TEST_F(HttpFilterTest, GrpcServiceMetadataOverride) { *route_proto.mutable_overrides()->mutable_grpc_initial_metadata()->Add() = makeHeaderValue("c", "c"); FilterConfigPerRoute route_config(route_proto); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); // Build expected merged grpc_service configuration. { diff --git a/test/extensions/filters/http/file_system_buffer/filter_test.cc b/test/extensions/filters/http/file_system_buffer/filter_test.cc index 846b912ebfef..78541b92b314 100644 --- a/test/extensions/filters/http/file_system_buffer/filter_test.cc +++ b/test/extensions/filters/http/file_system_buffer/filter_test.cc @@ -774,13 +774,11 @@ TEST_F(FileSystemBufferFilterTest, MergesRouteConfig) { )"); auto mock_route = std::make_shared(); EXPECT_CALL(decoder_callbacks_, route()).WillOnce(Return(mock_route)); - EXPECT_CALL(*mock_route, traversePerFilterConfig(_, _)) - .WillOnce([vhost_config, route_config]( - const std::string&, - std::function add_config) { - add_config(*vhost_config); - add_config(*route_config); - }); + EXPECT_CALL(*mock_route, perFilterConfigs(_)) + .WillOnce( + [vhost_config, route_config](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {vhost_config.get(), route_config.get()}; + }); // The default config would return Continue, so these returning StopIteration shows that // both route_configs were applied. EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, diff --git a/test/extensions/filters/http/header_mutation/header_mutation_test.cc b/test/extensions/filters/http/header_mutation/header_mutation_test.cc index 3b5ede576915..318f05d6c204 100644 --- a/test/extensions/filters/http/header_mutation/header_mutation_test.cc +++ b/test/extensions/filters/http/header_mutation/header_mutation_test.cc @@ -113,10 +113,9 @@ TEST(HeaderMutationFilterTest, HeaderMutationFilterTest) { filter.setDecoderFilterCallbacks(decoder_callbacks); filter.setEncoderFilterCallbacks(encoder_callbacks); - EXPECT_CALL(*decoder_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(*config); + EXPECT_CALL(*decoder_callbacks.route_, perFilterConfigs(_)) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {config.get()}; })); { @@ -238,10 +237,9 @@ TEST(HeaderMutationFilterTest, HeaderMutationFilterTest) { }; // If the decoding phase is not performed then try to get the config from the encoding phase. - EXPECT_CALL(*encoder_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(*config); + EXPECT_CALL(*encoder_callbacks.route_, perFilterConfigs(_)) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {config.get()}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter.encodeHeaders(headers, true)); diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index b8d1cc93b647..6d3e8961d82a 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -94,6 +94,7 @@ class GeoipProviderTestBase { Registry::FactoryRegistry::getFactory( "envoy.geoip_providers.maxmind")); ASSERT(provider_factory_); + on_changed_cbs_.reserve(1); } ~GeoipProviderTestBase() { diff --git a/test/extensions/resource_monitors/cpu_utilization/BUILD b/test/extensions/resource_monitors/cpu_utilization/BUILD new file mode 100644 index 000000000000..22d752a5f06a --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/BUILD @@ -0,0 +1,53 @@ +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 = "cpu_utilization_monitor_test", + srcs = ["cpu_utilization_monitor_test.cc"], + extension_names = ["envoy.resource_monitors.cpu_utilization"], + external_deps = ["abseil_optional"], + tags = ["skip_on_windows"], + deps = [ + "//source/extensions/resource_monitors/cpu_utilization:cpu_utilization_monitor", + "//source/extensions/resource_monitors/cpu_utilization:linux_cpu_stats_reader", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) + +envoy_extension_cc_test( + name = "linux_cpu_stats_reader_test", + srcs = ["linux_cpu_stats_reader_test.cc"], + extension_names = ["envoy.resource_monitors.cpu_utilization"], + external_deps = ["abseil_optional"], + tags = ["skip_on_windows"], + deps = [ + "//source/extensions/resource_monitors/cpu_utilization:linux_cpu_stats_reader", + "//test/test_common:environment_lib", + ], +) + +envoy_extension_cc_test( + name = "config_test", + srcs = ["config_test.cc"], + extension_names = ["envoy.resource_monitors.cpu_utilization"], + tags = ["skip_on_windows"], + deps = [ + "//envoy/registry", + "//source/common/stats:isolated_store_lib", + "//source/extensions/resource_monitors/cpu_utilization:config", + "//source/server:resource_monitor_config_lib", + "//test/mocks/event:event_mocks", + "//test/mocks/server:options_mocks", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/resource_monitors/cpu_utilization/config_test.cc b/test/extensions/resource_monitors/cpu_utilization/config_test.cc new file mode 100644 index 000000000000..bda708a08cf2 --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/config_test.cc @@ -0,0 +1,38 @@ +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/registry/registry.h" + +#include "source/extensions/resource_monitors/cpu_utilization/config.h" +#include "source/server/resource_monitor_config_impl.h" + +#include "test/mocks/event/mocks.h" +#include "test/mocks/server/options.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { +namespace { + +TEST(CpuUtilizationMonitorFactoryTest, CreateMonitor) { + auto factory = + Registry::FactoryRegistry::getFactory( + "envoy.resource_monitors.cpu_utilization"); + EXPECT_NE(factory, nullptr); + + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + Event::MockDispatcher dispatcher; + Api::ApiPtr api = Api::createApiForTest(); + Server::MockOptions options; + Server::Configuration::ResourceMonitorFactoryContextImpl context( + dispatcher, options, *api, ProtobufMessage::getStrictValidationVisitor()); + auto monitor = factory->createResourceMonitor(config, context); + EXPECT_NE(monitor, nullptr); +} + +} // namespace +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor_test.cc b/test/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor_test.cc new file mode 100644 index 000000000000..66d83caf1d0a --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor_test.cc @@ -0,0 +1,113 @@ +#include + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" + +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" +#include "source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h" + +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { +namespace { + +using testing::Return; + +class MockCpuStatsReader : public CpuStatsReader { +public: + MockCpuStatsReader() = default; + + MOCK_METHOD(CpuTimes, getCpuTimes, ()); +}; + +class ResourcePressure : public Server::ResourceUpdateCallbacks { +public: + void onSuccess(const Server::ResourceUsage& usage) override { + pressure_ = usage.resource_pressure_; + } + + void onFailure(const EnvoyException& error) override { error_ = error; } + + bool hasPressure() const { return pressure_.has_value(); } + bool hasError() const { return error_.has_value(); } + + double pressure() const { return *pressure_; } + +private: + absl::optional pressure_; + absl::optional error_; +}; + +TEST(CpuUtilizationMonitorTest, ComputesCorrectUsage) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{true, 50, 100})) + .WillOnce(Return(CpuTimes{true, 100, 200})) + .WillOnce(Return(CpuTimes{true, 200, 300})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasPressure()); + ASSERT_FALSE(resource.hasError()); + EXPECT_DOUBLE_EQ(resource.pressure(), 0.025); // dampening + + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasPressure()); + ASSERT_FALSE(resource.hasError()); + EXPECT_DOUBLE_EQ(resource.pressure(), 0.07375); // dampening +} + +TEST(CpuUtilizationMonitorTest, GetsErroneousStatsDenominator) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{true, 100, 100})) + .WillOnce(Return(CpuTimes{true, 100, 99})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); +} + +TEST(CpuUtilizationMonitorTest, GetsErroneousStatsNumerator) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{true, 100, 100})) + .WillOnce(Return(CpuTimes{true, 99, 150})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); +} + +TEST(CpuUtilizationMonitorTest, ReportsError) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{false, 0, 0})) + .WillOnce(Return(CpuTimes{false, 0, 0})) + .WillOnce(Return(CpuTimes{false, 0, 200})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); + + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); +} + +} // namespace +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader_test.cc b/test/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader_test.cc new file mode 100644 index 000000000000..a7d0476a4a82 --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader_test.cc @@ -0,0 +1,92 @@ +#include + +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" +#include "source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h" + +#include "test/test_common/environment.h" + +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { +namespace { + +TEST(LinuxCpuStatsReader, ReadsCpuStats) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats"); + AtomicFileUpdater file_updater(temp_path); + const std::string contents = R"EOF(cpu 14987204 4857 3003536 11594988 53631 0 759314 2463 0 0 +cpu0 1907532 599 369969 1398344 5970 0 121763 18 0 0 +cpu1 1883161 620 375962 1448133 5963 0 85914 10 0 0 +cpu2 1877318 610 376223 1458160 5713 0 81227 10 0 0 +cpu3 1844673 653 373370 1493333 6063 0 80492 1124 0 0 +cpu4 1879904 572 380089 1440757 7348 0 91022 10 0 0 +cpu5 1873470 607 377632 1449005 6359 0 94092 8 0 0 +cpu6 1878276 576 375458 1423527 7995 0 115756 8 0 0 +cpu7 1842866 615 374829 1483725 8218 0 89044 1272 0 0 +intr 1219233916 0 10 0 0 555 0 0 0 0 0 0 0 154 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 12 20859 24167 1125607 1182080 40577 52852415 108966441 51142451 43742777 52285969 56216800 52419266 95242197 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +ctxt 5657586121 +btime 1700654901 +processes 34530 +procs_running 7 +procs_blocked 0 +softirq 1714610175 0 8718679 72686 1588388544 32 0 293214 77920941 12627 39203452 +)EOF"; + file_updater.update(contents); + + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + + EXPECT_EQ(cpu_times.work_time, 17995597); + EXPECT_EQ(cpu_times.total_time, 29590585); +} + +TEST(LinuxCpuStatsReader, CannotReadFile) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats_not_exists"); + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + EXPECT_FALSE(cpu_times.is_valid); + EXPECT_EQ(cpu_times.work_time, 0); + EXPECT_EQ(cpu_times.total_time, 0); +} + +TEST(LinuxCpuStatsReader, UnexpectedFormatCpuLine) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats_unexpected_format"); + AtomicFileUpdater file_updater(temp_path); + const std::string contents = R"EOF(cpu0 1907532 599 369969 1398344 5970 0 121763 18 0 0 +cpu1 1883161 620 375962 1448133 5963 0 85914 10 0 0 +cpu 14987204 4857 3003536 11594988 53631 0 759314 2463 0 0 +)EOF"; + file_updater.update(contents); + + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + EXPECT_FALSE(cpu_times.is_valid); + EXPECT_EQ(cpu_times.work_time, 0); + EXPECT_EQ(cpu_times.total_time, 0); +} + +TEST(LinuxCpuStatsReader, UnexpectedFormatMissingTokens) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats_unexpected_format"); + AtomicFileUpdater file_updater(temp_path); + const std::string contents = R"EOF(cpu 14987204 4857 3003536 +cpu0 1907532 599 369969 1398344 5970 0 121763 18 0 0 +cpu1 1883161 620 375962 1448133 5963 0 85914 10 0 0 +)EOF"; + file_updater.update(contents); + + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + EXPECT_FALSE(cpu_times.is_valid); + EXPECT_EQ(cpu_times.work_time, 0); + EXPECT_EQ(cpu_times.total_time, 0); +} + +} // namespace +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/test/fuzz/utility.h b/test/fuzz/utility.h index 25120a3f69b6..d1ac39a70aa6 100644 --- a/test/fuzz/utility.h +++ b/test/fuzz/utility.h @@ -171,7 +171,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn stream_info.address().envoy_internal_address().server_listener_name())); } else { auto address_or_error = Envoy::Network::Address::resolveProtoAddress(stream_info.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); address = address_or_error.value(); } } else { @@ -181,7 +181,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn if (stream_info.has_upstream_local_address()) { auto upstream_local_address_or_error = Envoy::Network::Address::resolveProtoAddress(stream_info.upstream_local_address()); - THROW_IF_STATUS_NOT_OK(upstream_local_address_or_error, throw); + THROW_IF_NOT_OK_REF(upstream_local_address_or_error.status()); upstream_local_address = upstream_local_address_or_error.value(); } else { upstream_local_address = *Network::Utility::resolveUrl("tcp://10.0.0.1:10000"); diff --git a/test/integration/admin_html/test_server.cc b/test/integration/admin_html/test_server.cc index d371d7b22108..a96432d303e5 100644 --- a/test/integration/admin_html/test_server.cc +++ b/test/integration/admin_html/test_server.cc @@ -42,7 +42,7 @@ Http::Code testCallback(Http::ResponseHeaderMap& response_headers, Buffer::Insta std::string path = absl::StrCat(prefix, leaf); TRY_ASSERT_MAIN_THREAD { auto file_or_error = file_system.fileReadToEnd(path); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); response.add(file_or_error.value()); } END_TRY diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index e431aa45828e..b2dc7b4fa18a 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -671,6 +671,26 @@ TEST_P(QuicHttpIntegrationTest, RuntimeEnableDraft29) { test_server_->waitForCounterEq("http3.quic_version_h3_29", 1u); } +TEST_P(QuicHttpIntegrationTest, CertCompressionEnabled) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.quic_support_certificate_compression", "true"); + initialize(); + + EXPECT_LOG_CONTAINS_ALL_OF( + Envoy::ExpectedLogMessages( + {{"trace", "Cert compression successful"}, {"trace", "Cert decompression successful"}}), + { testRouterHeaderOnlyRequestAndResponse(); }); +} + +TEST_P(QuicHttpIntegrationTest, CertCompressionDisabled) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.quic_support_certificate_compression", "false"); + initialize(); + + EXPECT_LOG_NOT_CONTAINS("trace", "Cert compression successful", + { testRouterHeaderOnlyRequestAndResponse(); }); +} + TEST_P(QuicHttpIntegrationTest, ZeroRtt) { // Make sure all connections use the same PersistentQuicInfoImpl. concurrency_ = 1; diff --git a/test/mocks/http/mocks.cc b/test/mocks/http/mocks.cc index a7f12edb2e4d..7406cfa3446a 100644 --- a/test/mocks/http/mocks.cc +++ b/test/mocks/http/mocks.cc @@ -109,15 +109,14 @@ MockStreamDecoderFilterCallbacks::MockStreamDecoderFilterCallbacks() { } return route->mostSpecificPerFilterConfig("envoy.filter"); })); - ON_CALL(*this, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - auto route = this->route(); - if (route == nullptr) { - return; - } - route->traversePerFilterConfig("envoy.filter", cb); - })); + ON_CALL(*this, perFilterConfigs()) + .WillByDefault(Invoke([this]() -> Router::RouteSpecificFilterConfigs { + auto route = this->route(); + if (route == nullptr) { + return {}; + } + return route->perFilterConfigs("envoy.filter"); + })); } MockStreamDecoderFilterCallbacks::~MockStreamDecoderFilterCallbacks() = default; @@ -158,15 +157,14 @@ MockStreamEncoderFilterCallbacks::MockStreamEncoderFilterCallbacks() { } return route->mostSpecificPerFilterConfig("envoy.filter"); })); - ON_CALL(*this, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - auto route = this->route(); - if (route == nullptr) { - return; - } - route->traversePerFilterConfig("envoy.filter", cb); - })); + ON_CALL(*this, perFilterConfigs()) + .WillByDefault(Invoke([this]() -> Router::RouteSpecificFilterConfigs { + auto route = this->route(); + if (route == nullptr) { + return {}; + } + return route->perFilterConfigs("envoy.filter"); + })); } MockStreamEncoderFilterCallbacks::~MockStreamEncoderFilterCallbacks() = default; diff --git a/test/mocks/http/mocks.h b/test/mocks/http/mocks.h index cdf2690c2a1c..7dcf37ca998b 100644 --- a/test/mocks/http/mocks.h +++ b/test/mocks/http/mocks.h @@ -272,8 +272,7 @@ class MockStreamDecoderFilterCallbacks : public StreamDecoderFilterCallbacks, MOCK_METHOD(void, addUpstreamSocketOptions, (const Network::Socket::OptionsSharedPtr& options)); MOCK_METHOD(Network::Socket::OptionsSharedPtr, getUpstreamSocketOptions, (), (const)); MOCK_METHOD(const Router::RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (), (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (std::function cb), (const)); + MOCK_METHOD(Router::RouteSpecificFilterConfigs, perFilterConfigs, (), (const)); MOCK_METHOD(Http1StreamEncoderOptionsOptRef, http1StreamEncoderOptions, ()); MOCK_METHOD(OptRef, downstreamCallbacks, ()); MOCK_METHOD(OptRef, upstreamCallbacks, ()); @@ -369,8 +368,7 @@ class MockStreamEncoderFilterCallbacks : public StreamEncoderFilterCallbacks, MOCK_METHOD(uint32_t, encoderBufferLimit, ()); MOCK_METHOD(void, restoreContextOnContinue, (ScopeTrackedObjectStack&)); MOCK_METHOD(const Router::RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (), (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (std::function cb), (const)); + MOCK_METHOD(Router::RouteSpecificFilterConfigs, perFilterConfigs, (), (const)); MOCK_METHOD(Http1StreamEncoderOptionsOptRef, http1StreamEncoderOptions, ()); MOCK_METHOD(OptRef, downstreamCallbacks, ()); MOCK_METHOD(OptRef, upstreamCallbacks, ()); diff --git a/test/mocks/router/mocks.h b/test/mocks/router/mocks.h index 1fcadf99f811..2a8ee2c4c01d 100644 --- a/test/mocks/router/mocks.h +++ b/test/mocks/router/mocks.h @@ -319,7 +319,7 @@ class MockVirtualHost : public VirtualHost { MOCK_METHOD(const RateLimitPolicy&, rateLimitPolicy, (), (const)); MOCK_METHOD(const CorsPolicy*, corsPolicy, (), (const)); MOCK_METHOD(const CommonConfig&, routeConfig, (), (const)); - MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (const std::string&), + MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (absl::string_view), (const)); MOCK_METHOD(bool, includeAttemptCountInRequest, (), (const)); MOCK_METHOD(bool, includeAttemptCountInResponse, (), (const)); @@ -327,9 +327,7 @@ class MockVirtualHost : public VirtualHost { MOCK_METHOD(Upstream::RetryPrioritySharedPtr, retryPriority, ()); MOCK_METHOD(Upstream::RetryHostPredicateSharedPtr, retryHostPredicate, ()); MOCK_METHOD(uint32_t, retryShadowBufferLimit, (), (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (const std::string&, std::function), - (const)); + MOCK_METHOD(RouteSpecificFilterConfigs, perFilterConfigs, (absl::string_view), (const)); MOCK_METHOD(const envoy::config::core::v3::Metadata&, metadata, (), (const)); MOCK_METHOD(const Envoy::Config::TypedMetadata&, typedMetadata, (), (const)); MOCK_METHOD(const VirtualCluster*, virtualCluster, (const Http::HeaderMap& headers), (const)); @@ -516,12 +514,10 @@ class MockRoute : public Route { MOCK_METHOD(const Decorator*, decorator, (), (const)); MOCK_METHOD(const RouteTracing*, tracingConfig, (), (const)); MOCK_METHOD(absl::optional, filterDisabled, (absl::string_view), (const)); - MOCK_METHOD(const RouteSpecificFilterConfig*, perFilterConfig, (const std::string&), (const)); - MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (const std::string&), - (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (const std::string&, std::function), + MOCK_METHOD(const RouteSpecificFilterConfig*, perFilterConfig, (absl::string_view), (const)); + MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (absl::string_view), (const)); + MOCK_METHOD(RouteSpecificFilterConfigs, perFilterConfigs, (absl::string_view), (const)); MOCK_METHOD(const envoy::config::core::v3::Metadata&, metadata, (), (const)); MOCK_METHOD(const Envoy::Config::TypedMetadata&, typedMetadata, (), (const)); MOCK_METHOD(const std::string&, routeName, (), (const)); diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index 8138b1e56ebc..4a9420f37622 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -8,7 +8,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/api/posix:83.8" # flaky (accept failover non-deterministic): be careful adjusting "source/common/config:96.1" "source/common/crypto:95.5" -"source/common/event:95.1" # Emulated edge events guards don't report LCOV +"source/common/event:95.2" # Emulated edge events guards don't report LCOV "source/common/filesystem/posix:96.3" # FileReadToEndNotReadable fails in some env; createPath can't test all failure branches. "source/common/http/http2:96.0" "source/common/json:94.4" @@ -16,7 +16,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/memory:74.5" # tcmalloc code path is not enabled in coverage build, only gperf tcmalloc, see PR#32589 "source/common/network:94.4" # Flaky, `activateFileEvents`, `startSecureTransport` and `ioctl`, listener_socket do not always report LCOV "source/common/network/dns_resolver:91.4" # A few lines of MacOS code not tested in linux scripts. Tested in MacOS scripts -"source/common/quic:93.7" +"source/common/quic:93.5" "source/common/secret:95.4" "source/common/signal:87.2" # Death tests don't report LCOV "source/common/thread:0.0" # Death tests don't report LCOV @@ -29,7 +29,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/common/wasm/ext:92.0" "source/extensions/filters/common/fault:94.5" "source/extensions/filters/common/rbac:90.8" -"source/extensions/filters/http/cache:95.1" +"source/extensions/filters/http/cache:95.3" "source/extensions/filters/http/grpc_json_transcoder:94.2" # TODO(#28232) "source/extensions/filters/http/ip_tagging:88.2" "source/extensions/filters/http/kill_request:91.7" # Death tests don't report LCOV @@ -52,8 +52,8 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/wasm_runtime/wamr:0.0" # Not enabled in coverage build "source/extensions/wasm_runtime/wasmtime:0.0" # Not enabled in coverage build "source/extensions/watchdog:83.3" # Death tests within extensions -"source/extensions/listener_managers:70.5" -"source/extensions/listener_managers/validation_listener_manager:70.5" +"source/extensions/listener_managers:77.3" +"source/extensions/listener_managers/validation_listener_manager:77.3" "source/extensions/watchdog/profile_action:83.3" "source/server:91.0" # flaky: be careful adjusting. See https://github.com/envoyproxy/envoy/issues/15239 "source/server/config_validation:91.8" diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 2b04f6be9239..76c8cb8b8a58 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -868,97 +868,99 @@ monotonic==1.6 \ --hash=sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7 \ --hash=sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c # via gsutil -multidict==6.0.5 \ - --hash=sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556 \ - --hash=sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c \ - --hash=sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29 \ - --hash=sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b \ - --hash=sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8 \ - --hash=sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7 \ - --hash=sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd \ - --hash=sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40 \ - --hash=sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6 \ - --hash=sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3 \ - --hash=sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c \ - --hash=sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9 \ - --hash=sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5 \ - --hash=sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae \ - --hash=sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442 \ - --hash=sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9 \ - --hash=sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc \ - --hash=sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c \ - --hash=sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea \ - --hash=sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5 \ - --hash=sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50 \ - --hash=sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182 \ - --hash=sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453 \ - --hash=sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e \ - --hash=sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600 \ - --hash=sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733 \ - --hash=sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda \ - --hash=sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241 \ - --hash=sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461 \ - --hash=sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e \ - --hash=sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e \ - --hash=sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b \ - --hash=sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e \ - --hash=sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7 \ - --hash=sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386 \ - --hash=sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd \ - --hash=sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9 \ - --hash=sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf \ - --hash=sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee \ - --hash=sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5 \ - --hash=sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a \ - --hash=sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271 \ - --hash=sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54 \ - --hash=sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4 \ - --hash=sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496 \ - --hash=sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb \ - --hash=sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319 \ - --hash=sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3 \ - --hash=sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f \ - --hash=sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527 \ - --hash=sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed \ - --hash=sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604 \ - --hash=sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef \ - --hash=sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8 \ - --hash=sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5 \ - --hash=sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5 \ - --hash=sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626 \ - --hash=sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c \ - --hash=sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d \ - --hash=sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c \ - --hash=sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc \ - --hash=sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc \ - --hash=sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b \ - --hash=sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38 \ - --hash=sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450 \ - --hash=sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1 \ - --hash=sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f \ - --hash=sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3 \ - --hash=sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755 \ - --hash=sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226 \ - --hash=sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a \ - --hash=sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046 \ - --hash=sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf \ - --hash=sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479 \ - --hash=sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e \ - --hash=sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1 \ - --hash=sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a \ - --hash=sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83 \ - --hash=sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929 \ - --hash=sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93 \ - --hash=sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a \ - --hash=sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c \ - --hash=sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44 \ - --hash=sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89 \ - --hash=sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba \ - --hash=sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e \ - --hash=sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da \ - --hash=sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24 \ - --hash=sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423 \ - --hash=sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef +multidict==6.1.0 \ + --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ + --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ + --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ + --hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \ + --hash=sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b \ + --hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \ + --hash=sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748 \ + --hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \ + --hash=sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f \ + --hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \ + --hash=sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6 \ + --hash=sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada \ + --hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \ + --hash=sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2 \ + --hash=sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d \ + --hash=sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a \ + --hash=sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef \ + --hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \ + --hash=sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb \ + --hash=sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60 \ + --hash=sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6 \ + --hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \ + --hash=sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478 \ + --hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \ + --hash=sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7 \ + --hash=sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56 \ + --hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \ + --hash=sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6 \ + --hash=sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30 \ + --hash=sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb \ + --hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \ + --hash=sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0 \ + --hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \ + --hash=sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c \ + --hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \ + --hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \ + --hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \ + --hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \ + --hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \ + --hash=sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2 \ + --hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \ + --hash=sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3 \ + --hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \ + --hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \ + --hash=sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657 \ + --hash=sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581 \ + --hash=sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492 \ + --hash=sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43 \ + --hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \ + --hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \ + --hash=sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926 \ + --hash=sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057 \ + --hash=sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc \ + --hash=sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80 \ + --hash=sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255 \ + --hash=sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1 \ + --hash=sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972 \ + --hash=sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53 \ + --hash=sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1 \ + --hash=sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423 \ + --hash=sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a \ + --hash=sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160 \ + --hash=sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c \ + --hash=sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd \ + --hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \ + --hash=sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5 \ + --hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \ + --hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \ + --hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \ + --hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \ + --hash=sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4 \ + --hash=sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156 \ + --hash=sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753 \ + --hash=sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28 \ + --hash=sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d \ + --hash=sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a \ + --hash=sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304 \ + --hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \ + --hash=sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429 \ + --hash=sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72 \ + --hash=sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399 \ + --hash=sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3 \ + --hash=sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392 \ + --hash=sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167 \ + --hash=sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c \ + --hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \ + --hash=sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351 \ + --hash=sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76 \ + --hash=sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875 \ + --hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \ + --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \ + --hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db # via # -r requirements.in # aiohttp @@ -1516,99 +1518,99 @@ yapf==0.40.2 \ # via # -r requirements.in # envoy-code-check -yarl==1.11.0 \ - --hash=sha256:01a7905e662665ca8e058635377522bc3c98bdb873be761ff42c86eb72b03914 \ - --hash=sha256:0310eb2e63872de66047e05ad9982f2e53ad6405dc42fa60d7cc670bf6ca8aa8 \ - --hash=sha256:03717a6627e55934b2a1d9caf24f299b461a2e8d048a90920f42ad5c20ae1b82 \ - --hash=sha256:03a726fb50588307dfe1d233b67535d493fb0bb157bdbfda6bb34e04189f2f57 \ - --hash=sha256:05ab59db0bb64e847972373c5cda8924e6605480f6b13cc04573fa0d87bfc637 \ - --hash=sha256:07e8cfb1dd7669a129f8fd5df1da65efa73aea77582bde2a3a837412e2863543 \ - --hash=sha256:0a657db1b9982f3dac0e360614d0e8945d2873da6e681fb7fca23ef1c3eb37f8 \ - --hash=sha256:0c58656c2e0b41b5d325130b8da4f8e216aad10029e7de5c523a6be25faa9fe8 \ - --hash=sha256:11af21bbf807688d49b7d4915bb28cbc2e3aa028a2ee194738477eabcc413c65 \ - --hash=sha256:121d3798e4bb35a4321b2422cb887f80ea39f94bf52f0eb5cb2c168bb0043c9b \ - --hash=sha256:18ec42da256cfcb9b4cd5d253e04c291f69911a5228d1438a7d431c15ba0ae40 \ - --hash=sha256:195f7791bc23d5f2480efe53f935daf8a61661000dfbfbdd70dbd06397594fff \ - --hash=sha256:1a29b82c42a7791ffe53ee6dfbf29acc61ea7ec05643dcacc50510ed6187b897 \ - --hash=sha256:202f5ec49ff163dcc767426deb55020a28078e61d6bbe1f80331d92bca53b236 \ - --hash=sha256:2371510367d39d74997acfdcd1dead17938c79c99365482821627f7838a8eba0 \ - --hash=sha256:24da0b38274727fe9266d09229987e7f0efdb97beb94c0bb2d327d65f112e78d \ - --hash=sha256:2516e238daf0339c8ac4dfab9d7cda9afad652ff073517f200d653d5d8371f7e \ - --hash=sha256:25f8bc849004122591104793a576e9c747b0e5d9486d6a30225521b817255748 \ - --hash=sha256:2949067359d1ef5bf3228c7f1deb102c209832a13df5419239f99449bc1d3fa9 \ - --hash=sha256:2a596bb15e036952549871a4ccd2205679902dc7f241e3ced6b2ab2e44c55795 \ - --hash=sha256:30f391ccf4b1b1e0ba4880075ba337d41a619a5350f67053927f67ebe764bf44 \ - --hash=sha256:31df9d9b3fe6e15decee629fc7976a5fb21eaa39e290f60e57e1d422827194c6 \ - --hash=sha256:361fdb3993431157302b7104d525092b5df4d7d346df5a5ffeee2d1ca8e0d15b \ - --hash=sha256:39e3087e1ef70862de81e22af9eb299faee580f41673ef92829949022791b521 \ - --hash=sha256:3a601c99fc20fd0eea84e7bc0dc9e7f196f55a0ded67242d724988c754295538 \ - --hash=sha256:3ade2265716667b6bd4123d6f684b5f7cf4a8d83dcf1d5581ac44643466bb00a \ - --hash=sha256:3c458483711d393dad51340505c3fab3194748fd06bab311d2f8b5b7a7349e9a \ - --hash=sha256:3d1bd3262e00043907e0a6d7d4f7b7a4815281acc25699a2384552870c79f1f0 \ - --hash=sha256:418eeb8f228ea36c368bf6782ebd6016ecebfb1a8b90145ef6726ffcbba65ef8 \ - --hash=sha256:42ff79371614764fc0a4ab8eaba9adb493bf9ad856e2a4664f6c754fc907a903 \ - --hash=sha256:48bac099586cf75ae5837b0ac17a674450d01f451f38afcb02acfc940110b60b \ - --hash=sha256:4a0d090d296ced05edfe29c6ff34869412fa6a97d0928c12b00939c4842884cd \ - --hash=sha256:4ae63bc65e5bf8843bd1eca46e75eaa9eb157e0312fb362123181512892daad8 \ - --hash=sha256:4c19a0d95943bb2c914b4e71043803be34bc75c08c4a6ca232bdc649a1e9ef1b \ - --hash=sha256:4c8dc0efcf8266ecfe057b95e01f43eb62516196a4bbf3918fd1dcb8d0dc0dff \ - --hash=sha256:4fa9d762eee63eed767895d68b994c58e29f809292a4d0fca483e9cc6fdc22c8 \ - --hash=sha256:50ceaeda771ee3e382291168c90c7ede62b63ecf3e181024bcfeb35c0ea6c84f \ - --hash=sha256:52433604340a4ab3d1f32281c6eb9ad9b47c99435b4212f763121bf7348c8c00 \ - --hash=sha256:53c80b1927b75aed208d7fd965a3a705dc8c1db4d50b9112418fa0f7784363e6 \ - --hash=sha256:540fd5f62fe21f3d1d9efe8af5c4d9dbbb184ce03ce95acb0289500e46215dd2 \ - --hash=sha256:5b008c3127382503e7a1e12b4c3a3236e3dd833a4c62a066f4a0fbd650c655d2 \ - --hash=sha256:60ed3c7f64e820959d7f682ec2f559b4f4df723dc09df619d269853a4214a4b4 \ - --hash=sha256:6471d747d0ac8059895e66d32ca8630c8db5b572ca7763150d0927eaa257df67 \ - --hash=sha256:65a1a05efca52b102691e64db5fcf973030a1c88fee393804ff91f99c95a6e74 \ - --hash=sha256:68e14ae71e5b51c8282ae5db53ccb3baffc40e1551370a8a2361f1c1d8a0bf8c \ - --hash=sha256:69a45c711fea9b783b592a75f26f6dc59b2e4a923b97bf6eec357566fcb1d922 \ - --hash=sha256:6e73dab98e3c3b5441720153e72a5f28e717aac2d22f1ec4b08ef33417d9987e \ - --hash=sha256:706ac0f77b45e9e0278ec6c98929764e119d3ce3136792b6475e7ae961da53ec \ - --hash=sha256:732d56da00ea7a5da4f0d15adbbd22dcb37da7825510aafde40112e53f6baa52 \ - --hash=sha256:765128029218eade3a01187cdd7f375977cc827505ed31828196c8ae9b622928 \ - --hash=sha256:79d420399f0e82e302236a762d8b8ceec89761ce3b30c83ac1d4d6e29f811444 \ - --hash=sha256:7bd54d79025b59d1dc5fb26a09734d6a9cc651a04bc381966ed264b28331a168 \ - --hash=sha256:7fd535cc41b81a566ad347081b671ab5c7e5f5b6a15526d85b4e748baf065cf0 \ - --hash=sha256:7ff371002fbbb79613269d76a2932c99979dac15fac30107064ef70d25f35474 \ - --hash=sha256:8055b0d78ce1cafa657c4b455e22661e8d3b2834de66a0753c3567da47fcc4aa \ - --hash=sha256:84624db40e2358cfd5cf2558b1aaffd93366d27ee32228a97785f2ec87d44a17 \ - --hash=sha256:8aee7c8378c6aa3103b99d1eb9995268ef730fa9f88ea68b9eee4341e204eec9 \ - --hash=sha256:9057f5de2fade7440e6db358913bc7ae8de43ba72c83cf95420a1fc1a6c6b59e \ - --hash=sha256:93fca4c9f88c17ead902b3f3285b2d039fc8f26d117e1441973ba64315109b54 \ - --hash=sha256:9425c333575fce5e0fb414b766492c6ba4aa335ef910a7540dbdefe58a78232e \ - --hash=sha256:969ad4ee3892e893471b6572bbf2bbb091f93e7c81de25d6b3a5c0a5126e5ccb \ - --hash=sha256:976d02274e6d88b24c7131e7b26a083412b2592f2bbcef53d3b00b2508cad26c \ - --hash=sha256:98e2eb182d59f0845a79434003f94b4f61cd69465248f9388c2e5bf2191c9f7f \ - --hash=sha256:9dc66e2420e1e282105071934883bbb9c37c16901b5b8aa0a8aee370b477eac6 \ - --hash=sha256:a45e51ba3777031e0b20c1e7ab59114ed4e1884b3c1db48962c1d8d08aefb418 \ - --hash=sha256:a4f7e470f2c9c8b8774a5bda72adfb8e9dc4ec32311fe9bdaa4921e36cf6659b \ - --hash=sha256:aacd62ff67efd54cb18cea2aa7ae4fb83cfbca19a07055d4777266b70561defe \ - --hash=sha256:b3dd10f0fe0e0f659926c1da791de5bef05fd48974ad74618c9168e302e2b7cc \ - --hash=sha256:b8bbac56c80610dd659ace534765d7bcd2488f6600023f6984f35108b2b3f4f0 \ - --hash=sha256:bc94be7472b9f88d7441340534a3ecae05c86ccfec7ba75ce5b6e4778b2bfc6e \ - --hash=sha256:c006fe73f851cf20b9986b3b4cc15239795bd5da9c3fda76bb3e043da5bec4ff \ - --hash=sha256:c6c0d640bad721834a737e25267fb71d296684ada21ca7d5ad2e63da7b73f1b7 \ - --hash=sha256:c9d4d2cc4b076c8ad0175a15ee9482a387b3303c97d4b71062db7356b2ac04c7 \ - --hash=sha256:c9fbe9dc6ee8bfe1af34137e3add6f0e49799dd5467dd6af189d27616879161e \ - --hash=sha256:d10be62bee117f05b1ad75a6c2538ca9e5367342dc8a4f3c206c87dadbc1189c \ - --hash=sha256:d29e446cfb0a82d3df7745968b9fa286665a9be8b4d68de46bcc32d917cb218e \ - --hash=sha256:d97cb22ad380850754fa16ef8d490d9340d8573d81f73429f3975e8e87db0586 \ - --hash=sha256:ddab47748933ac9cf5f29d6e9e2e2060cff40b2751d02c55129661ea4e577152 \ - --hash=sha256:e24bb6a8be89ccc3ce8c47e8940fdfcb7429e9efbf65ce6fa3e7d122fcf0bcf0 \ - --hash=sha256:e300eaf5e0329ad31b3d53e2f3d26b4b6dff1217207c6ab1d4212967b54b2185 \ - --hash=sha256:e38176a559edde0cfff4b663791a007a5f9f90c73aee1d6f7ddbcf6bfb7287b3 \ - --hash=sha256:e7dddf5f41395c84fc59e0ed5493b24bfeb39fb04823e880b52c8c55085d4695 \ - --hash=sha256:ea501ea07e14ba6364ff2621bfc8b2381e5b1e10353927fa9a607057fd2b98e5 \ - --hash=sha256:ead4d89eade0e09b8ef97877664abb0e2e8704787db5564f83658fdee5c36497 \ - --hash=sha256:ed0c090f00c3fc024f7b0799cab9dd7c419fcd8f1a00634d1f9952bab7e7bfb2 \ - --hash=sha256:f1e2d4ce72e06e38a16da3e9c24a0520dbc19018a69ef6ed57b6b38527cb275c \ - --hash=sha256:f4cb417d380e2d77961eecec75aaaf6f7ab14e6de26eb3a498f498029a6556a1 \ - --hash=sha256:f7cc02d8e9a612174869f4b983f159e87659096f7e2dc1fe9effd9902e408739 \ - --hash=sha256:f86f4f4a57a29ef08fa70c4667d04c5e3ba513500da95586208b285437cb9592 \ - --hash=sha256:fa9de2f87be58f714a230bd1f3ef3aad1ed65c9931146e3fc55f85fcbe6bacc3 \ - --hash=sha256:fcb7c36ba8b663a5900e6d40533f0e698ba0f38f744aad5410d4e38129e41a70 \ - --hash=sha256:fe78dec8caeda1e7b353cbd8aa0cc5a5bc182b22998d64ec8fa9ee59c898ab3b +yarl==1.11.1 \ + --hash=sha256:01a8697ec24f17c349c4f655763c4db70eebc56a5f82995e5e26e837c6eb0e49 \ + --hash=sha256:02da8759b47d964f9173c8675710720b468aa1c1693be0c9c64abb9d8d9a4867 \ + --hash=sha256:04293941646647b3bfb1719d1d11ff1028e9c30199509a844da3c0f5919dc520 \ + --hash=sha256:067b961853c8e62725ff2893226fef3d0da060656a9827f3f520fb1d19b2b68a \ + --hash=sha256:077da604852be488c9a05a524068cdae1e972b7dc02438161c32420fb4ec5e14 \ + --hash=sha256:09696438cb43ea6f9492ef237761b043f9179f455f405279e609f2bc9100212a \ + --hash=sha256:0b8486f322d8f6a38539136a22c55f94d269addb24db5cb6f61adc61eabc9d93 \ + --hash=sha256:0ea9682124fc062e3d931c6911934a678cb28453f957ddccf51f568c2f2b5e05 \ + --hash=sha256:0f351fa31234699d6084ff98283cb1e852270fe9e250a3b3bf7804eb493bd937 \ + --hash=sha256:14438dfc5015661f75f85bc5adad0743678eefee266ff0c9a8e32969d5d69f74 \ + --hash=sha256:15061ce6584ece023457fb8b7a7a69ec40bf7114d781a8c4f5dcd68e28b5c53b \ + --hash=sha256:15439f3c5c72686b6c3ff235279630d08936ace67d0fe5c8d5bbc3ef06f5a420 \ + --hash=sha256:17b5a386d0d36fb828e2fb3ef08c8829c1ebf977eef88e5367d1c8c94b454639 \ + --hash=sha256:18ac56c9dd70941ecad42b5a906820824ca72ff84ad6fa18db33c2537ae2e089 \ + --hash=sha256:1bb2d9e212fb7449b8fb73bc461b51eaa17cc8430b4a87d87be7b25052d92f53 \ + --hash=sha256:1e969fa4c1e0b1a391f3fcbcb9ec31e84440253325b534519be0d28f4b6b533e \ + --hash=sha256:1fa2e7a406fbd45b61b4433e3aa254a2c3e14c4b3186f6e952d08a730807fa0c \ + --hash=sha256:2164cd9725092761fed26f299e3f276bb4b537ca58e6ff6b252eae9631b5c96e \ + --hash=sha256:21a7c12321436b066c11ec19c7e3cb9aec18884fe0d5b25d03d756a9e654edfe \ + --hash=sha256:238a21849dd7554cb4d25a14ffbfa0ef380bb7ba201f45b144a14454a72ffa5a \ + --hash=sha256:250e888fa62d73e721f3041e3a9abf427788a1934b426b45e1b92f62c1f68366 \ + --hash=sha256:25861303e0be76b60fddc1250ec5986c42f0a5c0c50ff57cc30b1be199c00e63 \ + --hash=sha256:267b24f891e74eccbdff42241c5fb4f974de2d6271dcc7d7e0c9ae1079a560d9 \ + --hash=sha256:27fcb271a41b746bd0e2a92182df507e1c204759f460ff784ca614e12dd85145 \ + --hash=sha256:2909fa3a7d249ef64eeb2faa04b7957e34fefb6ec9966506312349ed8a7e77bf \ + --hash=sha256:3257978c870728a52dcce8c2902bf01f6c53b65094b457bf87b2644ee6238ddc \ + --hash=sha256:327c724b01b8641a1bf1ab3b232fb638706e50f76c0b5bf16051ab65c868fac5 \ + --hash=sha256:3de5292f9f0ee285e6bd168b2a77b2a00d74cbcfa420ed078456d3023d2f6dff \ + --hash=sha256:3fce4da3703ee6048ad4138fe74619c50874afe98b1ad87b2698ef95bf92c96d \ + --hash=sha256:3ff6b1617aa39279fe18a76c8d165469c48b159931d9b48239065767ee455b2b \ + --hash=sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00 \ + --hash=sha256:4179522dc0305c3fc9782549175c8e8849252fefeb077c92a73889ccbcd508ad \ + --hash=sha256:4307d9a3417eea87715c9736d050c83e8c1904e9b7aada6ce61b46361b733d92 \ + --hash=sha256:476e20c433b356e16e9a141449f25161e6b69984fb4cdbd7cd4bd54c17844998 \ + --hash=sha256:489fa8bde4f1244ad6c5f6d11bb33e09cf0d1d0367edb197619c3e3fc06f3d91 \ + --hash=sha256:48a28bed68ab8fb7e380775f0029a079f08a17799cb3387a65d14ace16c12e2b \ + --hash=sha256:48dfd117ab93f0129084577a07287376cc69c08138694396f305636e229caa1a \ + --hash=sha256:4973eac1e2ff63cf187073cd4e1f1148dcd119314ab79b88e1b3fad74a18c9d5 \ + --hash=sha256:498442e3af2a860a663baa14fbf23fb04b0dd758039c0e7c8f91cb9279799bff \ + --hash=sha256:501c503eed2bb306638ccb60c174f856cc3246c861829ff40eaa80e2f0330367 \ + --hash=sha256:504cf0d4c5e4579a51261d6091267f9fd997ef58558c4ffa7a3e1460bd2336fa \ + --hash=sha256:61a5f2c14d0a1adfdd82258f756b23a550c13ba4c86c84106be4c111a3a4e413 \ + --hash=sha256:637c7ddb585a62d4469f843dac221f23eec3cbad31693b23abbc2c366ad41ff4 \ + --hash=sha256:66b63c504d2ca43bf7221a1f72fbe981ff56ecb39004c70a94485d13e37ebf45 \ + --hash=sha256:67459cf8cf31da0e2cbdb4b040507e535d25cfbb1604ca76396a3a66b8ba37a6 \ + --hash=sha256:688654f8507464745ab563b041d1fb7dab5d9912ca6b06e61d1c4708366832f5 \ + --hash=sha256:6907daa4b9d7a688063ed098c472f96e8181733c525e03e866fb5db480a424df \ + --hash=sha256:69721b8effdb588cb055cc22f7c5105ca6fdaa5aeb3ea09021d517882c4a904c \ + --hash=sha256:6d23754b9939cbab02c63434776df1170e43b09c6a517585c7ce2b3d449b7318 \ + --hash=sha256:7175a87ab8f7fbde37160a15e58e138ba3b2b0e05492d7351314a250d61b1591 \ + --hash=sha256:72bf26f66456baa0584eff63e44545c9f0eaed9b73cb6601b647c91f14c11f38 \ + --hash=sha256:74db2ef03b442276d25951749a803ddb6e270d02dda1d1c556f6ae595a0d76a8 \ + --hash=sha256:750f656832d7d3cb0c76be137ee79405cc17e792f31e0a01eee390e383b2936e \ + --hash=sha256:75e0ae31fb5ccab6eda09ba1494e87eb226dcbd2372dae96b87800e1dcc98804 \ + --hash=sha256:768ecc550096b028754ea28bf90fde071c379c62c43afa574edc6f33ee5daaec \ + --hash=sha256:7d51324a04fc4b0e097ff8a153e9276c2593106a811704025bbc1d6916f45ca6 \ + --hash=sha256:7e975a2211952a8a083d1b9d9ba26472981ae338e720b419eb50535de3c02870 \ + --hash=sha256:8215f6f21394d1f46e222abeb06316e77ef328d628f593502d8fc2a9117bde83 \ + --hash=sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d \ + --hash=sha256:8418c053aeb236b20b0ab8fa6bacfc2feaaf7d4683dd96528610989c99723d5f \ + --hash=sha256:87f020d010ba80a247c4abc335fc13421037800ca20b42af5ae40e5fd75e7909 \ + --hash=sha256:884eab2ce97cbaf89f264372eae58388862c33c4f551c15680dd80f53c89a269 \ + --hash=sha256:8a336eaa7ee7e87cdece3cedb395c9657d227bfceb6781295cf56abcd3386a26 \ + --hash=sha256:8aef1b64da41d18026632d99a06b3fefe1d08e85dd81d849fa7c96301ed22f1b \ + --hash=sha256:8aef97ba1dd2138112890ef848e17d8526fe80b21f743b4ee65947ea184f07a2 \ + --hash=sha256:8ed653638ef669e0efc6fe2acb792275cb419bf9cb5c5049399f3556995f23c7 \ + --hash=sha256:9361628f28f48dcf8b2f528420d4d68102f593f9c2e592bfc842f5fb337e44fd \ + --hash=sha256:946eedc12895873891aaceb39bceb484b4977f70373e0122da483f6c38faaa68 \ + --hash=sha256:94d0caaa912bfcdc702a4204cd5e2bb01eb917fc4f5ea2315aa23962549561b0 \ + --hash=sha256:964a428132227edff96d6f3cf261573cb0f1a60c9a764ce28cda9525f18f7786 \ + --hash=sha256:999bfee0a5b7385a0af5ffb606393509cfde70ecca4f01c36985be6d33e336da \ + --hash=sha256:a08ea567c16f140af8ddc7cb58e27e9138a1386e3e6e53982abaa6f2377b38cc \ + --hash=sha256:a28b70c9e2213de425d9cba5ab2e7f7a1c8ca23a99c4b5159bf77b9c31251447 \ + --hash=sha256:a34e1e30f1774fa35d37202bbeae62423e9a79d78d0874e5556a593479fdf239 \ + --hash=sha256:a4264515f9117be204935cd230fb2a052dd3792789cc94c101c535d349b3dab0 \ + --hash=sha256:a7915ea49b0c113641dc4d9338efa9bd66b6a9a485ffe75b9907e8573ca94b84 \ + --hash=sha256:aac44097d838dda26526cffb63bdd8737a2dbdf5f2c68efb72ad83aec6673c7e \ + --hash=sha256:b91044952da03b6f95fdba398d7993dd983b64d3c31c358a4c89e3c19b6f7aef \ + --hash=sha256:ba444bdd4caa2a94456ef67a2f383710928820dd0117aae6650a4d17029fa25e \ + --hash=sha256:c2dc4250fe94d8cd864d66018f8344d4af50e3758e9d725e94fecfa27588ff82 \ + --hash=sha256:c35f493b867912f6fda721a59cc7c4766d382040bdf1ddaeeaa7fa4d072f4675 \ + --hash=sha256:c92261eb2ad367629dc437536463dc934030c9e7caca861cc51990fe6c565f26 \ + --hash=sha256:ce928c9c6409c79e10f39604a7e214b3cb69552952fbda8d836c052832e6a979 \ + --hash=sha256:d95b52fbef190ca87d8c42f49e314eace4fc52070f3dfa5f87a6594b0c1c6e46 \ + --hash=sha256:dae7bd0daeb33aa3e79e72877d3d51052e8b19c9025ecf0374f542ea8ec120e4 \ + --hash=sha256:e286580b6511aac7c3268a78cdb861ec739d3e5a2a53b4809faef6b49778eaff \ + --hash=sha256:e4b53f73077e839b3f89c992223f15b1d2ab314bdbdf502afdc7bb18e95eae27 \ + --hash=sha256:e8f63904df26d1a66aabc141bfd258bf738b9bc7bc6bdef22713b4f5ef789a4c \ + --hash=sha256:f3a6d90cab0bdf07df8f176eae3a07127daafcf7457b997b2bf46776da2c7eb7 \ + --hash=sha256:f41fa79114a1d2eddb5eea7b912d6160508f57440bd302ce96eaa384914cd265 \ + --hash=sha256:f46f81501160c28d0c0b7333b4f7be8983dbbc161983b6fb814024d1b4952f79 \ + --hash=sha256:f61db3b7e870914dbd9434b560075e0366771eecbe6d2b5561f5bc7485f39efd # via # -r requirements.in # aiohttp diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index 263479eba905..452a48b9a23e 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -1537,3 +1537,4 @@ NAT NXDOMAIN DNAT RSP +EWMA