api: validation of API structure. (#9598)
This patch introduces a new checker, tools/api/validate_structure.py, that is run as part of the bazel.api CI job. It ensures that the package layout for the API doesn't violate some constraints, largely reflecting the heuristics we used for v3alpha migration. Along the way, I discovered there were some packages that were versionless and not boosted to v3alpha, and there were some extensions left behind in envoy.config. These are fixed as well to allow the validation to succeed. Risk level: Low Testing: tools/api/validate_structure.py passes, bazel test //test/... Fixes #9580 Signed-off-by: Harvey Tuch <htuch@google.com> Mirrored from https://github.com/envoyproxy/envoy @ 29b30911dbfb3f9760efeb28238ceac36e1a1a23master-ci-test
parent
0bbbff879a
commit
e1415ce794
31 changed files with 261 additions and 37 deletions
@ -0,0 +1,29 @@ |
||||
syntax = "proto3"; |
||||
|
||||
package envoy.config.listener.v3alpha; |
||||
|
||||
import "google/protobuf/any.proto"; |
||||
|
||||
import "udpa/annotations/versioning.proto"; |
||||
|
||||
option java_package = "io.envoyproxy.envoy.config.listener.v3alpha"; |
||||
option java_outer_classname = "ApiListenerProto"; |
||||
option java_multiple_files = true; |
||||
|
||||
// [#not-implemented-hide:] |
||||
// Describes a type of API listener, which is used in non-proxy clients. The type of API |
||||
// exposed to the non-proxy application depends on the type of API listener. |
||||
message ApiListener { |
||||
option (udpa.annotations.versioning).previous_message_type = |
||||
"envoy.config.listener.v2.ApiListener"; |
||||
|
||||
// The type in this field determines the type of API listener. At present, the following |
||||
// types are supported: |
||||
// envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager (HTTP) |
||||
// [#next-major-version: In the v3 API, replace this Any field with a oneof containing the |
||||
// specific config message for each type of API listener. We could not do this in v2 because |
||||
// it would have caused circular dependencies for go protos: lds.proto depends on this file, |
||||
// and http_connection_manager.proto depends on rds.proto, which is in the same directory as |
||||
// lds.proto, so lds.proto cannot depend on this file.] |
||||
google.protobuf.Any api_listener = 1; |
||||
} |
@ -0,0 +1,12 @@ |
||||
# DO NOT EDIT. This file is generated by tools/proto_sync.py. |
||||
|
||||
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") |
||||
|
||||
licenses(["notice"]) # Apache 2 |
||||
|
||||
api_proto_package( |
||||
deps = [ |
||||
"//envoy/config/accesslog/v2:pkg", |
||||
"@com_github_cncf_udpa//udpa/annotations:pkg", |
||||
], |
||||
) |
@ -0,0 +1,12 @@ |
||||
# DO NOT EDIT. This file is generated by tools/proto_sync.py. |
||||
|
||||
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") |
||||
|
||||
licenses(["notice"]) # Apache 2 |
||||
|
||||
api_proto_package( |
||||
deps = [ |
||||
"//envoy/config/cluster/redis:pkg", |
||||
"@com_github_cncf_udpa//udpa/annotations:pkg", |
||||
], |
||||
) |
@ -0,0 +1,84 @@ |
||||
syntax = "proto3"; |
||||
|
||||
package envoy.extensions.clusters.redis.v3alpha; |
||||
|
||||
import "google/protobuf/duration.proto"; |
||||
import "google/protobuf/wrappers.proto"; |
||||
|
||||
import "udpa/annotations/versioning.proto"; |
||||
|
||||
import "validate/validate.proto"; |
||||
|
||||
option java_package = "io.envoyproxy.envoy.extensions.clusters.redis.v3alpha"; |
||||
option java_outer_classname = "RedisClusterProto"; |
||||
option java_multiple_files = true; |
||||
|
||||
// [#protodoc-title: Redis Cluster Configuration] |
||||
// This cluster adds support for `Redis Cluster <https://redis.io/topics/cluster-spec>`_, as part |
||||
// of :ref:`Envoy's support for Redis Cluster <arch_overview_redis>`. |
||||
// |
||||
// Redis Cluster is an extension of Redis which supports sharding and high availability (where a |
||||
// shard that loses its master fails over to a replica, and designates it as the new master). |
||||
// However, as there is no unified frontend or proxy service in front of Redis Cluster, the client |
||||
// (in this case Envoy) must locally maintain the state of the Redis Cluster, specifically the |
||||
// topology. A random node in the cluster is queried for the topology using the `CLUSTER SLOTS |
||||
// command <https://redis.io/commands/cluster-slots>`_. This result is then stored locally, and |
||||
// updated at user-configured intervals. |
||||
// |
||||
// Additionally, if |
||||
// :ref:`enable_redirection<envoy_api_field_extensions.filters.network.redis_proxy.v3alpha.RedisProxy.ConnPoolSettings.enable_redirection>` |
||||
// is true, then moved and ask redirection errors from upstream servers will trigger a topology |
||||
// refresh when they exceed a user-configured error threshold. |
||||
// |
||||
// Example: |
||||
// |
||||
// .. code-block:: yaml |
||||
// |
||||
// name: name |
||||
// connect_timeout: 0.25s |
||||
// dns_lookup_family: V4_ONLY |
||||
// hosts: |
||||
// - socket_address: |
||||
// address: foo.bar.com |
||||
// port_value: 22120 |
||||
// cluster_type: |
||||
// name: envoy.clusters.redis |
||||
// typed_config: |
||||
// "@type": type.googleapis.com/google.protobuf.Struct |
||||
// value: |
||||
// cluster_refresh_rate: 30s |
||||
// cluster_refresh_timeout: 0.5s |
||||
// redirect_refresh_interval: 10s |
||||
// redirect_refresh_threshold: 10 |
||||
// [#extension: envoy.clusters.redis] |
||||
|
||||
// [#next-free-field: 7] |
||||
message RedisClusterConfig { |
||||
option (udpa.annotations.versioning).previous_message_type = |
||||
"envoy.config.cluster.redis.RedisClusterConfig"; |
||||
|
||||
// Interval between successive topology refresh requests. If not set, this defaults to 5s. |
||||
google.protobuf.Duration cluster_refresh_rate = 1 [(validate.rules).duration = {gt {}}]; |
||||
|
||||
// Timeout for topology refresh request. If not set, this defaults to 3s. |
||||
google.protobuf.Duration cluster_refresh_timeout = 2 [(validate.rules).duration = {gt {}}]; |
||||
|
||||
// The minimum interval that must pass after triggering a topology refresh request before a new |
||||
// request can possibly be triggered again. Any errors received during one of these |
||||
// time intervals are ignored. If not set, this defaults to 5s. |
||||
google.protobuf.Duration redirect_refresh_interval = 3; |
||||
|
||||
// The number of redirection errors that must be received before |
||||
// triggering a topology refresh request. If not set, this defaults to 5. |
||||
// If this is set to 0, topology refresh after redirect is disabled. |
||||
google.protobuf.UInt32Value redirect_refresh_threshold = 4; |
||||
|
||||
// The number of failures that must be received before triggering a topology refresh request. |
||||
// If not set, this defaults to 0, which disables the topology refresh due to failure. |
||||
uint32 failure_refresh_threshold = 5; |
||||
|
||||
// The number of hosts became degraded or unhealthy before triggering a topology refresh request. |
||||
// If not set, this defaults to 0, which disables the topology refresh due to degraded or |
||||
// unhealthy host. |
||||
uint32 host_degraded_refresh_threshold = 6; |
||||
} |
@ -0,0 +1,12 @@ |
||||
# DO NOT EDIT. This file is generated by tools/proto_sync.py. |
||||
|
||||
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") |
||||
|
||||
licenses(["notice"]) # Apache 2 |
||||
|
||||
api_proto_package( |
||||
deps = [ |
||||
"//envoy/config/retry/previous_priorities:pkg", |
||||
"@com_github_cncf_udpa//udpa/annotations:pkg", |
||||
], |
||||
) |
@ -0,0 +1,54 @@ |
||||
syntax = "proto3"; |
||||
|
||||
package envoy.extensions.retry.priority.previous_priorities.v3alpha; |
||||
|
||||
import "udpa/annotations/versioning.proto"; |
||||
|
||||
import "validate/validate.proto"; |
||||
|
||||
option java_package = "io.envoyproxy.envoy.extensions.retry.priority.previous_priorities.v3alpha"; |
||||
option java_outer_classname = "PreviousPrioritiesConfigProto"; |
||||
option java_multiple_files = true; |
||||
|
||||
// A retry host selector that attempts to spread retries between priorities, even if certain |
||||
// priorities would not normally be attempted due to higher priorities being available. |
||||
// |
||||
// As priorities get excluded, load will be distributed amongst the remaining healthy priorities |
||||
// based on the relative health of the priorities, matching how load is distributed during regular |
||||
// host selection. For example, given priority healths of {100, 50, 50}, the original load will be |
||||
// {100, 0, 0} (since P0 has capacity to handle 100% of the traffic). If P0 is excluded, the load |
||||
// changes to {0, 50, 50}, because P1 is only able to handle 50% of the traffic, causing the |
||||
// remaining to spill over to P2. |
||||
// |
||||
// Each priority attempted will be excluded until there are no healthy priorities left, at which |
||||
// point the list of attempted priorities will be reset, essentially starting from the beginning. |
||||
// For example, given three priorities P0, P1, P2 with healthy % of 100, 0 and 50 respectively, the |
||||
// following sequence of priorities would be selected (assuming update_frequency = 1): |
||||
// Attempt 1: P0 (P0 is 100% healthy) |
||||
// Attempt 2: P2 (P0 already attempted, P2 only healthy priority) |
||||
// Attempt 3: P0 (no healthy priorities, reset) |
||||
// Attempt 4: P2 |
||||
// |
||||
// In the case of all upstream hosts being unhealthy, no adjustments will be made to the original |
||||
// priority load, so behavior should be identical to not using this plugin. |
||||
// |
||||
// Using this PriorityFilter requires rebuilding the priority load, which runs in O(# of |
||||
// priorities), which might incur significant overhead for clusters with many priorities. |
||||
// [#extension: envoy.retry_priorities.previous_priorities] |
||||
message PreviousPrioritiesConfig { |
||||
option (udpa.annotations.versioning).previous_message_type = |
||||
"envoy.config.retry.previous_priorities.PreviousPrioritiesConfig"; |
||||
|
||||
// How often the priority load should be updated based on previously attempted priorities. Useful |
||||
// to allow each priorities to receive more than one request before being excluded or to reduce |
||||
// the number of times that the priority load has to be recomputed. |
||||
// |
||||
// For example, by setting this to 2, then the first two attempts (initial attempt and first |
||||
// retry) will use the unmodified priority load. The third and fourth attempt will use priority |
||||
// load which excludes the priorities routed to with the first two attempts, and the fifth and |
||||
// sixth attempt will use the priority load excluding the priorities used for the first four |
||||
// attempts. |
||||
// |
||||
// Must be greater than 0. |
||||
int32 update_frequency = 1 [(validate.rules).int32 = {gt: 0}]; |
||||
} |
Loading…
Reference in new issue