Skip to content

Commit

Permalink
api/config: use resource type annotations to provide type-to-endpoint. (
Browse files Browse the repository at this point in the history
#9566)

Previously, type_to_endpoint.cc had a lot of hardcoding, which doesn't scale well with multiple API
versions. See #9526 for an example of the issues
encountered.

This patch switches to using explicit resource type annotations on service descriptors, which is
great for documentation (previously this was sometimes given in comments, sometimes not), and allows
for a reflection driven reverse map from resource type URL to endpoints to be built at runtime.

Risk level: Low
Testing: New unit tests for type_to_endpoint.cc and golden protoxform tests for the new annotations.

Fixes #9454.

Signed-off-by: Harvey Tuch <htuch@google.com>
  • Loading branch information
htuch authored Jan 6, 2020
1 parent a60f685 commit cceab39
Show file tree
Hide file tree
Showing 62 changed files with 473 additions and 112 deletions.
5 changes: 5 additions & 0 deletions api/envoy/annotations/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package()
16 changes: 16 additions & 0 deletions api/envoy/annotations/resource.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
syntax = "proto3";

package envoy.annotations;

import "google/protobuf/descriptor.proto";

// Magic number in this file derived from top 28bit of SHA256 digest of "envoy.annotation.resource".
extend google.protobuf.ServiceOptions {
ResourceAnnotation resource = 265073217;
}

message ResourceAnnotation {
// Annotation for xDS services that indicates the fully-qualified Protobuf type for the resource
// type.
string type = 1;
}
1 change: 1 addition & 0 deletions api/envoy/api/v2/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/api/v2/auth:pkg",
"//envoy/api/v2/cluster:pkg",
"//envoy/api/v2/core:pkg",
Expand Down
3 changes: 3 additions & 0 deletions api/envoy/api/v2/cds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "envoy/api/v2/discovery.proto";

import "google/api/annotations.proto";

import "envoy/annotations/resource.proto";
import "udpa/annotations/migrate.proto";

import public "envoy/api/v2/cluster.proto";
Expand All @@ -20,6 +21,8 @@ option (udpa.annotations.file_migrate).move_to_package = "envoy.service.cluster.

// Return list of all clusters this proxy will load balance to.
service ClusterDiscoveryService {
option (envoy.annotations.resource).type = "envoy.api.v2.Cluster";

rpc StreamClusters(stream DiscoveryRequest) returns (stream DiscoveryResponse) {
}

Expand Down
3 changes: 3 additions & 0 deletions api/envoy/api/v2/eds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "google/api/annotations.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "envoy/annotations/resource.proto";
import "udpa/annotations/migrate.proto";
import "validate/validate.proto";

Expand All @@ -23,6 +24,8 @@ option (udpa.annotations.file_migrate).move_to_package = "envoy.service.endpoint
// Endpoint discovery :ref:`architecture overview <arch_overview_service_discovery_types_eds>`

service EndpointDiscoveryService {
option (envoy.annotations.resource).type = "envoy.api.v2.ClusterLoadAssignment";

// The resource_names field in DiscoveryRequest specifies a list of clusters
// to subscribe to updates for.
rpc StreamEndpoints(stream DiscoveryRequest) returns (stream DiscoveryResponse) {
Expand Down
3 changes: 3 additions & 0 deletions api/envoy/api/v2/lds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "google/api/annotations.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";

import "envoy/annotations/resource.proto";
import "udpa/annotations/migrate.proto";
import "validate/validate.proto";

Expand All @@ -27,6 +28,8 @@ option (udpa.annotations.file_migrate).move_to_package = "envoy.service.listener
// consist of a complete update of all listeners. Existing connections will be
// allowed to drain from listeners that are no longer present.
service ListenerDiscoveryService {
option (envoy.annotations.resource).type = "envoy.api.v2.Listener";

rpc DeltaListeners(stream DeltaDiscoveryRequest) returns (stream DeltaDiscoveryResponse) {
}

Expand Down
5 changes: 5 additions & 0 deletions api/envoy/api/v2/rds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "envoy/api/v2/discovery.proto";
import "google/api/annotations.proto";
import "google/protobuf/wrappers.proto";

import "envoy/annotations/resource.proto";
import "udpa/annotations/migrate.proto";
import "validate/validate.proto";

Expand All @@ -26,6 +27,8 @@ option (udpa.annotations.file_migrate).move_to_package = "envoy.service.route.v3
// configurations. Each listener will bind its HTTP connection manager filter to
// a route table via this identifier.
service RouteDiscoveryService {
option (envoy.annotations.resource).type = "envoy.api.v2.RouteConfiguration";

rpc StreamRoutes(stream DiscoveryRequest) returns (stream DiscoveryResponse) {
}

Expand All @@ -49,6 +52,8 @@ service RouteDiscoveryService {
// contains a list of virtual host names that have been :ref:`unsubscribed
// <xds_protocol_unsubscribe>` from the routing table associated with the RouteConfiguration.
service VirtualHostDiscoveryService {
option (envoy.annotations.resource).type = "envoy.api.v2.route.VirtualHost";

rpc DeltaVirtualHosts(stream DeltaDiscoveryRequest) returns (stream DeltaDiscoveryResponse) {
}
}
Expand Down
3 changes: 3 additions & 0 deletions api/envoy/api/v2/srds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "envoy/api/v2/discovery.proto";

import "google/api/annotations.proto";

import "envoy/annotations/resource.proto";
import "udpa/annotations/migrate.proto";

import public "envoy/api/v2/scoped_route.proto";
Expand All @@ -27,6 +28,8 @@ option (udpa.annotations.file_migrate).move_to_package = "envoy.service.route.v3
// :ref:`RouteConfiguration<envoy_api_msg_RouteConfiguration>` message) to each
// HTTP request.
service ScopedRoutesDiscoveryService {
option (envoy.annotations.resource).type = "envoy.api.v2.ScopedRouteConfiguration";

rpc StreamScopedRoutes(stream DiscoveryRequest) returns (stream DiscoveryResponse) {
}

Expand Down
1 change: 1 addition & 0 deletions api/envoy/service/cluster/v3alpha/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/api/v2:pkg",
"//envoy/service/discovery/v3alpha:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
Expand Down
4 changes: 4 additions & 0 deletions api/envoy/service/cluster/v3alpha/cds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import "google/api/annotations.proto";

import "udpa/annotations/versioning.proto";

import "envoy/annotations/resource.proto";

option java_package = "io.envoyproxy.envoy.service.cluster.v3alpha";
option java_outer_classname = "CdsProto";
option java_multiple_files = true;
Expand All @@ -17,6 +19,8 @@ option java_generic_services = true;

// Return list of all clusters this proxy will load balance to.
service ClusterDiscoveryService {
option (envoy.annotations.resource).type = "envoy.config.cluster.v3alpha.Cluster";

rpc StreamClusters(stream discovery.v3alpha.DiscoveryRequest)
returns (stream discovery.v3alpha.DiscoveryResponse) {
}
Expand Down
1 change: 1 addition & 0 deletions api/envoy/service/discovery/v2/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/api/v2:pkg",
"//envoy/api/v2/core:pkg",
"//envoy/api/v2/endpoint:pkg",
Expand Down
3 changes: 3 additions & 0 deletions api/envoy/service/discovery/v2/rtds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "envoy/api/v2/discovery.proto";
import "google/api/annotations.proto";
import "google/protobuf/struct.proto";

import "envoy/annotations/resource.proto";
import "udpa/annotations/migrate.proto";
import "validate/validate.proto";

Expand All @@ -21,6 +22,8 @@ option (udpa.annotations.file_migrate).move_to_package = "envoy.service.runtime.

// Discovery service for Runtime resources.
service RuntimeDiscoveryService {
option (envoy.annotations.resource).type = "envoy.service.discovery.v2.Runtime";

rpc StreamRuntime(stream api.v2.DiscoveryRequest) returns (stream api.v2.DiscoveryResponse) {
}

Expand Down
3 changes: 3 additions & 0 deletions api/envoy/service/discovery/v2/sds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "envoy/api/v2/discovery.proto";

import "google/api/annotations.proto";

import "envoy/annotations/resource.proto";
import "udpa/annotations/migrate.proto";

option java_package = "io.envoyproxy.envoy.service.discovery.v2";
Expand All @@ -15,6 +16,8 @@ option java_generic_services = true;
option (udpa.annotations.file_migrate).move_to_package = "envoy.service.secret.v3alpha";

service SecretDiscoveryService {
option (envoy.annotations.resource).type = "envoy.api.v2.auth.Secret";

rpc DeltaSecrets(stream api.v2.DeltaDiscoveryRequest)
returns (stream api.v2.DeltaDiscoveryResponse) {
}
Expand Down
1 change: 1 addition & 0 deletions api/envoy/service/endpoint/v3alpha/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/api/v2:pkg",
"//envoy/service/discovery/v3alpha:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
Expand Down
3 changes: 3 additions & 0 deletions api/envoy/service/endpoint/v3alpha/eds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "google/protobuf/wrappers.proto";

import "udpa/annotations/versioning.proto";

import "envoy/annotations/resource.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.service.endpoint.v3alpha";
Expand All @@ -21,6 +22,8 @@ option java_generic_services = true;
// Endpoint discovery :ref:`architecture overview <arch_overview_service_discovery_types_eds>`

service EndpointDiscoveryService {
option (envoy.annotations.resource).type = "envoy.config.endpoint.v3alpha.ClusterLoadAssignment";

// The resource_names field in DiscoveryRequest specifies a list of clusters
// to subscribe to updates for.
rpc StreamEndpoints(stream discovery.v3alpha.DiscoveryRequest)
Expand Down
1 change: 1 addition & 0 deletions api/envoy/service/listener/v3alpha/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/api/v2:pkg",
"//envoy/service/discovery/v3alpha:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
Expand Down
3 changes: 3 additions & 0 deletions api/envoy/service/listener/v3alpha/lds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "google/protobuf/wrappers.proto";

import "udpa/annotations/versioning.proto";

import "envoy/annotations/resource.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.service.listener.v3alpha";
Expand All @@ -25,6 +26,8 @@ option java_generic_services = true;
// consist of a complete update of all listeners. Existing connections will be
// allowed to drain from listeners that are no longer present.
service ListenerDiscoveryService {
option (envoy.annotations.resource).type = "envoy.config.listener.v3alpha.Listener";

rpc DeltaListeners(stream discovery.v3alpha.DeltaDiscoveryRequest)
returns (stream discovery.v3alpha.DeltaDiscoveryResponse) {
}
Expand Down
1 change: 1 addition & 0 deletions api/envoy/service/route/v3alpha/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/api/v2:pkg",
"//envoy/service/discovery/v3alpha:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
Expand Down
5 changes: 5 additions & 0 deletions api/envoy/service/route/v3alpha/rds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "google/protobuf/wrappers.proto";

import "udpa/annotations/versioning.proto";

import "envoy/annotations/resource.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.service.route.v3alpha";
Expand All @@ -24,6 +25,8 @@ option java_generic_services = true;
// configurations. Each listener will bind its HTTP connection manager filter to
// a route table via this identifier.
service RouteDiscoveryService {
option (envoy.annotations.resource).type = "envoy.config.route.v3alpha.RouteConfiguration";

rpc StreamRoutes(stream discovery.v3alpha.DiscoveryRequest)
returns (stream discovery.v3alpha.DiscoveryResponse) {
}
Expand Down Expand Up @@ -52,6 +55,8 @@ service RouteDiscoveryService {
// :ref:`unsubscribed <xds_protocol_unsubscribe>` from the routing table associated with the
// RouteConfiguration.
service VirtualHostDiscoveryService {
option (envoy.annotations.resource).type = "envoy.config.route.v3alpha.VirtualHost";

rpc DeltaVirtualHosts(stream discovery.v3alpha.DeltaDiscoveryRequest)
returns (stream discovery.v3alpha.DeltaDiscoveryResponse) {
}
Expand Down
4 changes: 4 additions & 0 deletions api/envoy/service/route/v3alpha/srds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import "google/api/annotations.proto";

import "udpa/annotations/versioning.proto";

import "envoy/annotations/resource.proto";

option java_package = "io.envoyproxy.envoy.service.route.v3alpha";
option java_outer_classname = "SrdsProto";
option java_multiple_files = true;
Expand All @@ -24,6 +26,8 @@ option java_generic_services = true;
// :ref:`RouteConfiguration<envoy_api_msg_config.route.v3alpha.RouteConfiguration>` message) to each
// HTTP request.
service ScopedRoutesDiscoveryService {
option (envoy.annotations.resource).type = "envoy.config.route.v3alpha.ScopedRouteConfiguration";

rpc StreamScopedRoutes(stream discovery.v3alpha.DiscoveryRequest)
returns (stream discovery.v3alpha.DiscoveryResponse) {
}
Expand Down
1 change: 1 addition & 0 deletions api/envoy/service/runtime/v3alpha/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/service/discovery/v2:pkg",
"//envoy/service/discovery/v3alpha:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
Expand Down
3 changes: 3 additions & 0 deletions api/envoy/service/runtime/v3alpha/rtds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "google/protobuf/struct.proto";

import "udpa/annotations/versioning.proto";

import "envoy/annotations/resource.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.service.runtime.v3alpha";
Expand All @@ -21,6 +22,8 @@ option java_generic_services = true;

// Discovery service for Runtime resources.
service RuntimeDiscoveryService {
option (envoy.annotations.resource).type = "envoy.service.runtime.v3alpha.Runtime";

rpc StreamRuntime(stream discovery.v3alpha.DiscoveryRequest)
returns (stream discovery.v3alpha.DiscoveryResponse) {
}
Expand Down
1 change: 1 addition & 0 deletions api/envoy/service/secret/v3alpha/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2
api_proto_package(
has_services = True,
deps = [
"//envoy/annotations:pkg",
"//envoy/service/discovery/v2:pkg",
"//envoy/service/discovery/v3alpha:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
Expand Down
5 changes: 5 additions & 0 deletions api/envoy/service/secret/v3alpha/sds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ import "google/api/annotations.proto";

import "udpa/annotations/versioning.proto";

import "envoy/annotations/resource.proto";

option java_package = "io.envoyproxy.envoy.service.secret.v3alpha";
option java_outer_classname = "SdsProto";
option java_multiple_files = true;
option java_generic_services = true;

service SecretDiscoveryService {
option (envoy.annotations.resource).type =
"envoy.extensions.transport_sockets.tls.v3alpha.Secret";

rpc DeltaSecrets(stream discovery.v3alpha.DeltaDiscoveryRequest)
returns (stream discovery.v3alpha.DeltaDiscoveryResponse) {
}
Expand Down
19 changes: 0 additions & 19 deletions api/test/validate/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,6 @@ api_cc_test(
name = "pgv_test",
srcs = ["pgv_test.cc"],
deps = [
"//envoy/api/v2:pkg_cc_proto",
"//envoy/api/v2/core:pkg_cc_proto",
"//envoy/config/bootstrap/v2:pkg_cc_proto",
"//envoy/config/filter/accesslog/v2:pkg_cc_proto",
"//envoy/config/filter/http/buffer/v2:pkg_cc_proto",
"//envoy/config/filter/http/fault/v2:pkg_cc_proto",
"//envoy/config/filter/http/gzip/v2:pkg_cc_proto",
"//envoy/config/filter/http/header_to_metadata/v2:pkg_cc_proto",
"//envoy/config/filter/http/health_check/v2:pkg_cc_proto",
"//envoy/config/filter/http/ip_tagging/v2:pkg_cc_proto",
"//envoy/config/filter/http/lua/v2:pkg_cc_proto",
"//envoy/config/filter/http/router/v2:pkg_cc_proto",
"//envoy/config/filter/http/squash/v2:pkg_cc_proto",
"//envoy/config/filter/http/transcoder/v2:pkg_cc_proto",
"//envoy/config/filter/network/http_connection_manager/v2:pkg_cc_proto",
"//envoy/config/filter/network/mongo_proxy/v2:pkg_cc_proto",
"//envoy/config/filter/network/redis_proxy/v2:pkg_cc_proto",
"//envoy/config/filter/network/tcp_proxy/v2:pkg_cc_proto",
"//envoy/config/health_checker/redis/v2:pkg_cc_proto",
"@envoy_api//envoy/api/v2:pkg_cc_proto",
"@envoy_api//envoy/api/v2/core:pkg_cc_proto",
"@envoy_api//envoy/api/v2/listener:pkg_cc_proto",
Expand Down
5 changes: 5 additions & 0 deletions generated_api_shadow/envoy/annotations/BUILD

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions generated_api_shadow/envoy/annotations/resource.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cceab39

Please sign in to comment.