Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

formatter: support for virtual host metadata #34958

Merged
merged 8 commits into from
Jul 11, 2024
1 change: 1 addition & 0 deletions api/envoy/extensions/formatter/metadata/v3/metadata.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// * ROUTE
// * UPSTREAM_HOST
// * LISTENER
// * VIRTUAL_HOST
//
// See :ref:`here <config_access_log>` for more information on access log configuration.

Expand Down
3 changes: 3 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,9 @@ new_features:
Added :ref:`strip_failure_response
<envoy_v3_api_field_extensions.filters.http.jwt_authn.v3.JwtAuthentication.strip_failure_response>`
to allow stripping the failure response details from the JWT authentication filter.
- area: formatter
change: |
added formatters for :ref:`METADATA(VIRTUAL_HOST)<envoy_v3_api_msg_extensions.formatter.metadata.v3.Metadata>`.
- area: quic
change: |
Added :ref:`DataSourceServerPreferredAddressConfig
Expand Down
29 changes: 29 additions & 0 deletions source/extensions/formatter/metadata/metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,29 @@ class ListenerMetadataFormatter : public ::Envoy::Formatter::MetadataFormatter {
}) {}
};

// Metadata formatter for virtual host metadata.
class VirtualHostMetadataFormatter : public ::Envoy::Formatter::MetadataFormatter {
public:
VirtualHostMetadataFormatter(const std::string& filter_namespace,
const std::vector<std::string>& path,
absl::optional<size_t> max_length)
: ::Envoy::Formatter::MetadataFormatter(filter_namespace, path, max_length,
[](const StreamInfo::StreamInfo& stream_info)
-> const envoy::config::core::v3::Metadata* {
Router::RouteConstSharedPtr route =
stream_info.route();
if (route == nullptr) {
return nullptr;
}
const Router::RouteEntry* route_entry =
route->routeEntry();
if (route_entry == nullptr) {
return nullptr;
}
return &route_entry->virtualHost().metadata();
}) {}
};

// Constructor registers all types of supported metadata along with the
// handlers accessing the required metadata type.
MetadataFormatterCommandParser::MetadataFormatterCommandParser() {
Expand Down Expand Up @@ -78,6 +101,12 @@ MetadataFormatterCommandParser::MetadataFormatterCommandParser() {
absl::optional<size_t> max_length) {
return std::make_unique<ListenerMetadataFormatter>(filter_namespace, path, max_length);
};

metadata_formatter_providers_["VIRTUAL_HOST"] = [](const std::string& filter_namespace,
const std::vector<std::string>& path,
absl::optional<size_t> max_length) {
return std::make_unique<VirtualHostMetadataFormatter>(filter_namespace, path, max_length);
};
}

::Envoy::Formatter::FormatterProviderPtr
Expand Down
30 changes: 30 additions & 0 deletions test/extensions/formatter/metadata/metadata_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,36 @@ TEST_F(MetadataFormatterTest, NoListenerMetadata) {
getTestMetadataFormatter("LISTENER")->formatWithContext(formatter_context_, stream_info_));
}

// Test that METADATA(VIRTUAL_HOST accesses selected virtual host metadata.
TEST_F(MetadataFormatterTest, VirtualHostMetadata) {
std::shared_ptr<Router::MockRoute> route{new NiceMock<Router::MockRoute>()};
EXPECT_CALL(stream_info_, route()).WillRepeatedly(testing::Return(route));

std::shared_ptr<Router::MockRouteEntry> route_entry{new NiceMock<Router::MockRouteEntry>()};
EXPECT_CALL(*route, routeEntry()).WillRepeatedly(testing::Return(route_entry.get()));

std::shared_ptr<Router::MockVirtualHost> virtual_host{new NiceMock<Router::MockVirtualHost>()};
EXPECT_CALL(*route_entry, virtualHost()).WillRepeatedly(testing::ReturnRef(*virtual_host));

EXPECT_CALL(*virtual_host, metadata()).WillRepeatedly(testing::ReturnRef(*metadata_));
EXPECT_EQ("test_value", getTestMetadataFormatter("VIRTUAL_HOST")
->formatWithContext(formatter_context_, stream_info_));
}

TEST_F(MetadataFormatterTest, VirtualHostMetadataNoRoute) {
EXPECT_CALL(stream_info_, route()).WillRepeatedly(testing::Return(nullptr));
EXPECT_EQ("-", getTestMetadataFormatter("VIRTUAL_HOST")
->formatWithContext(formatter_context_, stream_info_));
}

TEST_F(MetadataFormatterTest, VirtualHostMetadataNoRouteEntry) {
std::shared_ptr<Router::MockRoute> route{new NiceMock<Router::MockRoute>()};
EXPECT_CALL(stream_info_, route()).WillRepeatedly(testing::Return(route));
EXPECT_CALL(*route, routeEntry()).WillRepeatedly(testing::Return(nullptr));
EXPECT_EQ("-", getTestMetadataFormatter("VIRTUAL_HOST")
->formatWithContext(formatter_context_, stream_info_));
}

} // namespace Formatter
} // namespace Extensions
} // namespace Envoy