From f413f859a6a7a5a673949bf20ea25a2f388d2078 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Thu, 5 Mar 2026 23:49:34 +0000 Subject: [PATCH 1/5] Add metadata for HDS response Signed-off-by: Takeshi Yoneda --- api/envoy/service/health/v3/hds.proto | 14 ++++ envoy/upstream/upstream.h | 13 ++++ .../upstream/health_discovery_service.cc | 8 ++ source/common/upstream/upstream_impl.h | 4 + .../http/health_checker_impl.cc | 5 ++ test/common/upstream/hds_test.cc | 77 +++++++++++++++++++ 6 files changed, 121 insertions(+) diff --git a/api/envoy/service/health/v3/hds.proto b/api/envoy/service/health/v3/hds.proto index 41ed2040b1a73..a0dc8c66a910f 100644 --- a/api/envoy/service/health/v3/hds.proto +++ b/api/envoy/service/health/v3/hds.proto @@ -10,6 +10,7 @@ import "envoy/config/endpoint/v3/endpoint_components.proto"; import "google/api/annotations.proto"; import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; @@ -109,6 +110,19 @@ message EndpointHealth { config.endpoint.v3.Endpoint endpoint = 1; config.core.v3.HealthStatus health_status = 2; + + // Optional metadata about the health check result, populated by the active + // health checker and forwarded to the management server for richer health + // state interpretation. + // + // Well-known keys: + // + // ``http_status_code`` (number) + // Set by the HTTP health checker. Contains the HTTP response status code + // returned by the upstream endpoint during the most recent health check, + // e.g. ``200``, ``503``. Only present when the health check received a + // complete HTTP response; absent on connection failures or timeouts. + google.protobuf.Struct health_metadata = 3; } // Group endpoint health by locality under each cluster. diff --git a/envoy/upstream/upstream.h b/envoy/upstream/upstream.h index b8685b06b6ef4..1d2d3ae159c56 100644 --- a/envoy/upstream/upstream.h +++ b/envoy/upstream/upstream.h @@ -323,6 +323,19 @@ class Host : virtual public HostDescription { * Set true to disable active health check for the host. */ virtual void setDisableActiveHealthCheck(bool disable_active_health_check) PURE; + + /** + * Store the HTTP status code from the last active health check response. + * Used by HDS to report richer health state to the control plane. + * 0 means no response has been recorded yet. + */ + virtual void setLastHealthCheckHttpStatus(uint32_t) {} + + /** + * @return the HTTP status code from the last active health check response, or + * 0 if no response has been recorded. + */ + virtual uint32_t lastHealthCheckHttpStatus() const { return 0; } }; using HostConstSharedPtr = std::shared_ptr; diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index 9354ca79e5df6..74f992b5d0e63 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -124,6 +124,14 @@ envoy::service::health::v3::HealthCheckRequestOrEndpointHealthResponse HdsDelega } } + // If a HTTP health check has run, attach the last response code to the + // HDS report so the control plane can interpret richer health states. + const uint32_t http_status = host->lastHealthCheckHttpStatus(); + if (http_status != 0) { + (*endpoint->mutable_health_metadata()->mutable_fields())["http_status_code"] + .set_number_value(http_status); + } + // TODO(drewsortega): remove this once we are on v4 and endpoint_health_response is // removed. Copy this endpoint's health info to the legacy flat-list. response.mutable_endpoint_health_response()->add_endpoints_health()->MergeFrom(*endpoint); diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index 9387f644be238..1b0e43531f155 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -378,6 +378,9 @@ class HostImplBase : public Host, uint32_t healthFlagsGetAll() const override { return health_flags_; } void healthFlagsSetAll(uint32_t bits) override { health_flags_ |= bits; } + void setLastHealthCheckHttpStatus(uint32_t status) override { last_hc_http_status_ = status; } + uint32_t lastHealthCheckHttpStatus() const override { return last_hc_http_status_; } + Host::HealthStatus healthStatus() const override { // Evaluate active health status first. @@ -465,6 +468,7 @@ class HostImplBase : public Host, // flag access? May be we could refactor HealthFlag to contain all these statuses and flags in the // future. std::atomic eds_health_status_{}; + std::atomic last_hc_http_status_{0}; struct HostHandleImpl : HostHandle { HostHandleImpl(const std::shared_ptr& parent) : parent_(parent) { diff --git a/source/extensions/health_checkers/http/health_checker_impl.cc b/source/extensions/health_checkers/http/health_checker_impl.cc index 5c08c5e0d4083..8d6c8a281aecd 100644 --- a/source/extensions/health_checkers/http/health_checker_impl.cc +++ b/source/extensions/health_checkers/http/health_checker_impl.cc @@ -419,6 +419,11 @@ HttpHealthCheckerImpl::HttpActiveHealthCheckSession::healthCheckResult() { void HttpHealthCheckerImpl::HttpActiveHealthCheckSession::onResponseComplete() { request_in_flight_ = false; + // Store the raw HTTP response code on the host for HDS metadata reporting. + if (response_headers_ != nullptr) { + host_->setLastHealthCheckHttpStatus(Http::Utility::getResponseStatus(*response_headers_)); + } + switch (healthCheckResult()) { case HealthCheckResult::Succeeded: handleSuccess(false); diff --git a/test/common/upstream/hds_test.cc b/test/common/upstream/hds_test.cc index 2a30969a78de9..fd4b754108e05 100644 --- a/test/common/upstream/hds_test.cc +++ b/test/common/upstream/hds_test.cc @@ -1288,5 +1288,82 @@ TEST_F(HdsTest, TestCustomHealthCheckPortWhenUpdate) { } } +// Test that sendResponse includes health_metadata with http_status_code +// when setHealthCheckMetadata has been called on a host. +TEST_F(HdsTest, TestSendResponseWithHealthMetadata) { + EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_)); + EXPECT_CALL(async_stream_, sendMessageRaw_(_, _)); + createHdsDelegate(); + + // Create Message + message.reset(createSimpleMessage()); + + Network::MockClientConnection* connection_ = new NiceMock(); + EXPECT_CALL(server_context_.dispatcher_, createClientConnection_(_, _, _, _)) + .WillRepeatedly(Return(connection_)); + EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(2); + EXPECT_CALL(async_stream_, sendMessageRaw_(_, false)); + EXPECT_CALL(*test_factory_, createClusterInfo(_)).WillOnce(Return(cluster_info_)); + EXPECT_CALL(*connection_, setBufferLimits(_)); + EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)); + + // Process message + hds_delegate_->onReceiveMessage(std::move(message)); + connection_->raiseEvent(Network::ConnectionEvent::Connected); + + // Set the HTTP response code on the host to simulate a health check result. + auto& host = hds_delegate_->hdsClusters()[0]->prioritySet().hostSetsPerPriority()[0]->hosts()[0]; + host->setLastHealthCheckHttpStatus(200); + + // Send Response + auto msg = hds_delegate_->sendResponse(); + + // Verify health_metadata contains the HTTP status code in the legacy flat list. + const auto& endpoint_health = msg.endpoint_health_response().endpoints_health(0); + ASSERT_TRUE(endpoint_health.has_health_metadata()); + const auto& fields = endpoint_health.health_metadata().fields(); + auto it = fields.find("http_status_code"); + ASSERT_NE(it, fields.end()); + EXPECT_EQ(it->second.number_value(), 200.0); + + // Also verify the structured (cluster-based) response. + const auto& cluster_endpoint = + msg.endpoint_health_response().cluster_endpoints_health(0).locality_endpoints_health(0); + const auto& structured_endpoint = cluster_endpoint.endpoints_health(0); + ASSERT_TRUE(structured_endpoint.has_health_metadata()); + EXPECT_EQ(structured_endpoint.health_metadata().fields().at("http_status_code").number_value(), + 200.0); +} + +// Test that sendResponse does not include health_metadata when no metadata +// has been set on the host (default empty Struct). +TEST_F(HdsTest, TestSendResponseNoHealthMetadataByDefault) { + EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_)); + EXPECT_CALL(async_stream_, sendMessageRaw_(_, _)); + createHdsDelegate(); + + // Create Message + message.reset(createSimpleMessage()); + + Network::MockClientConnection* connection_ = new NiceMock(); + EXPECT_CALL(server_context_.dispatcher_, createClientConnection_(_, _, _, _)) + .WillRepeatedly(Return(connection_)); + EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(2); + EXPECT_CALL(async_stream_, sendMessageRaw_(_, false)); + EXPECT_CALL(*test_factory_, createClusterInfo(_)).WillOnce(Return(cluster_info_)); + EXPECT_CALL(*connection_, setBufferLimits(_)); + EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)); + + // Process message (do NOT set any health metadata on host) + hds_delegate_->onReceiveMessage(std::move(message)); + connection_->raiseEvent(Network::ConnectionEvent::Connected); + + // Send Response + auto msg = hds_delegate_->sendResponse(); + + // Verify health_metadata is absent when no metadata has been set. + EXPECT_FALSE(msg.endpoint_health_response().endpoints_health(0).has_health_metadata()); +} + } // namespace Upstream } // namespace Envoy From 4c6d710668265354dd11c58740593d5b2bfb56d1 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Thu, 5 Mar 2026 23:57:11 +0000 Subject: [PATCH 2/5] add coverage Signed-off-by: Takeshi Yoneda --- .../upstream/health_checker_impl_test.cc | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/common/upstream/health_checker_impl_test.cc b/test/common/upstream/health_checker_impl_test.cc index e1aaca4a4bcca..63aad863e1f90 100644 --- a/test/common/upstream/health_checker_impl_test.cc +++ b/test/common/upstream/health_checker_impl_test.cc @@ -899,6 +899,42 @@ TEST_F(HttpHealthCheckerImplTest, Success) { cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->coarseHealth()); } +// Verify that lastHealthCheckHttpStatus is recorded for a 200 response and +// updated on a subsequent 503. +TEST_F(HttpHealthCheckerImplTest, LastHealthCheckHttpStatusRecorded) { + setupNoServiceValidationHC(); + EXPECT_CALL(*this, onHostStatus(_, _)).Times(2); + + cluster_->prioritySet().getMockHostSet(0)->hosts_ = { + makeTestHost(cluster_->info_, "tcp://127.0.0.1:80")}; + cluster_->info_->trafficStats()->upstream_cx_total_.inc(); + expectSessionCreate(); + expectStreamCreate(0); + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); + health_checker_->start(); + + EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); + EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _)) + .WillRepeatedly(Return(45000)); + EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); + respond(0, "200", false, false, true); + EXPECT_EQ(200U, + cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->lastHealthCheckHttpStatus()); + + // A second check with a 503 should overwrite the stored status. + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_, _)); + expectStreamCreate(0); + test_sessions_[0]->interval_timer_->invokeCallback(); + EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _)); + EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(_, _)); + EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer()); + EXPECT_CALL(event_logger_, logEjectUnhealthy(_, _, _)); + respond(0, "503", false, false, true); + EXPECT_EQ(503U, + cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->lastHealthCheckHttpStatus()); +} + TEST_F(HttpHealthCheckerImplTest, Degraded) { setupNoServiceValidationHC(); EXPECT_CALL(*this, onHostStatus(_, HealthTransition::Changed)).Times(2); From ad8e1177937b2957b27913894004b0050836f24b Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Thu, 19 Mar 2026 22:04:52 +0000 Subject: [PATCH 3/5] review: pure virtual & use uint64_t & optional Signed-off-by: Takeshi Yoneda --- envoy/upstream/upstream.h | 4 ++-- source/common/upstream/health_discovery_service.cc | 6 +++--- source/common/upstream/upstream_impl.h | 6 ++++-- test/mocks/upstream/host.h | 2 ++ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/envoy/upstream/upstream.h b/envoy/upstream/upstream.h index 91b04100cde92..5da2d68054021 100644 --- a/envoy/upstream/upstream.h +++ b/envoy/upstream/upstream.h @@ -329,13 +329,13 @@ class Host : virtual public HostDescription { * Used by HDS to report richer health state to the control plane. * 0 means no response has been recorded yet. */ - virtual void setLastHealthCheckHttpStatus(uint32_t) {} + virtual void setLastHealthCheckHttpStatus(uint32_t) PURE; /** * @return the HTTP status code from the last active health check response, or * 0 if no response has been recorded. */ - virtual uint32_t lastHealthCheckHttpStatus() const { return 0; } + virtual absl::optional lastHealthCheckHttpStatus() const PURE; }; using HostConstSharedPtr = std::shared_ptr; diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index 74f992b5d0e63..649c78cb1a0c6 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -126,10 +126,10 @@ envoy::service::health::v3::HealthCheckRequestOrEndpointHealthResponse HdsDelega // If a HTTP health check has run, attach the last response code to the // HDS report so the control plane can interpret richer health states. - const uint32_t http_status = host->lastHealthCheckHttpStatus(); - if (http_status != 0) { + auto http_status = host->lastHealthCheckHttpStatus(); + if (http_status.has_value()) { (*endpoint->mutable_health_metadata()->mutable_fields())["http_status_code"] - .set_number_value(http_status); + .set_number_value(http_status.value()); } // TODO(drewsortega): remove this once we are on v4 and endpoint_health_response is diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index d7a31337c398a..9be69ffc4f008 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -379,7 +379,9 @@ class HostImplBase : public Host, void healthFlagsSetAll(uint32_t bits) override { health_flags_ |= bits; } void setLastHealthCheckHttpStatus(uint32_t status) override { last_hc_http_status_ = status; } - uint32_t lastHealthCheckHttpStatus() const override { return last_hc_http_status_; } + absl::optional lastHealthCheckHttpStatus() const override { + return last_hc_http_status_; + } Host::HealthStatus healthStatus() const override { // Evaluate active health status first. @@ -469,7 +471,7 @@ class HostImplBase : public Host, // flag access? May be we could refactor HealthFlag to contain all these statuses and flags in the // future. std::atomic eds_health_status_{}; - std::atomic last_hc_http_status_{0}; + absl::optional> last_hc_http_status_ = absl::nullopt; struct HostHandleImpl : HostHandle { HostHandleImpl(const std::shared_ptr& parent) : parent_(parent) { diff --git a/test/mocks/upstream/host.h b/test/mocks/upstream/host.h index 28bbd08f5d09a..5186fd3804e3f 100644 --- a/test/mocks/upstream/host.h +++ b/test/mocks/upstream/host.h @@ -216,6 +216,8 @@ class MockHostLight : public Host { MOCK_METHOD(absl::optional, lastHcPassTime, (), (const)); MOCK_METHOD(void, setLbPolicyData, (HostLbPolicyDataPtr lb_policy_data)); MOCK_METHOD(OptRef, lbPolicyData, (), (const)); + MOCK_METHOD(void, setLastHealthCheckHttpStatus, (uint32_t)); + MOCK_METHOD(absl::optional, lastHealthCheckHttpStatus, (), (const)); bool disable_active_health_check_ = false; }; From 067e397506ed916dae0165cc5a45051b2b64a717 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 24 Mar 2026 01:58:38 +0000 Subject: [PATCH 4/5] review: use 32_t Signed-off-by: Takeshi Yoneda --- envoy/upstream/upstream.h | 2 +- source/common/upstream/upstream_impl.h | 2 +- test/mocks/upstream/host.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/envoy/upstream/upstream.h b/envoy/upstream/upstream.h index 5da2d68054021..99fdecb7ebf58 100644 --- a/envoy/upstream/upstream.h +++ b/envoy/upstream/upstream.h @@ -329,7 +329,7 @@ class Host : virtual public HostDescription { * Used by HDS to report richer health state to the control plane. * 0 means no response has been recorded yet. */ - virtual void setLastHealthCheckHttpStatus(uint32_t) PURE; + virtual void setLastHealthCheckHttpStatus(uint64_t) PURE; /** * @return the HTTP status code from the last active health check response, or diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index 5a3d9bf0328c6..768ee71fb43d1 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -383,7 +383,7 @@ class HostImplBase : public Host, uint32_t healthFlagsGetAll() const override { return health_flags_; } void healthFlagsSetAll(uint32_t bits) override { health_flags_ |= bits; } - void setLastHealthCheckHttpStatus(uint32_t status) override { last_hc_http_status_ = status; } + void setLastHealthCheckHttpStatus(uint64_t status) override { last_hc_http_status_ = status; } absl::optional lastHealthCheckHttpStatus() const override { return last_hc_http_status_; } diff --git a/test/mocks/upstream/host.h b/test/mocks/upstream/host.h index 5186fd3804e3f..1506abfbfae84 100644 --- a/test/mocks/upstream/host.h +++ b/test/mocks/upstream/host.h @@ -216,7 +216,7 @@ class MockHostLight : public Host { MOCK_METHOD(absl::optional, lastHcPassTime, (), (const)); MOCK_METHOD(void, setLbPolicyData, (HostLbPolicyDataPtr lb_policy_data)); MOCK_METHOD(OptRef, lbPolicyData, (), (const)); - MOCK_METHOD(void, setLastHealthCheckHttpStatus, (uint32_t)); + MOCK_METHOD(void, setLastHealthCheckHttpStatus, (uint64_t)); MOCK_METHOD(absl::optional, lastHealthCheckHttpStatus, (), (const)); bool disable_active_health_check_ = false; From 131053f40872ad6e5be1cf3cc9251ff28c9626a2 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Wed, 25 Mar 2026 17:43:16 +0000 Subject: [PATCH 5/5] Adds Cargo workspace Signed-off-by: Takeshi Yoneda --- Cargo.lock | 312 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 + 2 files changed, 315 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000000..5408ae0149a37 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,312 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "envoy-proxy-dynamic-modules-rust-sdk" +version = "0.1.0" +dependencies = [ + "bindgen", + "mockall", +] + +[[package]] +name = "fragile" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "mockall" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "predicates" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" +dependencies = [ + "anstyle", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" + +[[package]] +name = "predicates-tree" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "test-programs" +version = "0.1.0" +dependencies = [ + "envoy-proxy-dynamic-modules-rust-sdk", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000000..7997a7ba7af34 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +members = ["source/extensions/dynamic_modules/sdk/rust", "test/extensions/dynamic_modules/test_data/rust"] +resolver = "2"