diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..f0957c311 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +packages/grpc-js-xds/src/generated/** linguist-generated +packages/grpc-js-xds/interop/generated/** linguist-generated diff --git a/.gitmodules b/.gitmodules index d3c1ebaf6..f54fa6afc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,12 +10,12 @@ [submodule "packages/grpc-js-xds/deps/envoy-api"] path = packages/grpc-js-xds/deps/envoy-api url = https://github.com/envoyproxy/data-plane-api.git -[submodule "packages/grpc-js-xds/deps/udpa"] - path = packages/grpc-js-xds/deps/udpa - url = https://github.com/cncf/udpa.git [submodule "packages/grpc-js-xds/deps/googleapis"] path = packages/grpc-js-xds/deps/googleapis url = https://github.com/googleapis/googleapis.git [submodule "packages/grpc-js-xds/deps/protoc-gen-validate"] path = packages/grpc-js-xds/deps/protoc-gen-validate url = https://github.com/envoyproxy/protoc-gen-validate.git +[submodule "packages/grpc-js-xds/deps/xds"] + path = packages/grpc-js-xds/deps/xds + url = https://github.com/cncf/xds.git diff --git a/MAINTAINERS.md b/MAINTAINERS.md index c9e0522a1..bdcef2e26 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -8,16 +8,17 @@ See [CONTRIBUTING.md](https://github.com/grpc/grpc-community/blob/master/CONTRIB for general contribution guidelines. ## Maintainers (in alphabetical order) - - [jiangtaoli2016](https://github.com/jiangtaoli2016), Google Inc. + - [jtattermusch](https://github.com/jtattermusch), Google Inc. - [murgatroid99](https://github.com/murgatroid99), Google Inc. - [nicolasnoble](https://github.com/nicolasnoble), Google Inc. - - [ofrobots](https://github.com/ofrobots), Google Inc. - [srini100](https://github.com/srini100), Google Inc. - - [WeiranFang](https://github.com/WeiranFang), Google Inc. - [wenbozhu](https://github.com/wenbozhu), Google Inc. ## Emeritus Maintainers (in alphabetical order) + - [jiangtaoli2016](https://github.com/jiangtaoli2016), Google Inc. - [kjin](https://github.com/kjin), Google Inc. - [matt-kwong](https://github.com/matt-kwong), Google Inc. - \ No newline at end of file + - [ofrobots](https://github.com/ofrobots), Google Inc. + - [WeiranFang](https://github.com/WeiranFang), Google Inc. + diff --git a/PACKAGE-COMPARISON.md b/PACKAGE-COMPARISON.md index fa0ea319e..e6cee8934 100644 --- a/PACKAGE-COMPARISON.md +++ b/PACKAGE-COMPARISON.md @@ -1,6 +1,6 @@ # Feature comparison of `grpc` and `@grpc/grpc-js` packages -Feature | `grpc` | `@grpc/grpc-js` +Feature | `grpc` (deprecated) | `@grpc/grpc-js` --------|--------|---------- Client | :heavy_check_mark: | :heavy_check_mark: Server | :heavy_check_mark: | :heavy_check_mark: @@ -9,41 +9,24 @@ Streaming RPCs | :heavy_check_mark: | :heavy_check_mark: Deadlines | :heavy_check_mark: | :heavy_check_mark: Cancellation | :heavy_check_mark: | :heavy_check_mark: Automatic Reconnection | :heavy_check_mark: | :heavy_check_mark: -Per-message Compression | :heavy_check_mark: | only for response messages +Per-message Compression | :heavy_check_mark: | :heavy_check_mark: (except messages sent by the server) Channel State | :heavy_check_mark: | :heavy_check_mark: JWT Access and Service Account Credentials | provided by the [Google Auth Library](https://www.npmjs.com/package/google-auth-library) | provided by the [Google Auth Library](https://www.npmjs.com/package/google-auth-library) Interceptors | :heavy_check_mark: | :heavy_check_mark: Connection Keepalives | :heavy_check_mark: | :heavy_check_mark: HTTP Connect Support | :heavy_check_mark: | :heavy_check_mark: -Retries | :heavy_check_mark: | :x: +Retries | :heavy_check_mark: (without hedging) | :heavy_check_mark: (including hedging) Stats/tracing/monitoring | :heavy_check_mark: | :x: -Load Balancing | :heavy_check_mark: | Pick first and round robin +Load Balancing | :heavy_check_mark: | :heavy_check_mark: Initial Metadata Options | :heavy_check_mark: | only `waitForReady` Other Properties | `grpc` | `@grpc/grpc-js` -----------------|--------|---------------- Pure JavaScript Code | :x: | :heavy_check_mark: -Supported Node Versions | >= 4 | ^8.13.0 or >=10.10.0 -Supported Electron Versions | All | >= 3 +Supported Node Versions | >= 4 and <=14 | ^8.13.0 or >=10.10.0 +Supported Electron Versions | <=11.2 | >= 3 Supported Platforms | Linux, Windows, MacOS | All Supported Architectures | x86, x86-64, ARM7+ | All -In addition, all channel arguments defined in [this header file](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/grpc_types.h) are handled by the `grpc` library. Of those, the following are handled by the `@grpc/grpc-js` library: - - - `grpc.ssl_target_name_override` - - `grpc.primary_user_agent` - - `grpc.secondary_user_agent` - - `grpc.default_authority` - - `grpc.keepalive_time_ms` - - `grpc.keepalive_timeout_ms` - - `grpc.keepalive_permit_without_calls` - - `grpc.service_config` - - `grpc.max_concurrent_streams` - - `grpc.initial_reconnect_backoff_ms` - - `grpc.max_reconnect_backoff_ms` - - `grpc.use_local_subchannel_pool` - - `grpc.max_send_message_length` - - `grpc.max_receive_message_length` - - `grpc.enable_http_proxy` - - `channelOverride` - - `channelFactoryOverride` +In addition, all channel arguments defined in [this header file](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/grpc_types.h) are handled by the `grpc` library. +Of those, a subset are handled by the `@grpc/grpc-js` library. See [the README](https://github.com/grpc/grpc-node/blob/master/packages/grpc-js/README.md#supported-channel-options) for `@grpc/grpc-js` for the list of supported channel options. diff --git a/README.md b/README.md index 159fbab4f..f0f215ce3 100644 --- a/README.md +++ b/README.md @@ -5,21 +5,21 @@ For a comparison of the features available in these two libraries, see [this document](https://github.com/grpc/grpc-node/tree/master/PACKAGE-COMPARISON.md) -### C-based Client and Server +### Pure JavaScript Client and Server -Directory: [`packages/grpc-native-core`](https://github.com/grpc/grpc-node/tree/grpc@1.24.x/packages/grpc-native-core) (lives in the `grpc@1.24.x` branch) (see here for installation information) +Directory: [`packages/grpc-js`](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) -npm package: [grpc](https://www.npmjs.com/package/grpc). +npm package: [@grpc/grpc-js](https://www.npmjs.com/package/@grpc/grpc-js) -This is the existing, feature-rich implementation of gRPC using a C++ addon. It works on all LTS versions of Node.js on most platforms that Node.js runs on. +This library implements the core functionality of gRPC purely in JavaScript, without a C++ addon. It works on the latest versions of Node.js on all platforms that Node.js runs on. -### Pure JavaScript Client +### C-based Client and Server (deprecated) -Directory: [`packages/grpc-js`](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) +Directory: [`packages/grpc-native-core`](https://github.com/grpc/grpc-node/tree/grpc@1.24.x/packages/grpc-native-core) (lives in the `grpc@1.24.x` branch) (see here for installation information) -npm package: [@grpc/grpc-js](https://www.npmjs.com/package/@grpc/grpc-js) +npm package: [grpc](https://www.npmjs.com/package/grpc). -This library implements the core functionality of gRPC purely in JavaScript, without a C++ addon. It works on the latest version of Node.js on all platforms that Node.js runs on. +This is the deprecated implementation of gRPC using a C++ addon. It works on versions of Node.js up to 14 on most platforms that Node.js runs on. ## Other Packages diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md new file mode 100644 index 000000000..bfcf94edc --- /dev/null +++ b/TROUBLESHOOTING.md @@ -0,0 +1,38 @@ +# Troubleshooting grpc-js + +This guide is for troubleshooting the `grpc-js` library for Node.js + +## Enabling extra logging and tracing + +Extra logging can be very useful for diagnosing problems. `grpc-js` supports +the `GRPC_VERBOSITY` and `GRPC_TRACE` environment variables that can be used to increase the amount of information +that gets printed to stderr. + +## GRPC_VERBOSITY + +`GRPC_VERBOSITY` is used to set the minimum level of log messages printed by gRPC (supported values are `DEBUG`, `INFO` and `ERROR`). If this environment variable is unset, only `ERROR` logs will be printed. + +## GRPC_TRACE + +`GRPC_TRACE` can be used to enable extra logging for some internal gRPC components. Enabling the right traces can be invaluable +for diagnosing for what is going wrong when things aren't working as intended. Possible values for `GRPC_TRACE` are listed in [Environment Variables Overview](doc/environment_variables.md). +Multiple traces can be enabled at once (use comma as separator). + +``` +# Enable debug logs for an application +GRPC_VERBOSITY=debug ./helloworld_application_using_grpc +``` + +``` +# Print information about channel state changes +GRPC_VERBOSITY=debug GRPC_TRACE=connectivity_state ./helloworld_application_using_grpc +``` + +``` +# Print info from 3 different tracers, including tracing logs with log level DEBUG +GRPC_VERBOSITY=debug GRPC_TRACE=channel,subchannel,call_stream ./helloworld_application_using_grpc +``` + +Please note that the `GRPC_TRACE` environment variable has nothing to do with gRPC's "tracing" feature (= tracing RPCs in +microservice environment to gain insight about how requests are processed by deployment), it is merely used to enable printing +of extra logs. diff --git a/doc/environment_variables.md b/doc/environment_variables.md new file mode 100644 index 000000000..70b32e715 --- /dev/null +++ b/doc/environment_variables.md @@ -0,0 +1,65 @@ +# grpc-js environment variables + +`@grpc/grpc-js` exposes some configuration as environment variables that +can be set. + +*For the legacy `grpc` library, the environment variables are documented +[in the main gRPC repository](https://github.com/grpc/grpc/blob/master/doc/environment_variables.md)* + +* grpc_proxy, https_proxy, http_proxy + The URI of the proxy to use for HTTP CONNECT support. These variables are + checked in order, and the first one that has a value is used. + +* no_grpc_proxy, no_proxy + A comma separated list of hostnames to connect to without using a proxy even + if a proxy is set. These variables are checked in order, and the first one + that has a value is used. + +* GRPC_SSL_CIPHER_SUITES + A colon separated list of cipher suites to use with OpenSSL + Defaults to the defaults for Node.js + +* GRPC_DEFAULT_SSL_ROOTS_FILE_PATH + PEM file to load SSL roots from + +* GRPC_NODE_TRACE, GRPC_TRACE + A comma separated list of tracers that provide additional insight into how + grpc-js is processing requests via debug logs. Available tracers include: + - `call_stream` - Traces client request internals + - `channel` - Traces channel events + - `connectivity_state` - Traces channel connectivity state changes + - `dns_resolver` - Traces DNS resolution + - `ip_resolver` - Traces IPv4/v6 resolution + - `pick_first` - Traces the pick first load balancing policy + - `proxy` - Traces proxy operations + - `resolving_load_balancer` - Traces the resolving load balancer + - `round_robin` - Traces the round robin load balancing policy + - `server` - Traces high-level server events + - `server_call` - Traces server handling of individual requests + - `subchannel` - Traces subchannel connectivity state and errors + - `subchannel_refcount` - Traces subchannel refcount changes. Includes per-call logs. + - `subchannel_flowctrl` - Traces HTTP/2 flow control. Includes per-call logs. + - `subchannel_internals` - Traces HTTP/2 session state. Includes per-call logs. + - `channel_stacktrace` - Traces channel construction events with stack traces. + - `keepalive` - Traces gRPC keepalive pings + - `index` - Traces module loading + - `outlier_detection` - Traces outlier detection events + + The following tracers are added by the `@grpc/grpc-js-xds` library: + - `cds_balancer` - Traces the CDS load balancing policy + - `eds_balancer` - Traces the EDS load balancing policy + - `priority` - Traces the priority load balancing policy + - `weighted_target` - Traces the weighted target load balancing policy + - `xds_client` - Traces the xDS Client + - `xds_cluster_manager` - Traces the xDS cluster manager load balancing policy + - `xds_resolver` - Traces the xDS name resolver + + 'all' can additionally be used to turn all traces on. + Individual traces can be disabled by prefixing them with '-'. + +* GRPC_NODE_VERBOSITY, GRPC_VERBOSITY + Default gRPC logging verbosity - one of: + - DEBUG - log all gRPC messages + - INFO - log INFO and ERROR message + - ERROR - log only errors (default) + - NONE - won't log any \ No newline at end of file diff --git a/packages/grpc-js-xds/README.md b/packages/grpc-js-xds/README.md index bcea70456..793e0c0d7 100644 --- a/packages/grpc-js-xds/README.md +++ b/packages/grpc-js-xds/README.md @@ -22,4 +22,11 @@ const client = new MyServiceClient('xds:///example.com:123'); ## Supported Features - [xDS-Based Global Load Balancing](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) - - [xDS traffic splitting and routing](https://github.com/grpc/proposal/blob/master/A28-xds-traffic-splitting-and-routing.md) \ No newline at end of file + - [xDS traffic splitting and routing](https://github.com/grpc/proposal/blob/master/A28-xds-traffic-splitting-and-routing.md) + - [xDS v3 API](https://github.com/grpc/proposal/blob/master/A30-xds-v3.md) + - [xDS Timeouts](https://github.com/grpc/proposal/blob/master/A31-xds-timeout-support-and-config-selector.md) + - [xDS Circuit Breaking](https://github.com/grpc/proposal/blob/master/A32-xds-circuit-breaking.md) + - [xDS Client-Side Fault Injection](https://github.com/grpc/proposal/blob/master/A33-Fault-Injection.md) + - [Client Status Discovery Service](https://github.com/grpc/proposal/blob/master/A40-csds-support.md) + - [Outlier Detection](https://github.com/grpc/proposal/blob/master/A50-xds-outlier-detection.md) + - [xDS Retry Support](https://github.com/grpc/proposal/blob/master/A44-xds-retry.md) \ No newline at end of file diff --git a/packages/grpc-js-xds/deps/envoy-api b/packages/grpc-js-xds/deps/envoy-api index 50cef8fca..20b1b5fce 160000 --- a/packages/grpc-js-xds/deps/envoy-api +++ b/packages/grpc-js-xds/deps/envoy-api @@ -1 +1 @@ -Subproject commit 50cef8fcab37ba59a61068934d08a3f4c28a681f +Subproject commit 20b1b5fcee88a20a08b71051a961181839ec7268 diff --git a/packages/grpc-js-xds/deps/udpa b/packages/grpc-js-xds/deps/udpa deleted file mode 160000 index 3b31d022a..000000000 --- a/packages/grpc-js-xds/deps/udpa +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3b31d022a144b334eb2224838e4d6952ab5253aa diff --git a/packages/grpc-js-xds/deps/xds b/packages/grpc-js-xds/deps/xds new file mode 160000 index 000000000..cb28da345 --- /dev/null +++ b/packages/grpc-js-xds/deps/xds @@ -0,0 +1 @@ +Subproject commit cb28da3451f158a947dfc45090fe92b07b243bc1 diff --git a/packages/grpc-js-xds/interop/Dockerfile b/packages/grpc-js-xds/interop/Dockerfile new file mode 100644 index 000000000..5ff12a433 --- /dev/null +++ b/packages/grpc-js-xds/interop/Dockerfile @@ -0,0 +1,38 @@ +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Dockerfile for building the xDS interop client. To build the image, run the +# following command from grpc-node directory: +# docker build -t -f packages/grpc-js-xds/interop/Dockerfile . + +FROM node:18-slim as build + +# Make a grpc-node directory and copy the repo into it. +WORKDIR /node/src/grpc-node +COPY . . + +WORKDIR /node/src/grpc-node/packages/grpc-js +RUN npm install +WORKDIR /node/src/grpc-node/packages/grpc-js-xds +RUN npm install + +FROM gcr.io/distroless/nodejs18-debian11:latest +WORKDIR /node/src/grpc-node +COPY --from=build /node/src/grpc-node/packages/grpc-js ./packages/grpc-js/ +COPY --from=build /node/src/grpc-node/packages/grpc-js-xds ./packages/grpc-js-xds/ + +ENV GRPC_VERBOSITY="DEBUG" +ENV GRPC_TRACE=xds_client,xds_resolver,cds_balancer,eds_balancer,priority,weighted_target,round_robin,resolving_load_balancer,subchannel,keepalive,dns_resolver,fault_injection,http_filter,csds,outlier_detection + +ENTRYPOINT [ "/nodejs/bin/node", "/node/src/grpc-node/packages/grpc-js-xds/build/interop/xds-interop-client" ] diff --git a/packages/grpc-js-xds/interop/xds-interop-client.ts b/packages/grpc-js-xds/interop/xds-interop-client.ts index 5f32831c1..0394c0ace 100644 --- a/packages/grpc-js-xds/interop/xds-interop-client.ts +++ b/packages/grpc-js-xds/interop/xds-interop-client.ts @@ -130,6 +130,13 @@ class CallStatsTracker { private subscribers: CallSubscriber[] = []; + private removeSubscriber(subscriber: CallSubscriber) { + const index = this.subscribers.indexOf(subscriber); + if (index >= 0) { + this.subscribers.splice(index, 1); + } + } + getCallStats(callCount: number, timeoutSec: number): Promise { return new Promise((resolve, reject) => { let finished = false; @@ -142,7 +149,7 @@ class CallStatsTracker { setTimeout(() => { if (!finished) { finished = true; - this.subscribers.splice(this.subscribers.indexOf(subscriber), 1); + this.removeSubscriber(subscriber); resolve(subscriber.getFinalStats()); } }, timeoutSec * 1000) @@ -155,7 +162,7 @@ class CallStatsTracker { for (const subscriber of callSubscribers) { subscriber.addCallStarted(); if (!subscriber.needsMoreCalls()) { - this.subscribers.splice(this.subscribers.indexOf(subscriber), 1); + this.removeSubscriber(subscriber); } } return { @@ -173,6 +180,27 @@ class CallStatsTracker { } } +class RecentTimestampList { + private timeList: bigint[] = []; + private nextIndex = 0; + + constructor(private readonly size: number) {} + + isFull() { + return this.timeList.length === this.size; + } + + insertTimestamp(timestamp: bigint) { + this.timeList[this.nextIndex] = timestamp; + this.nextIndex = (this.nextIndex + 1) % this.size; + } + + getSpan(): bigint { + const lastIndex = (this.nextIndex + this.size - 1) % this.size; + return this.timeList[lastIndex] - this.timeList[this.nextIndex]; + } +} + type CallType = 'EmptyCall' | 'UnaryCall'; interface ClientConfiguration { @@ -196,31 +224,79 @@ const currentConfig: ClientConfiguration = { let anyCallSucceeded = false; const accumulatedStats: LoadBalancerAccumulatedStatsResponse = { + num_rpcs_started_by_method: { + EMPTY_CALL: 0, + UNARY_CALL: 0 + }, + num_rpcs_succeeded_by_method: { + EMPTY_CALL: 0, + UNARY_CALL: 0 + }, + num_rpcs_failed_by_method: { + EMPTY_CALL: 0, + UNARY_CALL: 0 + }, stats_per_method: { - EmptyCall: { + EMPTY_CALL: { rpcs_started: 0, result: {} }, - UnaryCall: { + UNARY_CALL: { rpcs_started: 0, result: {} } } }; -function makeSingleRequest(client: TestServiceClient, type: CallType, failOnFailedRpcs: boolean, callStatsTracker: CallStatsTracker) { - const callTypeStats = accumulatedStats.stats_per_method![type]; - callTypeStats.rpcs_started! += 1; +function addAccumulatedCallStarted(callName: string) { + accumulatedStats.stats_per_method![callName].rpcs_started! += 1; + accumulatedStats.num_rpcs_started_by_method![callName] += 1; +} + +function addAccumulatedCallEnded(callName: string, result: grpc.status) { + accumulatedStats.stats_per_method![callName].result![result] = (accumulatedStats.stats_per_method![callName].result![result] ?? 0) + 1; + if (result === grpc.status.OK) { + accumulatedStats.num_rpcs_succeeded_by_method![callName] += 1; + } else { + accumulatedStats.num_rpcs_failed_by_method![callName] += 1; + } +} + +const callTimeHistogram: {[callType: string]: {[status: number]: number[]}} = { + UnaryCall: {}, + EmptyCall: {} +} + +/** + * Timestamps output by process.hrtime.bigint() are a bigint number of + * nanoseconds. This is the representation of 1 second in that context. + */ +const TIMESTAMP_ONE_SECOND = BigInt(1e9); + +function makeSingleRequest(client: TestServiceClient, type: CallType, failOnFailedRpcs: boolean, callStatsTracker: CallStatsTracker, callStartTimestamps: RecentTimestampList) { + const callEnumName = callTypeEnumMapReverse[type]; + addAccumulatedCallStarted(callEnumName); const notifier = callStatsTracker.startCall(); let gotMetadata: boolean = false; let hostname: string | null = null; let completed: boolean = false; let completedWithError: boolean = false; + const startTime = process.hrtime.bigint(); const deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + currentConfig.timeoutSec); const callback = (error: grpc.ServiceError | undefined, value: Empty__Output | undefined) => { const statusCode = error?.code ?? grpc.status.OK; - callTypeStats.result![statusCode] = (callTypeStats.result![statusCode] ?? 0) + 1; + const duration = process.hrtime.bigint() - startTime; + const durationSeconds = Number(duration / TIMESTAMP_ONE_SECOND) | 0; + if (!callTimeHistogram[type][statusCode]) { + callTimeHistogram[type][statusCode] = []; + } + if (callTimeHistogram[type][statusCode][durationSeconds]) { + callTimeHistogram[type][statusCode][durationSeconds] += 1; + } else { + callTimeHistogram[type][statusCode][durationSeconds] = 1; + } + addAccumulatedCallEnded(callEnumName, statusCode); if (error) { if (failOnFailedRpcs && anyCallSucceeded) { console.error('A call failed after a call succeeded'); @@ -253,15 +329,33 @@ function makeSingleRequest(client: TestServiceClient, type: CallType, failOnFail } } }); - + /* callStartTimestamps tracks the last N timestamps of started calls, where N + * is the target QPS. If the measured span of time between the first and last + * of those N calls is greater than 1 second, we make another call + * ~immediately to correct for that. */ + callStartTimestamps.insertTimestamp(startTime); + if (callStartTimestamps.isFull()) { + if (callStartTimestamps.getSpan() > TIMESTAMP_ONE_SECOND) { + setImmediate(() => { + makeSingleRequest(client, type, failOnFailedRpcs, callStatsTracker, callStartTimestamps); + }); + } + } } function sendConstantQps(client: TestServiceClient, qps: number, failOnFailedRpcs: boolean, callStatsTracker: CallStatsTracker) { + const callStartTimestampsTrackers: {[callType: string]: RecentTimestampList} = {}; + for (const callType of ['EmptyCall', 'UnaryCall']) { + callStartTimestampsTrackers[callType] = new RecentTimestampList(qps); + } setInterval(() => { for (const callType of currentConfig.callTypes) { - makeSingleRequest(client, callType, failOnFailedRpcs, callStatsTracker); + makeSingleRequest(client, callType, failOnFailedRpcs, callStatsTracker, callStartTimestampsTrackers[callType]); } }, 1000/qps); + setInterval(() => { + console.log(`Accumulated stats: ${JSON.stringify(accumulatedStats, undefined, 2)}`); + }, 1000); } const callTypeEnumMap = { @@ -269,18 +363,27 @@ const callTypeEnumMap = { 'UNARY_CALL': 'UnaryCall' as CallType }; +const callTypeEnumMapReverse = { + 'EmptyCall': 'EMPTY_CALL', + 'UnaryCall': 'UNARY_CALL' +} + +const DEFAULT_TIMEOUT_SEC = 20; + function main() { const argv = yargs .string(['fail_on_failed_rpcs', 'server', 'stats_port', 'rpc', 'metadata']) - .number(['num_channels', 'qps']) + .number(['num_channels', 'qps', 'rpc_timeout_sec']) .demandOption(['server', 'stats_port']) .default('num_channels', 1) .default('qps', 1) .default('rpc', 'UnaryCall') .default('metadata', '') + .default('rpc_timeout_sec', DEFAULT_TIMEOUT_SEC) .argv; console.log('Starting xDS interop client. Args: ', argv); currentConfig.callTypes = argv.rpc.split(',').filter(value => value === 'EmptyCall' || value === 'UnaryCall') as CallType[]; + currentConfig.timeoutSec = argv.rpc_timeout_sec; for (const item of argv.metadata.split(',')) { const [method, key, value] = item.split(':'); if (value === undefined) { @@ -316,23 +419,30 @@ function main() { }); }, GetClientAccumulatedStats: (call, callback) => { + console.log(`Sending accumulated stats response: ${JSON.stringify(accumulatedStats)}`); + console.log(`Call durations: ${JSON.stringify(callTimeHistogram, undefined, 2)}`); callback(null, accumulatedStats); } } const xdsUpdateClientConfigureServiceImpl: XdsUpdateClientConfigureServiceHandlers = { Configure: (call, callback) => { + console.log('Received new client configuration: ' + JSON.stringify(call.request, undefined, 2)); const callMetadata = { EmptyCall: new grpc.Metadata(), UnaryCall: new grpc.Metadata() - } + }; for (const metadataItem of call.request.metadata) { callMetadata[callTypeEnumMap[metadataItem.type]].add(metadataItem.key, metadataItem.value); } currentConfig.callTypes = call.request.types.map(value => callTypeEnumMap[value]); currentConfig.metadata = callMetadata; - currentConfig.timeoutSec = call.request.timeout_sec - console.log('Received new client configuration: ' + JSON.stringify(currentConfig, undefined, 2)); + if (call.request.timeout_sec > 0) { + currentConfig.timeoutSec = call.request.timeout_sec; + } else { + currentConfig.timeoutSec = DEFAULT_TIMEOUT_SEC; + } + console.log('Updated to new client configuration: ' + JSON.stringify(currentConfig, undefined, 2)); callback(null, {}); } } @@ -340,6 +450,7 @@ function main() { const server = new grpc.Server(); server.addService(loadedProto.grpc.testing.LoadBalancerStatsService.service, loadBalancerStatsServiceImpl); server.addService(loadedProto.grpc.testing.XdsUpdateClientConfigureService.service, xdsUpdateClientConfigureServiceImpl); + grpc.addAdminServicesToServer(server); server.bindAsync(`0.0.0.0:${argv.stats_port}`, grpc.ServerCredentials.createInsecure(), (error, port) => { if (error) { throw error; diff --git a/packages/grpc-js-xds/package.json b/packages/grpc-js-xds/package.json index dfd778bd3..7c735b652 100644 --- a/packages/grpc-js-xds/package.json +++ b/packages/grpc-js-xds/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/grpc-js-xds", - "version": "1.3.1", + "version": "1.8.2", "description": "Plugin for @grpc/grpc-js. Adds the xds:// URL scheme and associated features.", "main": "build/src/index.js", "scripts": { @@ -12,8 +12,9 @@ "prepare": "npm run compile", "pretest": "npm run compile", "posttest": "npm run check", - "generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs deps/envoy-api/ deps/udpa/ deps/googleapis/ deps/protoc-gen-validate/ -O src/generated/ --grpcLib @grpc/grpc-js envoy/service/discovery/v2/ads.proto envoy/service/load_stats/v2/lrs.proto envoy/api/v2/listener.proto envoy/api/v2/route.proto envoy/api/v2/cluster.proto envoy/api/v2/endpoint.proto envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto", - "generate-interop-types": "proto-loader-gen-types --keep-case --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs proto/ -O interop/generated --grpcLib @grpc/grpc-js grpc/testing/test.proto" + "generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --includeDirs deps/envoy-api/ deps/xds/ deps/googleapis/ deps/protoc-gen-validate/ -O src/generated/ --grpcLib @grpc/grpc-js envoy/service/discovery/v3/ads.proto envoy/service/load_stats/v3/lrs.proto envoy/config/listener/v3/listener.proto envoy/config/route/v3/route.proto envoy/config/cluster/v3/cluster.proto envoy/config/endpoint/v3/endpoint.proto envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto udpa/type/v1/typed_struct.proto xds/type/v3/typed_struct.proto envoy/extensions/filters/http/fault/v3/fault.proto envoy/service/status/v3/csds.proto", + "generate-interop-types": "proto-loader-gen-types --keep-case --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs proto/ -O interop/generated --grpcLib @grpc/grpc-js grpc/testing/test.proto", + "generate-test-types": "proto-loader-gen-types --keep-case --longs String --enums String --defaults --oneofs --json --includeComments --includeDirs proto/ -O test/generated --grpcLib @grpc/grpc-js grpc/testing/echo.proto" }, "repository": { "type": "git", @@ -47,7 +48,7 @@ "re2-wasm": "^1.0.1" }, "peerDependencies": { - "@grpc/grpc-js": "~1.3.0" + "@grpc/grpc-js": "~1.8.0" }, "engines": { "node": ">=10.10.0" @@ -55,15 +56,20 @@ "files": [ "src/**/*.ts", "build/src/**/*.{js,d.ts,js.map}", - "deps/envoy-api/envoy/api/v2/**/*.proto", + "deps/envoy-api/envoy/admin/v3/**/*.proto", "deps/envoy-api/envoy/config/**/*.proto", "deps/envoy-api/envoy/service/**/*.proto", "deps/envoy-api/envoy/type/**/*.proto", "deps/envoy-api/envoy/annotations/**/*.proto", + "deps/envoy-api/envoy/extensions/**/*.proto", "deps/googleapis/google/api/**/*.proto", "deps/googleapis/google/protobuf/**/*.proto", "deps/googleapis/google/rpc/**/*.proto", - "deps/udpa/udpa/annotations/**/*.proto", + "deps/xds/udpa/annotations/**/*.proto", + "deps/xds/udpa/type/**/*.proto", + "deps/xds/xds/annotations/**/*.proto", + "deps/xds/xds/core/**/*.proto", + "deps/xds/xds/type/**/*.proto", "deps/protoc-gen-validate/validate/**/*.proto" ] } diff --git a/packages/grpc-js-xds/proto/grpc/testing/echo.proto b/packages/grpc-js-xds/proto/grpc/testing/echo.proto new file mode 100644 index 000000000..7f444b43f --- /dev/null +++ b/packages/grpc-js-xds/proto/grpc/testing/echo.proto @@ -0,0 +1,70 @@ + +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package grpc.testing; + +import "grpc/testing/echo_messages.proto"; +import "grpc/testing/simple_messages.proto"; + +service EchoTestService { + rpc Echo(EchoRequest) returns (EchoResponse); + rpc Echo1(EchoRequest) returns (EchoResponse); + rpc Echo2(EchoRequest) returns (EchoResponse); + rpc CheckDeadlineUpperBound(SimpleRequest) returns (StringValue); + rpc CheckDeadlineSet(SimpleRequest) returns (StringValue); + // A service which checks that the initial metadata sent over contains some + // expected key value pair + rpc CheckClientInitialMetadata(SimpleRequest) returns (SimpleResponse); + rpc RequestStream(stream EchoRequest) returns (EchoResponse); + rpc ResponseStream(EchoRequest) returns (stream EchoResponse); + rpc BidiStream(stream EchoRequest) returns (stream EchoResponse); + rpc Unimplemented(EchoRequest) returns (EchoResponse); + rpc UnimplementedBidi(stream EchoRequest) returns (stream EchoResponse); +} + +service EchoTest1Service { + rpc Echo(EchoRequest) returns (EchoResponse); + rpc Echo1(EchoRequest) returns (EchoResponse); + rpc Echo2(EchoRequest) returns (EchoResponse); + // A service which checks that the initial metadata sent over contains some + // expected key value pair + rpc CheckClientInitialMetadata(SimpleRequest) returns (SimpleResponse); + rpc RequestStream(stream EchoRequest) returns (EchoResponse); + rpc ResponseStream(EchoRequest) returns (stream EchoResponse); + rpc BidiStream(stream EchoRequest) returns (stream EchoResponse); + rpc Unimplemented(EchoRequest) returns (EchoResponse); +} + +service EchoTest2Service { + rpc Echo(EchoRequest) returns (EchoResponse); + rpc Echo1(EchoRequest) returns (EchoResponse); + rpc Echo2(EchoRequest) returns (EchoResponse); + // A service which checks that the initial metadata sent over contains some + // expected key value pair + rpc CheckClientInitialMetadata(SimpleRequest) returns (SimpleResponse); + rpc RequestStream(stream EchoRequest) returns (EchoResponse); + rpc ResponseStream(EchoRequest) returns (stream EchoResponse); + rpc BidiStream(stream EchoRequest) returns (stream EchoResponse); + rpc Unimplemented(EchoRequest) returns (EchoResponse); +} + +service UnimplementedEchoService { + rpc Unimplemented(EchoRequest) returns (EchoResponse); +} + +// A service without any rpc defined to test coverage. +service NoRpcService {} diff --git a/packages/grpc-js-xds/proto/grpc/testing/echo_messages.proto b/packages/grpc-js-xds/proto/grpc/testing/echo_messages.proto new file mode 100644 index 000000000..44f22133e --- /dev/null +++ b/packages/grpc-js-xds/proto/grpc/testing/echo_messages.proto @@ -0,0 +1,74 @@ + +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package grpc.testing; + +option cc_enable_arenas = true; + +import "grpc/testing/xds/v3/orca_load_report.proto"; + +// Message to be echoed back serialized in trailer. +message DebugInfo { + repeated string stack_entries = 1; + string detail = 2; +} + +// Error status client expects to see. +message ErrorStatus { + int32 code = 1; + string error_message = 2; + string binary_error_details = 3; +} + +message RequestParams { + bool echo_deadline = 1; + int32 client_cancel_after_us = 2; + int32 server_cancel_after_us = 3; + bool echo_metadata = 4; + bool check_auth_context = 5; + int32 response_message_length = 6; + bool echo_peer = 7; + string expected_client_identity = 8; // will force check_auth_context. + bool skip_cancelled_check = 9; + string expected_transport_security_type = 10; + DebugInfo debug_info = 11; + bool server_die = 12; // Server should not see a request with this set. + string binary_error_details = 13; + ErrorStatus expected_error = 14; + int32 server_sleep_us = 15; // sleep when invoking server for deadline tests + int32 backend_channel_idx = 16; // which backend to send request to + bool echo_metadata_initially = 17; + bool server_notify_client_when_started = 18; + xds.data.orca.v3.OrcaLoadReport backend_metrics = 19; + bool echo_host_from_authority_header = 20; +} + +message EchoRequest { + string message = 1; + RequestParams param = 2; +} + +message ResponseParams { + int64 request_deadline = 1; + string host = 2; + string peer = 3; +} + +message EchoResponse { + string message = 1; + ResponseParams param = 2; +} diff --git a/packages/grpc-js-xds/proto/grpc/testing/simple_messages.proto b/packages/grpc-js-xds/proto/grpc/testing/simple_messages.proto new file mode 100644 index 000000000..3afe236b4 --- /dev/null +++ b/packages/grpc-js-xds/proto/grpc/testing/simple_messages.proto @@ -0,0 +1,26 @@ + +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package grpc.testing; + +message SimpleRequest {} + +message SimpleResponse {} + +message StringValue { + string message = 1; +} diff --git a/packages/grpc-js-xds/proto/grpc/testing/xds/v3/orca_load_report.proto b/packages/grpc-js-xds/proto/grpc/testing/xds/v3/orca_load_report.proto new file mode 100644 index 000000000..033e64ba4 --- /dev/null +++ b/packages/grpc-js-xds/proto/grpc/testing/xds/v3/orca_load_report.proto @@ -0,0 +1,44 @@ +// Copyright 2020 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package xds.data.orca.v3; + +// See section `ORCA load report format` of the design document in +// :ref:`https://github.com/envoyproxy/envoy/issues/6614`. + +message OrcaLoadReport { + // CPU utilization expressed as a fraction of available CPU resources. This + // should be derived from the latest sample or measurement. + double cpu_utilization = 1; + + // Memory utilization expressed as a fraction of available memory + // resources. This should be derived from the latest sample or measurement. + double mem_utilization = 2; + + // Total RPS being served by an endpoint. This should cover all services that an endpoint is + // responsible for. + uint64 rps = 3; + + // Application specific requests costs. Each value is an absolute cost (e.g. 3487 bytes of + // storage) associated with the request. + map request_cost = 4; + + // Resource utilization values. Each value is expressed as a fraction of total resources + // available, derived from the latest sample or measurement. + map utilization = 5; +} diff --git a/packages/grpc-js-xds/scripts/xds-v3.sh b/packages/grpc-js-xds/scripts/xds-v3.sh new file mode 100755 index 000000000..103cbc429 --- /dev/null +++ b/packages/grpc-js-xds/scripts/xds-v3.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright 2021 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +XDS_V3_OPT="--xds_v3_support" $(dirname $0)/xds.sh \ No newline at end of file diff --git a/packages/grpc-js-xds/scripts/xds.sh b/packages/grpc-js-xds/scripts/xds.sh old mode 100644 new mode 100755 index 714b6fff8..7e6794a31 --- a/packages/grpc-js-xds/scripts/xds.sh +++ b/packages/grpc-js-xds/scripts/xds.sh @@ -48,17 +48,21 @@ git clone -b master --single-branch --depth=1 https://github.com/grpc/grpc.git grpc/tools/run_tests/helper_scripts/prep_xds.sh -GRPC_NODE_TRACE=xds_client,xds_resolver,cds_balancer,eds_balancer,priority,weighted_target,round_robin,resolving_load_balancer,subchannel,keepalive,dns_resolver \ +mkdir -p "${KOKORO_ARTIFACTS_DIR}/github/grpc/reports" + +GRPC_NODE_TRACE=xds_client,xds_resolver,cds_balancer,eds_balancer,priority,weighted_target,round_robin,resolving_load_balancer,subchannel,keepalive,dns_resolver,fault_injection,http_filter,csds \ GRPC_NODE_VERBOSITY=DEBUG \ NODE_XDS_INTEROP_VERBOSITY=1 \ python3 grpc/tools/run_tests/run_xds_tests.py \ - --test_case="all,path_matching,header_matching" \ + --test_case="ping_pong,circuit_breaking" \ --project_id=grpc-testing \ - --source_image=projects/grpc-testing/global/images/xds-test-server-2 \ + --source_image=projects/grpc-testing/global/images/xds-test-server-5 \ --path_to_server_binary=/java_server/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/xds-test-server \ --gcp_suffix=$(date '+%s') \ --verbose \ - --client_cmd="$(which node) grpc-node/packages/grpc-js-xds/build/interop/xds-interop-client \ + --qps=75 \ + ${XDS_V3_OPT-} \ + --client_cmd="$(which node) --enable-source-maps --prof --logfile=${KOKORO_ARTIFACTS_DIR}/github/grpc/reports/prof.log grpc-node/packages/grpc-js-xds/build/interop/xds-interop-client \ --server=xds:///{server_uri} \ --stats_port={stats_port} \ --qps={qps} \ diff --git a/packages/grpc-js-xds/scripts/xds_k8s_lb.sh b/packages/grpc-js-xds/scripts/xds_k8s_lb.sh new file mode 100755 index 000000000..4a83d44d5 --- /dev/null +++ b/packages/grpc-js-xds/scripts/xds_k8s_lb.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail + +# Constants +readonly GITHUB_REPOSITORY_NAME="grpc-node" +readonly TEST_DRIVER_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/${TEST_DRIVER_REPO_OWNER:-grpc}/grpc/${TEST_DRIVER_BRANCH:-master}/tools/internal_ci/linux/grpc_xds_k8s_install_test_driver.sh" +## xDS test client Docker images +readonly SERVER_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/java-server:v1.46.x" +readonly CLIENT_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/node-client" +readonly FORCE_IMAGE_BUILD="${FORCE_IMAGE_BUILD:-0}" +readonly BUILD_APP_PATH="packages/grpc-js-xds/interop/Dockerfile" +readonly LANGUAGE_NAME="Node" + +####################################### +# Builds test app Docker images and pushes them to GCR +# Globals: +# BUILD_APP_PATH +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# TESTING_VERSION: version branch under test, f.e. v1.42.x, master +# Arguments: +# None +# Outputs: +# Writes the output of `gcloud builds submit` to stdout, stderr +####################################### +build_test_app_docker_images() { + echo "Building ${LANGUAGE_NAME} xDS interop test app Docker images" + + pushd "${SRC_DIR}" + docker build \ + -f "${BUILD_APP_PATH}" \ + -t "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + . + + gcloud -q auth configure-docker + docker push "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" + if is_version_branch "${TESTING_VERSION}"; then + tag_and_push_docker_image "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" "${TESTING_VERSION}" + fi + popd +} + +####################################### +# Builds test app and its docker images unless they already exist +# Globals: +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# FORCE_IMAGE_BUILD +# Arguments: +# None +# Outputs: +# Writes the output to stdout, stderr +####################################### +build_docker_images_if_needed() { + # Check if images already exist + client_tags="$(gcloud_gcr_list_image_tags "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}")" + printf "Client image: %s:%s\n" "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" + echo "${client_tags:-Client image not found}" + + # Build if any of the images are missing, or FORCE_IMAGE_BUILD=1 + if [[ "${FORCE_IMAGE_BUILD}" == "1" || -z "${client_tags}" ]]; then + build_test_app_docker_images + else + echo "Skipping ${LANGUAGE_NAME} test app build" + fi +} + +####################################### +# Executes the test case +# Globals: +# TEST_DRIVER_FLAGFILE: Relative path to test driver flagfile +# KUBE_CONTEXT: The name of kubectl context with GKE cluster access +# SECONDARY_KUBE_CONTEXT: The name of kubectl context with secondary GKE cluster access, if any +# TEST_XML_OUTPUT_DIR: Output directory for the test xUnit XML report +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# Arguments: +# Test case name +# Outputs: +# Writes the output of test execution to stdout, stderr +# Test xUnit report to ${TEST_XML_OUTPUT_DIR}/${test_name}/sponge_log.xml +####################################### +run_test() { + # Test driver usage: + # https://github.com/grpc/grpc/tree/master/tools/run_tests/xds_k8s_test_driver#basic-usage + local test_name="${1:?Usage: run_test test_name}" + local out_dir="${TEST_XML_OUTPUT_DIR}/${test_name}" + mkdir -pv "${out_dir}" + # testing_version is used by the framework to determine the supported PSM + # features. It's captured from Kokoro job name of the Node repo, which takes + # the form: + # grpc/node// + python3 -m "tests.${test_name}" \ + --flagfile="${TEST_DRIVER_FLAGFILE}" \ + --kube_context="${KUBE_CONTEXT}" \ + --secondary_kube_context="${SECONDARY_KUBE_CONTEXT}" \ + --client_image="${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + --server_image="${SERVER_IMAGE_NAME}" \ + --testing_version="${TESTING_VERSION}" \ + --force_cleanup \ + --collect_app_logs \ + --log_dir="${out_dir}" \ + --xml_output_file="${out_dir}/sponge_log.xml" \ + |& tee "${out_dir}/sponge_log.log" +} + +####################################### +# Main function: provision software necessary to execute tests, and run them +# Globals: +# KOKORO_ARTIFACTS_DIR +# GITHUB_REPOSITORY_NAME +# SRC_DIR: Populated with absolute path to the source repo +# TEST_DRIVER_REPO_DIR: Populated with the path to the repo containing +# the test driver +# TEST_DRIVER_FULL_DIR: Populated with the path to the test driver source code +# TEST_DRIVER_FLAGFILE: Populated with relative path to test driver flagfile +# TEST_XML_OUTPUT_DIR: Populated with the path to test xUnit XML report +# GIT_ORIGIN_URL: Populated with the origin URL of git repo used for the build +# GIT_COMMIT: Populated with the SHA-1 of git commit being built +# GIT_COMMIT_SHORT: Populated with the short SHA-1 of git commit being built +# KUBE_CONTEXT: Populated with name of kubectl context with GKE cluster access +# SECONDARY_KUBE_CONTEXT: Populated with name of kubectl context with secondary GKE cluster access, if any +# Arguments: +# None +# Outputs: +# Writes the output of test execution to stdout, stderr +####################################### +main() { + local script_dir + script_dir="$(dirname "$0")" + + cd "${script_dir}" + + git submodule update --init --recursive + + # Source the test driver from the master branch. + echo "Sourcing test driver install script from: ${TEST_DRIVER_INSTALL_SCRIPT_URL}" + source /dev/stdin <<< "$(curl -s "${TEST_DRIVER_INSTALL_SCRIPT_URL}")" + + activate_gke_cluster GKE_CLUSTER_PSM_LB + activate_secondary_gke_cluster GKE_CLUSTER_PSM_LB + + set -x + if [[ -n "${KOKORO_ARTIFACTS_DIR}" ]]; then + kokoro_setup_test_driver "${GITHUB_REPOSITORY_NAME}" + else + local_setup_test_driver "${script_dir}" + fi + build_docker_images_if_needed + + # Run tests + cd "${TEST_DRIVER_FULL_DIR}" + local failed_tests=0 + test_suites=("baseline_test" "api_listener_test" "change_backend_service_test" "failover_test" "remove_neg_test" "round_robin_test" "outlier_detection_test") + for test in "${test_suites[@]}"; do + run_test $test || (( ++failed_tests )) + done + echo "Failed test suites: ${failed_tests}" +} + +main "$@" diff --git a/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh b/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh new file mode 100644 index 000000000..fc74718f2 --- /dev/null +++ b/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh @@ -0,0 +1,162 @@ +#!/usr/bin/env bash +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail + +# Constants +readonly GITHUB_REPOSITORY_NAME="grpc-node" +readonly TEST_DRIVER_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/${TEST_DRIVER_REPO_OWNER:-grpc}/grpc/${TEST_DRIVER_BRANCH:-master}/tools/internal_ci/linux/grpc_xds_k8s_install_test_driver.sh" +## xDS test client Docker images +readonly CLIENT_IMAGE_NAME="gcr.io/grpc-testing/xds-interop/node-client" +readonly FORCE_IMAGE_BUILD="${FORCE_IMAGE_BUILD:-0}" +readonly BUILD_APP_PATH="packages/grpc-js-xds/interop/Dockerfile" +readonly LANGUAGE_NAME="Node" + +####################################### +# Builds test app Docker images and pushes them to GCR +# Globals: +# BUILD_APP_PATH +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# TESTING_VERSION: version branch under test, f.e. v1.42.x, master +# Arguments: +# None +# Outputs: +# Writes the output of `gcloud builds submit` to stdout, stderr +####################################### +build_test_app_docker_images() { + echo "Building ${LANGUAGE_NAME} xDS interop test app Docker images" + + pushd "${SRC_DIR}" + docker build \ + -f "${BUILD_APP_PATH}" \ + -t "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + . + + gcloud -q auth configure-docker + docker push "${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" + if is_version_branch "${TESTING_VERSION}"; then + tag_and_push_docker_image "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" "${TESTING_VERSION}" + fi + popd +} + +####################################### +# Builds test app and its docker images unless they already exist +# Globals: +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# FORCE_IMAGE_BUILD +# Arguments: +# None +# Outputs: +# Writes the output to stdout, stderr +####################################### +build_docker_images_if_needed() { + # Check if images already exist + client_tags="$(gcloud_gcr_list_image_tags "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}")" + printf "Client image: %s:%s\n" "${CLIENT_IMAGE_NAME}" "${GIT_COMMIT}" + echo "${client_tags:-Client image not found}" + + # Build if any of the images are missing, or FORCE_IMAGE_BUILD=1 + if [[ "${FORCE_IMAGE_BUILD}" == "1" || -z "${client_tags}" ]]; then + build_test_app_docker_images + else + echo "Skipping ${LANGUAGE_NAME} test app build" + fi +} + +####################################### +# Executes the test case +# Globals: +# TEST_DRIVER_FLAGFILE: Relative path to test driver flagfile +# KUBE_CONTEXT: The name of kubectl context with GKE cluster access +# TEST_XML_OUTPUT_DIR: Output directory for the test xUnit XML report +# CLIENT_IMAGE_NAME: Test client Docker image name +# GIT_COMMIT: SHA-1 of git commit being built +# TESTING_VERSION: version branch under test: used by the framework to determine the supported PSM +# features. +# Arguments: +# Test case name +# Outputs: +# Writes the output of test execution to stdout, stderr +# Test xUnit report to ${TEST_XML_OUTPUT_DIR}/${test_name}/sponge_log.xml +####################################### +run_test() { + # Test driver usage: + # https://github.com/grpc/grpc/tree/master/tools/run_tests/xds_k8s_test_driver#basic-usage + local test_name="${1:?Usage: run_test test_name}" + local out_dir="${TEST_XML_OUTPUT_DIR}/${test_name}" + mkdir -pv "${out_dir}" + set -x + python3 -m "tests.${test_name}" \ + --flagfile="${TEST_DRIVER_FLAGFILE}" \ + --flagfile="config/url-map.cfg" \ + --kube_context="${KUBE_CONTEXT}" \ + --client_image="${CLIENT_IMAGE_NAME}:${GIT_COMMIT}" \ + --testing_version="${TESTING_VERSION}" \ + --collect_app_logs \ + --log_dir="${out_dir}" \ + --xml_output_file="${out_dir}/sponge_log.xml" \ + |& tee "${out_dir}/sponge_log.log" +} + +####################################### +# Main function: provision software necessary to execute tests, and run them +# Globals: +# KOKORO_ARTIFACTS_DIR +# GITHUB_REPOSITORY_NAME +# SRC_DIR: Populated with absolute path to the source repo +# TEST_DRIVER_REPO_DIR: Populated with the path to the repo containing +# the test driver +# TEST_DRIVER_FULL_DIR: Populated with the path to the test driver source code +# TEST_DRIVER_FLAGFILE: Populated with relative path to test driver flagfile +# TEST_XML_OUTPUT_DIR: Populated with the path to test xUnit XML report +# GIT_ORIGIN_URL: Populated with the origin URL of git repo used for the build +# GIT_COMMIT: Populated with the SHA-1 of git commit being built +# GIT_COMMIT_SHORT: Populated with the short SHA-1 of git commit being built +# KUBE_CONTEXT: Populated with name of kubectl context with GKE cluster access +# Arguments: +# None +# Outputs: +# Writes the output of test execution to stdout, stderr +####################################### +main() { + local script_dir + script_dir="$(dirname "$0")" + + cd "${script_dir}" + + git submodule update --init --recursive + + # Source the test driver from the master branch. + echo "Sourcing test driver install script from: ${TEST_DRIVER_INSTALL_SCRIPT_URL}" + source /dev/stdin <<< "$(curl -s "${TEST_DRIVER_INSTALL_SCRIPT_URL}")" + + activate_gke_cluster GKE_CLUSTER_PSM_BASIC + + set -x + if [[ -n "${KOKORO_ARTIFACTS_DIR}" ]]; then + kokoro_setup_test_driver "${GITHUB_REPOSITORY_NAME}" + else + local_setup_test_driver "${script_dir}" + fi + build_docker_images_if_needed + # Run tests + cd "${TEST_DRIVER_FULL_DIR}" + run_test url_map || echo "Failed url_map test" +} + +main "$@" diff --git a/packages/grpc-js-xds/src/csds.ts b/packages/grpc-js-xds/src/csds.ts new file mode 100644 index 000000000..114c18042 --- /dev/null +++ b/packages/grpc-js-xds/src/csds.ts @@ -0,0 +1,214 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { Node } from "./generated/envoy/config/core/v3/Node"; +import { ClientConfig, _envoy_service_status_v3_ClientConfig_GenericXdsConfig as GenericXdsConfig } from "./generated/envoy/service/status/v3/ClientConfig"; +import { ClientStatusDiscoveryServiceHandlers } from "./generated/envoy/service/status/v3/ClientStatusDiscoveryService"; +import { ClientStatusRequest__Output } from "./generated/envoy/service/status/v3/ClientStatusRequest"; +import { ClientStatusResponse } from "./generated/envoy/service/status/v3/ClientStatusResponse"; +import { Timestamp } from "./generated/google/protobuf/Timestamp"; +import { AdsTypeUrl, CDS_TYPE_URL, EDS_TYPE_URL, LDS_TYPE_URL, RDS_TYPE_URL } from "./resources"; +import { HandleResponseResult } from "./xds-stream-state/xds-stream-state"; +import { sendUnaryData, ServerDuplexStream, ServerUnaryCall, status, experimental, loadPackageDefinition, logVerbosity } from '@grpc/grpc-js'; +import { loadSync } from "@grpc/proto-loader"; +import { ProtoGrpcType as CsdsProtoGrpcType } from "./generated/csds"; + +import registerAdminService = experimental.registerAdminService; + +const TRACER_NAME = 'csds'; + +function trace(text: string): void { + experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); +} + + +function dateToProtoTimestamp(date?: Date | null): Timestamp | null { + if (!date) { + return null; + } + const millisSinceEpoch = date.getTime(); + return { + seconds: (millisSinceEpoch / 1000) | 0, + nanos: (millisSinceEpoch % 1000) * 1_000_000 + } +} + +let clientNode: Node | null = null; + +const configStatus = { + [EDS_TYPE_URL]: new Map(), + [CDS_TYPE_URL]: new Map(), + [RDS_TYPE_URL]: new Map(), + [LDS_TYPE_URL]: new Map() +}; + +/** + * This function only accepts a v3 Node message, because we are only supporting + * v3 CSDS and it only handles v3 Nodes. If the client is actually using v2 xDS + * APIs, it should just provide the equivalent v3 Node message. + * @param node The Node message for the client that is requesting resources + */ +export function setCsdsClientNode(node: Node) { + clientNode = node; +} + +/** + * Update the config status maps from the list of names of requested resources + * for a specific type URL. These lists are the source of truth for determining + * what resources will be listed in the CSDS response. Any resource that is not + * in this list will never actually be applied anywhere. + * @param typeUrl The resource type URL + * @param names The list of resource names that are being requested + */ +export function updateCsdsRequestedNameList(typeUrl: AdsTypeUrl, names: string[]) { + trace('Update type URL ' + typeUrl + ' with names [' + names + ']'); + const currentTime = dateToProtoTimestamp(new Date()); + const configMap = configStatus[typeUrl]; + for (const name of names) { + if (!configMap.has(name)) { + configMap.set(name, { + type_url: typeUrl, + name: name, + last_updated: currentTime, + client_status: 'REQUESTED' + }); + } + } + for (const name of configMap.keys()) { + if (!names.includes(name)) { + configMap.delete(name); + } + } +} + +/** + * Update the config status maps from the result of parsing a single ADS + * response. All resources that validated are considered "ACKED", and all + * resources that failed validation are considered "NACKED". + * @param typeUrl The type URL of resources in this response + * @param versionInfo The version info field from this response + * @param updates The lists of resources that passed and failed validation + */ +export function updateCsdsResourceResponse(typeUrl: AdsTypeUrl, versionInfo: string, updates: HandleResponseResult) { + const currentTime = dateToProtoTimestamp(new Date()); + const configMap = configStatus[typeUrl]; + for (const {name, raw} of updates.accepted) { + const mapEntry = configMap.get(name); + if (mapEntry) { + trace('Updated ' + typeUrl + ' resource ' + name + ' to state ACKED'); + mapEntry.client_status = 'ACKED'; + mapEntry.version_info = versionInfo; + mapEntry.xds_config = raw; + mapEntry.error_state = null; + mapEntry.last_updated = currentTime; + } + } + for (const {name, error, raw} of updates.rejected) { + const mapEntry = configMap.get(name); + if (mapEntry) { + trace('Updated ' + typeUrl + ' resource ' + name + ' to state NACKED'); + mapEntry.client_status = 'NACKED'; + mapEntry.error_state = { + failed_configuration: raw, + last_update_attempt: currentTime, + details: error, + version_info: versionInfo + }; + } + } + for (const name of updates.missing) { + const mapEntry = configMap.get(name); + if (mapEntry) { + trace('Updated ' + typeUrl + ' resource ' + name + ' to state DOES_NOT_EXIST'); + mapEntry.client_status = 'DOES_NOT_EXIST'; + mapEntry.version_info = versionInfo; + mapEntry.xds_config = null; + mapEntry.error_state = null; + mapEntry.last_updated = currentTime; + } + } +} + +function getCurrentConfig(): ClientConfig { + const genericConfigList: GenericXdsConfig[] = []; + for (const configMap of Object.values(configStatus)) { + for (const configValue of configMap.values()) { + genericConfigList.push(configValue); + } + } + const config = { + node: clientNode, + generic_xds_configs: genericConfigList + }; + trace('Sending curent config ' + JSON.stringify(config, undefined, 2)); + return config; +} + +const csdsImplementation: ClientStatusDiscoveryServiceHandlers = { + FetchClientStatus(call: ServerUnaryCall, callback: sendUnaryData) { + const request = call.request; + if (request.node_matchers.length > 0) { + callback({ + code: status.INVALID_ARGUMENT, + details: 'Node matchers not supported' + }); + return; + } + callback(null, { + config: [getCurrentConfig()] + }); + }, + StreamClientStatus(call: ServerDuplexStream) { + call.on('data', (request: ClientStatusRequest__Output) => { + if (request.node_matchers.length > 0) { + call.emit('error', { + code: status.INVALID_ARGUMENT, + details: 'Node matchers not supported' + }); + return; + } + call.write({ + config: [getCurrentConfig()] + }); + }); + call.on('end', () => { + call.end(); + }); + } +} + +const loadedProto = loadSync('envoy/service/status/v3/csds.proto', { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + includeDirs: [ + // Paths are relative to src/build + __dirname + '/../../deps/envoy-api/', + __dirname + '/../../deps/xds/', + __dirname + '/../../deps/protoc-gen-validate/', + __dirname + '/../../deps/googleapis/' + ], +}); + +const csdsGrpcObject = loadPackageDefinition(loadedProto) as unknown as CsdsProtoGrpcType; +const csdsServiceDefinition = csdsGrpcObject.envoy.service.status.v3.ClientStatusDiscoveryService.service; + +export function setup() { + registerAdminService(() => csdsServiceDefinition, () => csdsImplementation); +} \ No newline at end of file diff --git a/packages/grpc-js-xds/src/environment.ts b/packages/grpc-js-xds/src/environment.ts index c2c7f2e05..7ec0fd187 100644 --- a/packages/grpc-js-xds/src/environment.ts +++ b/packages/grpc-js-xds/src/environment.ts @@ -13,4 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. * - */ \ No newline at end of file + */ + +export const EXPERIMENTAL_FAULT_INJECTION = (process.env.GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION ?? 'true') === 'true'; +export const EXPERIMENTAL_OUTLIER_DETECTION = (process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION ?? 'true') === 'true'; +export const EXPERIMENTAL_RETRY = (process.env.GRPC_XDS_EXPERIMENTAL_ENABLE_RETRY ?? 'true') === 'true'; \ No newline at end of file diff --git a/packages/grpc-js-xds/src/fraction.ts b/packages/grpc-js-xds/src/fraction.ts new file mode 100644 index 000000000..709af72b2 --- /dev/null +++ b/packages/grpc-js-xds/src/fraction.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FractionalPercent__Output } from "./generated/envoy/type/v3/FractionalPercent"; + +export interface Fraction { + numerator: number; + denominator: number; +} + +export function fractionToString(fraction: Fraction): string { + return `${fraction.numerator}/${fraction.denominator}`; +} + +const RUNTIME_FRACTION_DENOMINATOR_VALUES = { + HUNDRED: 100, + TEN_THOUSAND: 10_000, + MILLION: 1_000_000 +} + +export function envoyFractionToFraction(envoyFraction: FractionalPercent__Output): Fraction { + return { + numerator: envoyFraction.numerator, + denominator: RUNTIME_FRACTION_DENOMINATOR_VALUES[envoyFraction.denominator] + }; +} \ No newline at end of file diff --git a/packages/grpc-js-xds/src/generated/ads.ts b/packages/grpc-js-xds/src/generated/ads.ts index 0eacd1e34..228f6f1d4 100644 --- a/packages/grpc-js-xds/src/generated/ads.ts +++ b/packages/grpc-js-xds/src/generated/ads.ts @@ -1,7 +1,7 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; -import type { AggregatedDiscoveryServiceClient as _envoy_service_discovery_v2_AggregatedDiscoveryServiceClient } from './envoy/service/discovery/v2/AggregatedDiscoveryService'; +import type { AggregatedDiscoveryServiceClient as _envoy_service_discovery_v3_AggregatedDiscoveryServiceClient, AggregatedDiscoveryServiceDefinition as _envoy_service_discovery_v3_AggregatedDiscoveryServiceDefinition } from './envoy/service/discovery/v3/AggregatedDiscoveryService'; type SubtypeConstructor any, Subtype> = { new(...args: ConstructorParameters): Subtype; @@ -9,14 +9,11 @@ type SubtypeConstructor any, Subtype> export interface ProtoGrpcType { envoy: { - api: { - v2: { - DeltaDiscoveryRequest: MessageTypeDefinition - DeltaDiscoveryResponse: MessageTypeDefinition - DiscoveryRequest: MessageTypeDefinition - DiscoveryResponse: MessageTypeDefinition - Resource: MessageTypeDefinition - core: { + annotations: { + } + config: { + core: { + v3: { Address: MessageTypeDefinition AsyncDataSource: MessageTypeDefinition BackoffStrategy: MessageTypeDefinition @@ -25,6 +22,7 @@ export interface ProtoGrpcType { CidrRange: MessageTypeDefinition ControlPlane: MessageTypeDefinition DataSource: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition Extension: MessageTypeDefinition HeaderMap: MessageTypeDefinition HeaderValue: MessageTypeDefinition @@ -34,6 +32,7 @@ export interface ProtoGrpcType { Metadata: MessageTypeDefinition Node: MessageTypeDefinition Pipe: MessageTypeDefinition + QueryParameter: MessageTypeDefinition RemoteDataSource: MessageTypeDefinition RequestMethod: EnumTypeDefinition RetryPolicy: MessageTypeDefinition @@ -41,18 +40,20 @@ export interface ProtoGrpcType { RuntimeDouble: MessageTypeDefinition RuntimeFeatureFlag: MessageTypeDefinition RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition RuntimeUInt32: MessageTypeDefinition SocketAddress: MessageTypeDefinition SocketOption: MessageTypeDefinition TcpKeepalive: MessageTypeDefinition TrafficDirection: EnumTypeDefinition TransportSocket: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition } } } service: { discovery: { - v2: { + v3: { AdsDummy: MessageTypeDefinition /** * See https://github.com/lyft/envoy-api#apis for a description of the role of @@ -62,14 +63,21 @@ export interface ProtoGrpcType { * DiscoveryRequest/DiscoveryResponse provides sufficient information to recover * the multiplexed singleton APIs at the Envoy instance and management server. */ - AggregatedDiscoveryService: SubtypeConstructor & { service: ServiceDefinition } + AggregatedDiscoveryService: SubtypeConstructor & { service: _envoy_service_discovery_v3_AggregatedDiscoveryServiceDefinition } + DeltaDiscoveryRequest: MessageTypeDefinition + DeltaDiscoveryResponse: MessageTypeDefinition + DiscoveryRequest: MessageTypeDefinition + DiscoveryResponse: MessageTypeDefinition + Resource: MessageTypeDefinition } } } type: { - FractionalPercent: MessageTypeDefinition - Percent: MessageTypeDefinition - SemanticVersion: MessageTypeDefinition + v3: { + FractionalPercent: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + } } } google: { @@ -122,6 +130,7 @@ export interface ProtoGrpcType { MigrateAnnotation: MessageTypeDefinition PackageVersionStatus: EnumTypeDefinition StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition } } validate: { @@ -150,5 +159,21 @@ export interface ProtoGrpcType { UInt32Rules: MessageTypeDefinition UInt64Rules: MessageTypeDefinition } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + ContextParams: MessageTypeDefinition + } + } + } } diff --git a/packages/grpc-js-xds/src/generated/cluster.ts b/packages/grpc-js-xds/src/generated/cluster.ts index b7005a3f0..78ac3bbd3 100644 --- a/packages/grpc-js-xds/src/generated/cluster.ts +++ b/packages/grpc-js-xds/src/generated/cluster.ts @@ -1,5 +1,5 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; type SubtypeConstructor any, Subtype> = { @@ -10,34 +10,25 @@ export interface ProtoGrpcType { envoy: { annotations: { } - api: { - v2: { - Cluster: MessageTypeDefinition - ClusterLoadAssignment: MessageTypeDefinition - LoadBalancingPolicy: MessageTypeDefinition - UpstreamBindConfig: MessageTypeDefinition - UpstreamConnectionOptions: MessageTypeDefinition - auth: { - CertificateValidationContext: MessageTypeDefinition - CommonTlsContext: MessageTypeDefinition - DownstreamTlsContext: MessageTypeDefinition - GenericSecret: MessageTypeDefinition - PrivateKeyProvider: MessageTypeDefinition - SdsSecretConfig: MessageTypeDefinition - Secret: MessageTypeDefinition - TlsCertificate: MessageTypeDefinition - TlsParameters: MessageTypeDefinition - TlsSessionTicketKeys: MessageTypeDefinition - UpstreamTlsContext: MessageTypeDefinition - } - cluster: { + config: { + cluster: { + v3: { CircuitBreakers: MessageTypeDefinition + Cluster: MessageTypeDefinition + ClusterCollection: MessageTypeDefinition Filter: MessageTypeDefinition + LoadBalancingPolicy: MessageTypeDefinition OutlierDetection: MessageTypeDefinition + TrackClusterStats: MessageTypeDefinition + UpstreamBindConfig: MessageTypeDefinition + UpstreamConnectionOptions: MessageTypeDefinition } - core: { + } + core: { + v3: { Address: MessageTypeDefinition AggregatedConfigSource: MessageTypeDefinition + AlternateProtocolsCacheOptions: MessageTypeDefinition ApiConfigSource: MessageTypeDefinition ApiVersion: EnumTypeDefinition AsyncDataSource: MessageTypeDefinition @@ -48,8 +39,12 @@ export interface ProtoGrpcType { ConfigSource: MessageTypeDefinition ControlPlane: MessageTypeDefinition DataSource: MessageTypeDefinition + DnsResolutionConfig: MessageTypeDefinition + DnsResolverOptions: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition EventServiceConfig: MessageTypeDefinition Extension: MessageTypeDefinition + ExtensionConfigSource: MessageTypeDefinition GrpcProtocolOptions: MessageTypeDefinition GrpcService: MessageTypeDefinition HeaderMap: MessageTypeDefinition @@ -59,12 +54,16 @@ export interface ProtoGrpcType { HealthStatus: EnumTypeDefinition Http1ProtocolOptions: MessageTypeDefinition Http2ProtocolOptions: MessageTypeDefinition + Http3ProtocolOptions: MessageTypeDefinition HttpProtocolOptions: MessageTypeDefinition HttpUri: MessageTypeDefinition + KeepaliveSettings: MessageTypeDefinition Locality: MessageTypeDefinition Metadata: MessageTypeDefinition Node: MessageTypeDefinition Pipe: MessageTypeDefinition + QueryParameter: MessageTypeDefinition + QuicProtocolOptions: MessageTypeDefinition RateLimitSettings: MessageTypeDefinition RemoteDataSource: MessageTypeDefinition RequestMethod: EnumTypeDefinition @@ -73,7 +72,9 @@ export interface ProtoGrpcType { RuntimeDouble: MessageTypeDefinition RuntimeFeatureFlag: MessageTypeDefinition RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition RuntimeUInt32: MessageTypeDefinition + SchemeHeaderTransformation: MessageTypeDefinition SelfConfigSource: MessageTypeDefinition SocketAddress: MessageTypeDefinition SocketOption: MessageTypeDefinition @@ -81,37 +82,42 @@ export interface ProtoGrpcType { TcpProtocolOptions: MessageTypeDefinition TrafficDirection: EnumTypeDefinition TransportSocket: MessageTypeDefinition + TypedExtensionConfig: MessageTypeDefinition UpstreamHttpProtocolOptions: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition } - endpoint: { + } + endpoint: { + v3: { + ClusterLoadAssignment: MessageTypeDefinition Endpoint: MessageTypeDefinition LbEndpoint: MessageTypeDefinition + LedsClusterLocalityConfig: MessageTypeDefinition LocalityLbEndpoints: MessageTypeDefinition } } } type: { - CodecClientType: EnumTypeDefinition - DoubleRange: MessageTypeDefinition - FractionalPercent: MessageTypeDefinition - Int32Range: MessageTypeDefinition - Int64Range: MessageTypeDefinition - Percent: MessageTypeDefinition - SemanticVersion: MessageTypeDefinition matcher: { - ListStringMatcher: MessageTypeDefinition - RegexMatchAndSubstitute: MessageTypeDefinition - RegexMatcher: MessageTypeDefinition - StringMatcher: MessageTypeDefinition + v3: { + ListStringMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + } + } + v3: { + CodecClientType: EnumTypeDefinition + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition } } } google: { - api: { - CustomHttpPattern: MessageTypeDefinition - Http: MessageTypeDefinition - HttpRule: MessageTypeDefinition - } protobuf: { Any: MessageTypeDefinition BoolValue: MessageTypeDefinition @@ -155,10 +161,12 @@ export interface ProtoGrpcType { udpa: { annotations: { FieldMigrateAnnotation: MessageTypeDefinition + FieldSecurityAnnotation: MessageTypeDefinition FileMigrateAnnotation: MessageTypeDefinition MigrateAnnotation: MessageTypeDefinition PackageVersionStatus: EnumTypeDefinition StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition } } validate: { @@ -187,5 +195,24 @@ export interface ProtoGrpcType { UInt32Rules: MessageTypeDefinition UInt64Rules: MessageTypeDefinition } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + Authority: MessageTypeDefinition + CollectionEntry: MessageTypeDefinition + ContextParams: MessageTypeDefinition + ResourceLocator: MessageTypeDefinition + } + } + } } diff --git a/packages/grpc-js-xds/src/generated/csds.ts b/packages/grpc-js-xds/src/generated/csds.ts new file mode 100644 index 000000000..58e903bc9 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/csds.ts @@ -0,0 +1,393 @@ +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + +import type { ClientStatusDiscoveryServiceClient as _envoy_service_status_v3_ClientStatusDiscoveryServiceClient, ClientStatusDiscoveryServiceDefinition as _envoy_service_status_v3_ClientStatusDiscoveryServiceDefinition } from './envoy/service/status/v3/ClientStatusDiscoveryService'; + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + envoy: { + admin: { + v3: { + BootstrapConfigDump: MessageTypeDefinition + ClientResourceStatus: EnumTypeDefinition + ClustersConfigDump: MessageTypeDefinition + ConfigDump: MessageTypeDefinition + EndpointsConfigDump: MessageTypeDefinition + ListenersConfigDump: MessageTypeDefinition + RoutesConfigDump: MessageTypeDefinition + ScopedRoutesConfigDump: MessageTypeDefinition + SecretsConfigDump: MessageTypeDefinition + UpdateFailureState: MessageTypeDefinition + } + } + annotations: { + } + config: { + accesslog: { + v3: { + AccessLog: MessageTypeDefinition + AccessLogFilter: MessageTypeDefinition + AndFilter: MessageTypeDefinition + ComparisonFilter: MessageTypeDefinition + DurationFilter: MessageTypeDefinition + ExtensionFilter: MessageTypeDefinition + GrpcStatusFilter: MessageTypeDefinition + HeaderFilter: MessageTypeDefinition + MetadataFilter: MessageTypeDefinition + NotHealthCheckFilter: MessageTypeDefinition + OrFilter: MessageTypeDefinition + ResponseFlagFilter: MessageTypeDefinition + RuntimeFilter: MessageTypeDefinition + StatusCodeFilter: MessageTypeDefinition + TraceableFilter: MessageTypeDefinition + } + } + bootstrap: { + v3: { + Admin: MessageTypeDefinition + Bootstrap: MessageTypeDefinition + ClusterManager: MessageTypeDefinition + CustomInlineHeader: MessageTypeDefinition + FatalAction: MessageTypeDefinition + LayeredRuntime: MessageTypeDefinition + Runtime: MessageTypeDefinition + RuntimeLayer: MessageTypeDefinition + Watchdog: MessageTypeDefinition + Watchdogs: MessageTypeDefinition + } + } + cluster: { + v3: { + CircuitBreakers: MessageTypeDefinition + Cluster: MessageTypeDefinition + ClusterCollection: MessageTypeDefinition + Filter: MessageTypeDefinition + LoadBalancingPolicy: MessageTypeDefinition + OutlierDetection: MessageTypeDefinition + TrackClusterStats: MessageTypeDefinition + UpstreamBindConfig: MessageTypeDefinition + UpstreamConnectionOptions: MessageTypeDefinition + } + } + core: { + v3: { + Address: MessageTypeDefinition + AggregatedConfigSource: MessageTypeDefinition + AlternateProtocolsCacheOptions: MessageTypeDefinition + ApiConfigSource: MessageTypeDefinition + ApiVersion: EnumTypeDefinition + AsyncDataSource: MessageTypeDefinition + BackoffStrategy: MessageTypeDefinition + BindConfig: MessageTypeDefinition + BuildVersion: MessageTypeDefinition + CidrRange: MessageTypeDefinition + ConfigSource: MessageTypeDefinition + ControlPlane: MessageTypeDefinition + DataSource: MessageTypeDefinition + DnsResolutionConfig: MessageTypeDefinition + DnsResolverOptions: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition + EventServiceConfig: MessageTypeDefinition + Extension: MessageTypeDefinition + ExtensionConfigSource: MessageTypeDefinition + GrpcProtocolOptions: MessageTypeDefinition + GrpcService: MessageTypeDefinition + HeaderMap: MessageTypeDefinition + HeaderValue: MessageTypeDefinition + HeaderValueOption: MessageTypeDefinition + HealthCheck: MessageTypeDefinition + HealthStatus: EnumTypeDefinition + Http1ProtocolOptions: MessageTypeDefinition + Http2ProtocolOptions: MessageTypeDefinition + Http3ProtocolOptions: MessageTypeDefinition + HttpProtocolOptions: MessageTypeDefinition + HttpUri: MessageTypeDefinition + KeepaliveSettings: MessageTypeDefinition + Locality: MessageTypeDefinition + Metadata: MessageTypeDefinition + Node: MessageTypeDefinition + Pipe: MessageTypeDefinition + ProxyProtocolConfig: MessageTypeDefinition + QueryParameter: MessageTypeDefinition + QuicProtocolOptions: MessageTypeDefinition + RateLimitSettings: MessageTypeDefinition + RemoteDataSource: MessageTypeDefinition + RequestMethod: EnumTypeDefinition + RetryPolicy: MessageTypeDefinition + RoutingPriority: EnumTypeDefinition + RuntimeDouble: MessageTypeDefinition + RuntimeFeatureFlag: MessageTypeDefinition + RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition + RuntimeUInt32: MessageTypeDefinition + SchemeHeaderTransformation: MessageTypeDefinition + SelfConfigSource: MessageTypeDefinition + SocketAddress: MessageTypeDefinition + SocketOption: MessageTypeDefinition + TcpKeepalive: MessageTypeDefinition + TcpProtocolOptions: MessageTypeDefinition + TrafficDirection: EnumTypeDefinition + TransportSocket: MessageTypeDefinition + TypedExtensionConfig: MessageTypeDefinition + UdpSocketConfig: MessageTypeDefinition + UpstreamHttpProtocolOptions: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition + } + } + endpoint: { + v3: { + ClusterLoadAssignment: MessageTypeDefinition + Endpoint: MessageTypeDefinition + LbEndpoint: MessageTypeDefinition + LedsClusterLocalityConfig: MessageTypeDefinition + LocalityLbEndpoints: MessageTypeDefinition + } + } + listener: { + v3: { + ActiveRawUdpListenerConfig: MessageTypeDefinition + ApiListener: MessageTypeDefinition + Filter: MessageTypeDefinition + FilterChain: MessageTypeDefinition + FilterChainMatch: MessageTypeDefinition + Listener: MessageTypeDefinition + ListenerCollection: MessageTypeDefinition + ListenerFilter: MessageTypeDefinition + ListenerFilterChainMatchPredicate: MessageTypeDefinition + QuicProtocolOptions: MessageTypeDefinition + UdpListenerConfig: MessageTypeDefinition + } + } + metrics: { + v3: { + DogStatsdSink: MessageTypeDefinition + HistogramBucketSettings: MessageTypeDefinition + HystrixSink: MessageTypeDefinition + StatsConfig: MessageTypeDefinition + StatsMatcher: MessageTypeDefinition + StatsSink: MessageTypeDefinition + StatsdSink: MessageTypeDefinition + TagSpecifier: MessageTypeDefinition + } + } + overload: { + v3: { + BufferFactoryConfig: MessageTypeDefinition + OverloadAction: MessageTypeDefinition + OverloadManager: MessageTypeDefinition + ResourceMonitor: MessageTypeDefinition + ScaleTimersOverloadActionConfig: MessageTypeDefinition + ScaledTrigger: MessageTypeDefinition + ThresholdTrigger: MessageTypeDefinition + Trigger: MessageTypeDefinition + } + } + route: { + v3: { + CorsPolicy: MessageTypeDefinition + Decorator: MessageTypeDefinition + DirectResponseAction: MessageTypeDefinition + FilterAction: MessageTypeDefinition + FilterConfig: MessageTypeDefinition + HeaderMatcher: MessageTypeDefinition + HedgePolicy: MessageTypeDefinition + InternalRedirectPolicy: MessageTypeDefinition + NonForwardingAction: MessageTypeDefinition + QueryParameterMatcher: MessageTypeDefinition + RateLimit: MessageTypeDefinition + RedirectAction: MessageTypeDefinition + RetryPolicy: MessageTypeDefinition + Route: MessageTypeDefinition + RouteAction: MessageTypeDefinition + RouteMatch: MessageTypeDefinition + Tracing: MessageTypeDefinition + VirtualCluster: MessageTypeDefinition + VirtualHost: MessageTypeDefinition + WeightedCluster: MessageTypeDefinition + } + } + trace: { + v3: { + Tracing: MessageTypeDefinition + } + } + } + extensions: { + transport_sockets: { + tls: { + v3: { + CertificateProviderPluginInstance: MessageTypeDefinition + CertificateValidationContext: MessageTypeDefinition + GenericSecret: MessageTypeDefinition + PrivateKeyProvider: MessageTypeDefinition + SdsSecretConfig: MessageTypeDefinition + Secret: MessageTypeDefinition + TlsCertificate: MessageTypeDefinition + TlsParameters: MessageTypeDefinition + TlsSessionTicketKeys: MessageTypeDefinition + } + } + } + } + service: { + status: { + v3: { + ClientConfig: MessageTypeDefinition + ClientConfigStatus: EnumTypeDefinition + /** + * CSDS is Client Status Discovery Service. It can be used to get the status of + * an xDS-compliant client from the management server's point of view. It can + * also be used to get the current xDS states directly from the client. + */ + ClientStatusDiscoveryService: SubtypeConstructor & { service: _envoy_service_status_v3_ClientStatusDiscoveryServiceDefinition } + ClientStatusRequest: MessageTypeDefinition + ClientStatusResponse: MessageTypeDefinition + ConfigStatus: EnumTypeDefinition + PerXdsConfig: MessageTypeDefinition + } + } + } + type: { + matcher: { + v3: { + DoubleMatcher: MessageTypeDefinition + ListMatcher: MessageTypeDefinition + ListStringMatcher: MessageTypeDefinition + MetadataMatcher: MessageTypeDefinition + NodeMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + StructMatcher: MessageTypeDefinition + ValueMatcher: MessageTypeDefinition + } + } + metadata: { + v3: { + MetadataKey: MessageTypeDefinition + MetadataKind: MessageTypeDefinition + } + } + tracing: { + v3: { + CustomTag: MessageTypeDefinition + } + } + v3: { + CodecClientType: EnumTypeDefinition + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + } + } + } + google: { + api: { + CustomHttpPattern: MessageTypeDefinition + Http: MessageTypeDefinition + HttpRule: MessageTypeDefinition + } + protobuf: { + Any: MessageTypeDefinition + BoolValue: MessageTypeDefinition + BytesValue: MessageTypeDefinition + DescriptorProto: MessageTypeDefinition + DoubleValue: MessageTypeDefinition + Duration: MessageTypeDefinition + Empty: MessageTypeDefinition + EnumDescriptorProto: MessageTypeDefinition + EnumOptions: MessageTypeDefinition + EnumValueDescriptorProto: MessageTypeDefinition + EnumValueOptions: MessageTypeDefinition + FieldDescriptorProto: MessageTypeDefinition + FieldOptions: MessageTypeDefinition + FileDescriptorProto: MessageTypeDefinition + FileDescriptorSet: MessageTypeDefinition + FileOptions: MessageTypeDefinition + FloatValue: MessageTypeDefinition + GeneratedCodeInfo: MessageTypeDefinition + Int32Value: MessageTypeDefinition + Int64Value: MessageTypeDefinition + ListValue: MessageTypeDefinition + MessageOptions: MessageTypeDefinition + MethodDescriptorProto: MessageTypeDefinition + MethodOptions: MessageTypeDefinition + NullValue: EnumTypeDefinition + OneofDescriptorProto: MessageTypeDefinition + OneofOptions: MessageTypeDefinition + ServiceDescriptorProto: MessageTypeDefinition + ServiceOptions: MessageTypeDefinition + SourceCodeInfo: MessageTypeDefinition + StringValue: MessageTypeDefinition + Struct: MessageTypeDefinition + Timestamp: MessageTypeDefinition + UInt32Value: MessageTypeDefinition + UInt64Value: MessageTypeDefinition + UninterpretedOption: MessageTypeDefinition + Value: MessageTypeDefinition + } + } + udpa: { + annotations: { + FieldMigrateAnnotation: MessageTypeDefinition + FieldSecurityAnnotation: MessageTypeDefinition + FileMigrateAnnotation: MessageTypeDefinition + MigrateAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition + } + } + validate: { + AnyRules: MessageTypeDefinition + BoolRules: MessageTypeDefinition + BytesRules: MessageTypeDefinition + DoubleRules: MessageTypeDefinition + DurationRules: MessageTypeDefinition + EnumRules: MessageTypeDefinition + FieldRules: MessageTypeDefinition + Fixed32Rules: MessageTypeDefinition + Fixed64Rules: MessageTypeDefinition + FloatRules: MessageTypeDefinition + Int32Rules: MessageTypeDefinition + Int64Rules: MessageTypeDefinition + KnownRegex: EnumTypeDefinition + MapRules: MessageTypeDefinition + MessageRules: MessageTypeDefinition + RepeatedRules: MessageTypeDefinition + SFixed32Rules: MessageTypeDefinition + SFixed64Rules: MessageTypeDefinition + SInt32Rules: MessageTypeDefinition + SInt64Rules: MessageTypeDefinition + StringRules: MessageTypeDefinition + TimestampRules: MessageTypeDefinition + UInt32Rules: MessageTypeDefinition + UInt64Rules: MessageTypeDefinition + } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + Authority: MessageTypeDefinition + CollectionEntry: MessageTypeDefinition + ContextParams: MessageTypeDefinition + ResourceLocator: MessageTypeDefinition + } + } + } +} + diff --git a/packages/grpc-js-xds/src/generated/endpoint.ts b/packages/grpc-js-xds/src/generated/endpoint.ts index 33d5872ef..9a87bc9a5 100644 --- a/packages/grpc-js-xds/src/generated/endpoint.ts +++ b/packages/grpc-js-xds/src/generated/endpoint.ts @@ -1,5 +1,5 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; type SubtypeConstructor any, Subtype> = { @@ -10,18 +10,22 @@ export interface ProtoGrpcType { envoy: { annotations: { } - api: { - v2: { - ClusterLoadAssignment: MessageTypeDefinition - core: { + config: { + core: { + v3: { Address: MessageTypeDefinition + AggregatedConfigSource: MessageTypeDefinition + ApiConfigSource: MessageTypeDefinition + ApiVersion: EnumTypeDefinition AsyncDataSource: MessageTypeDefinition BackoffStrategy: MessageTypeDefinition BindConfig: MessageTypeDefinition BuildVersion: MessageTypeDefinition CidrRange: MessageTypeDefinition + ConfigSource: MessageTypeDefinition ControlPlane: MessageTypeDefinition DataSource: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition EventServiceConfig: MessageTypeDefinition Extension: MessageTypeDefinition GrpcService: MessageTypeDefinition @@ -35,6 +39,8 @@ export interface ProtoGrpcType { Metadata: MessageTypeDefinition Node: MessageTypeDefinition Pipe: MessageTypeDefinition + QueryParameter: MessageTypeDefinition + RateLimitSettings: MessageTypeDefinition RemoteDataSource: MessageTypeDefinition RequestMethod: EnumTypeDefinition RetryPolicy: MessageTypeDefinition @@ -42,42 +48,48 @@ export interface ProtoGrpcType { RuntimeDouble: MessageTypeDefinition RuntimeFeatureFlag: MessageTypeDefinition RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition RuntimeUInt32: MessageTypeDefinition + SelfConfigSource: MessageTypeDefinition SocketAddress: MessageTypeDefinition SocketOption: MessageTypeDefinition TcpKeepalive: MessageTypeDefinition TrafficDirection: EnumTypeDefinition TransportSocket: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition } - endpoint: { + } + endpoint: { + v3: { + ClusterLoadAssignment: MessageTypeDefinition Endpoint: MessageTypeDefinition LbEndpoint: MessageTypeDefinition + LedsClusterLocalityConfig: MessageTypeDefinition LocalityLbEndpoints: MessageTypeDefinition } } } type: { - CodecClientType: EnumTypeDefinition - DoubleRange: MessageTypeDefinition - FractionalPercent: MessageTypeDefinition - Int32Range: MessageTypeDefinition - Int64Range: MessageTypeDefinition - Percent: MessageTypeDefinition - SemanticVersion: MessageTypeDefinition matcher: { - ListStringMatcher: MessageTypeDefinition - RegexMatchAndSubstitute: MessageTypeDefinition - RegexMatcher: MessageTypeDefinition - StringMatcher: MessageTypeDefinition + v3: { + ListStringMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + } + } + v3: { + CodecClientType: EnumTypeDefinition + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition } } } google: { - api: { - CustomHttpPattern: MessageTypeDefinition - Http: MessageTypeDefinition - HttpRule: MessageTypeDefinition - } protobuf: { Any: MessageTypeDefinition BoolValue: MessageTypeDefinition @@ -125,6 +137,7 @@ export interface ProtoGrpcType { MigrateAnnotation: MessageTypeDefinition PackageVersionStatus: EnumTypeDefinition StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition } } validate: { @@ -153,5 +166,22 @@ export interface ProtoGrpcType { UInt32Rules: MessageTypeDefinition UInt64Rules: MessageTypeDefinition } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + Authority: MessageTypeDefinition + ContextParams: MessageTypeDefinition + } + } + } } diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/BootstrapConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/BootstrapConfigDump.ts new file mode 100644 index 000000000..d47f00ef3 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/BootstrapConfigDump.ts @@ -0,0 +1,32 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Bootstrap as _envoy_config_bootstrap_v3_Bootstrap, Bootstrap__Output as _envoy_config_bootstrap_v3_Bootstrap__Output } from '../../../envoy/config/bootstrap/v3/Bootstrap'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; + +/** + * This message describes the bootstrap configuration that Envoy was started with. This includes + * any CLI overrides that were merged. Bootstrap configuration information can be used to recreate + * the static portions of an Envoy configuration by reusing the output as the bootstrap + * configuration for another Envoy. + */ +export interface BootstrapConfigDump { + 'bootstrap'?: (_envoy_config_bootstrap_v3_Bootstrap | null); + /** + * The timestamp when the BootstrapConfig was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); +} + +/** + * This message describes the bootstrap configuration that Envoy was started with. This includes + * any CLI overrides that were merged. Bootstrap configuration information can be used to recreate + * the static portions of an Envoy configuration by reusing the output as the bootstrap + * configuration for another Envoy. + */ +export interface BootstrapConfigDump__Output { + 'bootstrap': (_envoy_config_bootstrap_v3_Bootstrap__Output | null); + /** + * The timestamp when the BootstrapConfig was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/ClientResourceStatus.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ClientResourceStatus.ts new file mode 100644 index 000000000..31c3a813a --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ClientResourceStatus.ts @@ -0,0 +1,34 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +/** + * Resource status from the view of a xDS client, which tells the synchronization + * status between the xDS client and the xDS server. + */ +export enum ClientResourceStatus { + /** + * Resource status is not available/unknown. + */ + UNKNOWN = 0, + /** + * Client requested this resource but hasn't received any update from management + * server. The client will not fail requests, but will queue them until update + * arrives or the client times out waiting for the resource. + */ + REQUESTED = 1, + /** + * This resource has been requested by the client but has either not been + * delivered by the server or was previously delivered by the server and then + * subsequently removed from resources provided by the server. For more + * information, please refer to the :ref:`"Knowing When a Requested Resource + * Does Not Exist" ` section. + */ + DOES_NOT_EXIST = 2, + /** + * Client received this resource and replied with ACK. + */ + ACKED = 3, + /** + * Client received this resource and replied with NACK. + */ + NACKED = 4, +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/ClustersConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ClustersConfigDump.ts new file mode 100644 index 000000000..ab7c528bf --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ClustersConfigDump.ts @@ -0,0 +1,164 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { UpdateFailureState as _envoy_admin_v3_UpdateFailureState, UpdateFailureState__Output as _envoy_admin_v3_UpdateFailureState__Output } from '../../../envoy/admin/v3/UpdateFailureState'; +import type { ClientResourceStatus as _envoy_admin_v3_ClientResourceStatus } from '../../../envoy/admin/v3/ClientResourceStatus'; + +/** + * Describes a dynamically loaded cluster via the CDS API. + * [#next-free-field: 6] + */ +export interface _envoy_admin_v3_ClustersConfigDump_DynamicCluster { + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time + * that the cluster was loaded. In the future, discrete per-cluster versions may be supported by + * the API. + */ + 'version_info'?: (string); + /** + * The cluster config. + */ + 'cluster'?: (_google_protobuf_Any | null); + /** + * The timestamp when the Cluster was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state'?: (_envoy_admin_v3_UpdateFailureState | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status'?: (_envoy_admin_v3_ClientResourceStatus | keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * Describes a dynamically loaded cluster via the CDS API. + * [#next-free-field: 6] + */ +export interface _envoy_admin_v3_ClustersConfigDump_DynamicCluster__Output { + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time + * that the cluster was loaded. In the future, discrete per-cluster versions may be supported by + * the API. + */ + 'version_info': (string); + /** + * The cluster config. + */ + 'cluster': (_google_protobuf_Any__Output | null); + /** + * The timestamp when the Cluster was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state': (_envoy_admin_v3_UpdateFailureState__Output | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status': (keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * Describes a statically loaded cluster. + */ +export interface _envoy_admin_v3_ClustersConfigDump_StaticCluster { + /** + * The cluster config. + */ + 'cluster'?: (_google_protobuf_Any | null); + /** + * The timestamp when the Cluster was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); +} + +/** + * Describes a statically loaded cluster. + */ +export interface _envoy_admin_v3_ClustersConfigDump_StaticCluster__Output { + /** + * The cluster config. + */ + 'cluster': (_google_protobuf_Any__Output | null); + /** + * The timestamp when the Cluster was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); +} + +/** + * Envoy's cluster manager fills this message with all currently known clusters. Cluster + * configuration information can be used to recreate an Envoy configuration by populating all + * clusters as static clusters or by returning them in a CDS response. + */ +export interface ClustersConfigDump { + /** + * This is the :ref:`version_info ` in the + * last processed CDS discovery response. If there are only static bootstrap clusters, this field + * will be "". + */ + 'version_info'?: (string); + /** + * The statically loaded cluster configs. + */ + 'static_clusters'?: (_envoy_admin_v3_ClustersConfigDump_StaticCluster)[]; + /** + * The dynamically loaded active clusters. These are clusters that are available to service + * data plane traffic. + */ + 'dynamic_active_clusters'?: (_envoy_admin_v3_ClustersConfigDump_DynamicCluster)[]; + /** + * The dynamically loaded warming clusters. These are clusters that are currently undergoing + * warming in preparation to service data plane traffic. Note that if attempting to recreate an + * Envoy configuration from a configuration dump, the warming clusters should generally be + * discarded. + */ + 'dynamic_warming_clusters'?: (_envoy_admin_v3_ClustersConfigDump_DynamicCluster)[]; +} + +/** + * Envoy's cluster manager fills this message with all currently known clusters. Cluster + * configuration information can be used to recreate an Envoy configuration by populating all + * clusters as static clusters or by returning them in a CDS response. + */ +export interface ClustersConfigDump__Output { + /** + * This is the :ref:`version_info ` in the + * last processed CDS discovery response. If there are only static bootstrap clusters, this field + * will be "". + */ + 'version_info': (string); + /** + * The statically loaded cluster configs. + */ + 'static_clusters': (_envoy_admin_v3_ClustersConfigDump_StaticCluster__Output)[]; + /** + * The dynamically loaded active clusters. These are clusters that are available to service + * data plane traffic. + */ + 'dynamic_active_clusters': (_envoy_admin_v3_ClustersConfigDump_DynamicCluster__Output)[]; + /** + * The dynamically loaded warming clusters. These are clusters that are currently undergoing + * warming in preparation to service data plane traffic. Note that if attempting to recreate an + * Envoy configuration from a configuration dump, the warming clusters should generally be + * discarded. + */ + 'dynamic_warming_clusters': (_envoy_admin_v3_ClustersConfigDump_DynamicCluster__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/ConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ConfigDump.ts new file mode 100644 index 000000000..8a0ab65c2 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ConfigDump.ts @@ -0,0 +1,65 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; + +/** + * The :ref:`/config_dump ` admin endpoint uses this wrapper + * message to maintain and serve arbitrary configuration information from any component in Envoy. + */ +export interface ConfigDump { + /** + * This list is serialized and dumped in its entirety at the + * :ref:`/config_dump ` endpoint. + * + * The following configurations are currently supported and will be dumped in the order given + * below: + * + * * *bootstrap*: :ref:`BootstrapConfigDump ` + * * *clusters*: :ref:`ClustersConfigDump ` + * * *endpoints*: :ref:`EndpointsConfigDump ` + * * *listeners*: :ref:`ListenersConfigDump ` + * * *scoped_routes*: :ref:`ScopedRoutesConfigDump ` + * * *routes*: :ref:`RoutesConfigDump ` + * * *secrets*: :ref:`SecretsConfigDump ` + * + * EDS Configuration will only be dumped by using parameter `?include_eds` + * + * You can filter output with the resource and mask query parameters. + * See :ref:`/config_dump?resource={} `, + * :ref:`/config_dump?mask={} `, + * or :ref:`/config_dump?resource={},mask={} + * ` for more information. + */ + 'configs'?: (_google_protobuf_Any)[]; +} + +/** + * The :ref:`/config_dump ` admin endpoint uses this wrapper + * message to maintain and serve arbitrary configuration information from any component in Envoy. + */ +export interface ConfigDump__Output { + /** + * This list is serialized and dumped in its entirety at the + * :ref:`/config_dump ` endpoint. + * + * The following configurations are currently supported and will be dumped in the order given + * below: + * + * * *bootstrap*: :ref:`BootstrapConfigDump ` + * * *clusters*: :ref:`ClustersConfigDump ` + * * *endpoints*: :ref:`EndpointsConfigDump ` + * * *listeners*: :ref:`ListenersConfigDump ` + * * *scoped_routes*: :ref:`ScopedRoutesConfigDump ` + * * *routes*: :ref:`RoutesConfigDump ` + * * *secrets*: :ref:`SecretsConfigDump ` + * + * EDS Configuration will only be dumped by using parameter `?include_eds` + * + * You can filter output with the resource and mask query parameters. + * See :ref:`/config_dump?resource={} `, + * :ref:`/config_dump?mask={} `, + * or :ref:`/config_dump?resource={},mask={} + * ` for more information. + */ + 'configs': (_google_protobuf_Any__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/EndpointsConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/EndpointsConfigDump.ts new file mode 100644 index 000000000..d68b27e7c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/EndpointsConfigDump.ts @@ -0,0 +1,126 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { UpdateFailureState as _envoy_admin_v3_UpdateFailureState, UpdateFailureState__Output as _envoy_admin_v3_UpdateFailureState__Output } from '../../../envoy/admin/v3/UpdateFailureState'; +import type { ClientResourceStatus as _envoy_admin_v3_ClientResourceStatus } from '../../../envoy/admin/v3/ClientResourceStatus'; + +/** + * [#next-free-field: 6] + */ +export interface _envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig { + /** + * [#not-implemented-hide:] This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time that + * the endpoint configuration was loaded. + */ + 'version_info'?: (string); + /** + * The endpoint config. + */ + 'endpoint_config'?: (_google_protobuf_Any | null); + /** + * [#not-implemented-hide:] The timestamp when the Endpoint was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state'?: (_envoy_admin_v3_UpdateFailureState | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status'?: (_envoy_admin_v3_ClientResourceStatus | keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * [#next-free-field: 6] + */ +export interface _envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig__Output { + /** + * [#not-implemented-hide:] This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time that + * the endpoint configuration was loaded. + */ + 'version_info': (string); + /** + * The endpoint config. + */ + 'endpoint_config': (_google_protobuf_Any__Output | null); + /** + * [#not-implemented-hide:] The timestamp when the Endpoint was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state': (_envoy_admin_v3_UpdateFailureState__Output | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status': (keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +export interface _envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig { + /** + * The endpoint config. + */ + 'endpoint_config'?: (_google_protobuf_Any | null); + /** + * [#not-implemented-hide:] The timestamp when the Endpoint was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); +} + +export interface _envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig__Output { + /** + * The endpoint config. + */ + 'endpoint_config': (_google_protobuf_Any__Output | null); + /** + * [#not-implemented-hide:] The timestamp when the Endpoint was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); +} + +/** + * Envoy's admin fill this message with all currently known endpoints. Endpoint + * configuration information can be used to recreate an Envoy configuration by populating all + * endpoints as static endpoints or by returning them in an EDS response. + */ +export interface EndpointsConfigDump { + /** + * The statically loaded endpoint configs. + */ + 'static_endpoint_configs'?: (_envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig)[]; + /** + * The dynamically loaded endpoint configs. + */ + 'dynamic_endpoint_configs'?: (_envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig)[]; +} + +/** + * Envoy's admin fill this message with all currently known endpoints. Endpoint + * configuration information can be used to recreate an Envoy configuration by populating all + * endpoints as static endpoints or by returning them in an EDS response. + */ +export interface EndpointsConfigDump__Output { + /** + * The statically loaded endpoint configs. + */ + 'static_endpoint_configs': (_envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig__Output)[]; + /** + * The dynamically loaded endpoint configs. + */ + 'dynamic_endpoint_configs': (_envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/ListenersConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ListenersConfigDump.ts new file mode 100644 index 000000000..745abedae --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ListenersConfigDump.ts @@ -0,0 +1,198 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { UpdateFailureState as _envoy_admin_v3_UpdateFailureState, UpdateFailureState__Output as _envoy_admin_v3_UpdateFailureState__Output } from '../../../envoy/admin/v3/UpdateFailureState'; +import type { ClientResourceStatus as _envoy_admin_v3_ClientResourceStatus } from '../../../envoy/admin/v3/ClientResourceStatus'; + +/** + * Describes a dynamically loaded listener via the LDS API. + * [#next-free-field: 7] + */ +export interface _envoy_admin_v3_ListenersConfigDump_DynamicListener { + /** + * The name or unique id of this listener, pulled from the DynamicListenerState config. + */ + 'name'?: (string); + /** + * The listener state for any active listener by this name. + * These are listeners that are available to service data plane traffic. + */ + 'active_state'?: (_envoy_admin_v3_ListenersConfigDump_DynamicListenerState | null); + /** + * The listener state for any warming listener by this name. + * These are listeners that are currently undergoing warming in preparation to service data + * plane traffic. Note that if attempting to recreate an Envoy configuration from a + * configuration dump, the warming listeners should generally be discarded. + */ + 'warming_state'?: (_envoy_admin_v3_ListenersConfigDump_DynamicListenerState | null); + /** + * The listener state for any draining listener by this name. + * These are listeners that are currently undergoing draining in preparation to stop servicing + * data plane traffic. Note that if attempting to recreate an Envoy configuration from a + * configuration dump, the draining listeners should generally be discarded. + */ + 'draining_state'?: (_envoy_admin_v3_ListenersConfigDump_DynamicListenerState | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + */ + 'error_state'?: (_envoy_admin_v3_UpdateFailureState | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status'?: (_envoy_admin_v3_ClientResourceStatus | keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * Describes a dynamically loaded listener via the LDS API. + * [#next-free-field: 7] + */ +export interface _envoy_admin_v3_ListenersConfigDump_DynamicListener__Output { + /** + * The name or unique id of this listener, pulled from the DynamicListenerState config. + */ + 'name': (string); + /** + * The listener state for any active listener by this name. + * These are listeners that are available to service data plane traffic. + */ + 'active_state': (_envoy_admin_v3_ListenersConfigDump_DynamicListenerState__Output | null); + /** + * The listener state for any warming listener by this name. + * These are listeners that are currently undergoing warming in preparation to service data + * plane traffic. Note that if attempting to recreate an Envoy configuration from a + * configuration dump, the warming listeners should generally be discarded. + */ + 'warming_state': (_envoy_admin_v3_ListenersConfigDump_DynamicListenerState__Output | null); + /** + * The listener state for any draining listener by this name. + * These are listeners that are currently undergoing draining in preparation to stop servicing + * data plane traffic. Note that if attempting to recreate an Envoy configuration from a + * configuration dump, the draining listeners should generally be discarded. + */ + 'draining_state': (_envoy_admin_v3_ListenersConfigDump_DynamicListenerState__Output | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + */ + 'error_state': (_envoy_admin_v3_UpdateFailureState__Output | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status': (keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +export interface _envoy_admin_v3_ListenersConfigDump_DynamicListenerState { + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time + * that the listener was loaded. In the future, discrete per-listener versions may be supported + * by the API. + */ + 'version_info'?: (string); + /** + * The listener config. + */ + 'listener'?: (_google_protobuf_Any | null); + /** + * The timestamp when the Listener was last successfully updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); +} + +export interface _envoy_admin_v3_ListenersConfigDump_DynamicListenerState__Output { + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time + * that the listener was loaded. In the future, discrete per-listener versions may be supported + * by the API. + */ + 'version_info': (string); + /** + * The listener config. + */ + 'listener': (_google_protobuf_Any__Output | null); + /** + * The timestamp when the Listener was last successfully updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); +} + +/** + * Describes a statically loaded listener. + */ +export interface _envoy_admin_v3_ListenersConfigDump_StaticListener { + /** + * The listener config. + */ + 'listener'?: (_google_protobuf_Any | null); + /** + * The timestamp when the Listener was last successfully updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); +} + +/** + * Describes a statically loaded listener. + */ +export interface _envoy_admin_v3_ListenersConfigDump_StaticListener__Output { + /** + * The listener config. + */ + 'listener': (_google_protobuf_Any__Output | null); + /** + * The timestamp when the Listener was last successfully updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); +} + +/** + * Envoy's listener manager fills this message with all currently known listeners. Listener + * configuration information can be used to recreate an Envoy configuration by populating all + * listeners as static listeners or by returning them in a LDS response. + */ +export interface ListenersConfigDump { + /** + * This is the :ref:`version_info ` in the + * last processed LDS discovery response. If there are only static bootstrap listeners, this field + * will be "". + */ + 'version_info'?: (string); + /** + * The statically loaded listener configs. + */ + 'static_listeners'?: (_envoy_admin_v3_ListenersConfigDump_StaticListener)[]; + /** + * State for any warming, active, or draining listeners. + */ + 'dynamic_listeners'?: (_envoy_admin_v3_ListenersConfigDump_DynamicListener)[]; +} + +/** + * Envoy's listener manager fills this message with all currently known listeners. Listener + * configuration information can be used to recreate an Envoy configuration by populating all + * listeners as static listeners or by returning them in a LDS response. + */ +export interface ListenersConfigDump__Output { + /** + * This is the :ref:`version_info ` in the + * last processed LDS discovery response. If there are only static bootstrap listeners, this field + * will be "". + */ + 'version_info': (string); + /** + * The statically loaded listener configs. + */ + 'static_listeners': (_envoy_admin_v3_ListenersConfigDump_StaticListener__Output)[]; + /** + * State for any warming, active, or draining listeners. + */ + 'dynamic_listeners': (_envoy_admin_v3_ListenersConfigDump_DynamicListener__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/RoutesConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/RoutesConfigDump.ts new file mode 100644 index 000000000..2a62e9b74 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/RoutesConfigDump.ts @@ -0,0 +1,130 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { UpdateFailureState as _envoy_admin_v3_UpdateFailureState, UpdateFailureState__Output as _envoy_admin_v3_UpdateFailureState__Output } from '../../../envoy/admin/v3/UpdateFailureState'; +import type { ClientResourceStatus as _envoy_admin_v3_ClientResourceStatus } from '../../../envoy/admin/v3/ClientResourceStatus'; + +/** + * [#next-free-field: 6] + */ +export interface _envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig { + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time that + * the route configuration was loaded. + */ + 'version_info'?: (string); + /** + * The route config. + */ + 'route_config'?: (_google_protobuf_Any | null); + /** + * The timestamp when the Route was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state'?: (_envoy_admin_v3_UpdateFailureState | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status'?: (_envoy_admin_v3_ClientResourceStatus | keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * [#next-free-field: 6] + */ +export interface _envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig__Output { + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time that + * the route configuration was loaded. + */ + 'version_info': (string); + /** + * The route config. + */ + 'route_config': (_google_protobuf_Any__Output | null); + /** + * The timestamp when the Route was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state': (_envoy_admin_v3_UpdateFailureState__Output | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status': (keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +export interface _envoy_admin_v3_RoutesConfigDump_StaticRouteConfig { + /** + * The route config. + */ + 'route_config'?: (_google_protobuf_Any | null); + /** + * The timestamp when the Route was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); +} + +export interface _envoy_admin_v3_RoutesConfigDump_StaticRouteConfig__Output { + /** + * The route config. + */ + 'route_config': (_google_protobuf_Any__Output | null); + /** + * The timestamp when the Route was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); +} + +/** + * Envoy's RDS implementation fills this message with all currently loaded routes, as described by + * their RouteConfiguration objects. Static routes that are either defined in the bootstrap configuration + * or defined inline while configuring listeners are separated from those configured dynamically via RDS. + * Route configuration information can be used to recreate an Envoy configuration by populating all routes + * as static routes or by returning them in RDS responses. + */ +export interface RoutesConfigDump { + /** + * The statically loaded route configs. + */ + 'static_route_configs'?: (_envoy_admin_v3_RoutesConfigDump_StaticRouteConfig)[]; + /** + * The dynamically loaded route configs. + */ + 'dynamic_route_configs'?: (_envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig)[]; +} + +/** + * Envoy's RDS implementation fills this message with all currently loaded routes, as described by + * their RouteConfiguration objects. Static routes that are either defined in the bootstrap configuration + * or defined inline while configuring listeners are separated from those configured dynamically via RDS. + * Route configuration information can be used to recreate an Envoy configuration by populating all routes + * as static routes or by returning them in RDS responses. + */ +export interface RoutesConfigDump__Output { + /** + * The statically loaded route configs. + */ + 'static_route_configs': (_envoy_admin_v3_RoutesConfigDump_StaticRouteConfig__Output)[]; + /** + * The dynamically loaded route configs. + */ + 'dynamic_route_configs': (_envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/ScopedRoutesConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ScopedRoutesConfigDump.ts new file mode 100644 index 000000000..f271635bc --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/ScopedRoutesConfigDump.ts @@ -0,0 +1,144 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { UpdateFailureState as _envoy_admin_v3_UpdateFailureState, UpdateFailureState__Output as _envoy_admin_v3_UpdateFailureState__Output } from '../../../envoy/admin/v3/UpdateFailureState'; +import type { ClientResourceStatus as _envoy_admin_v3_ClientResourceStatus } from '../../../envoy/admin/v3/ClientResourceStatus'; + +/** + * [#next-free-field: 7] + */ +export interface _envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs { + /** + * The name assigned to the scoped route configurations. + */ + 'name'?: (string); + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time that + * the scoped routes configuration was loaded. + */ + 'version_info'?: (string); + /** + * The scoped route configurations. + */ + 'scoped_route_configs'?: (_google_protobuf_Any)[]; + /** + * The timestamp when the scoped route config set was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state'?: (_envoy_admin_v3_UpdateFailureState | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status'?: (_envoy_admin_v3_ClientResourceStatus | keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * [#next-free-field: 7] + */ +export interface _envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs__Output { + /** + * The name assigned to the scoped route configurations. + */ + 'name': (string); + /** + * This is the per-resource version information. This version is currently taken from the + * :ref:`version_info ` field at the time that + * the scoped routes configuration was loaded. + */ + 'version_info': (string); + /** + * The scoped route configurations. + */ + 'scoped_route_configs': (_google_protobuf_Any__Output)[]; + /** + * The timestamp when the scoped route config set was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state': (_envoy_admin_v3_UpdateFailureState__Output | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status': (keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +export interface _envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs { + /** + * The name assigned to the scoped route configurations. + */ + 'name'?: (string); + /** + * The scoped route configurations. + */ + 'scoped_route_configs'?: (_google_protobuf_Any)[]; + /** + * The timestamp when the scoped route config set was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); +} + +export interface _envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs__Output { + /** + * The name assigned to the scoped route configurations. + */ + 'name': (string); + /** + * The scoped route configurations. + */ + 'scoped_route_configs': (_google_protobuf_Any__Output)[]; + /** + * The timestamp when the scoped route config set was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); +} + +/** + * Envoy's scoped RDS implementation fills this message with all currently loaded route + * configuration scopes (defined via ScopedRouteConfigurationsSet protos). This message lists both + * the scopes defined inline with the higher order object (i.e., the HttpConnectionManager) and the + * dynamically obtained scopes via the SRDS API. + */ +export interface ScopedRoutesConfigDump { + /** + * The statically loaded scoped route configs. + */ + 'inline_scoped_route_configs'?: (_envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs)[]; + /** + * The dynamically loaded scoped route configs. + */ + 'dynamic_scoped_route_configs'?: (_envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs)[]; +} + +/** + * Envoy's scoped RDS implementation fills this message with all currently loaded route + * configuration scopes (defined via ScopedRouteConfigurationsSet protos). This message lists both + * the scopes defined inline with the higher order object (i.e., the HttpConnectionManager) and the + * dynamically obtained scopes via the SRDS API. + */ +export interface ScopedRoutesConfigDump__Output { + /** + * The statically loaded scoped route configs. + */ + 'inline_scoped_route_configs': (_envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs__Output)[]; + /** + * The dynamically loaded scoped route configs. + */ + 'dynamic_scoped_route_configs': (_envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/SecretsConfigDump.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/SecretsConfigDump.ts new file mode 100644 index 000000000..21921edec --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/SecretsConfigDump.ts @@ -0,0 +1,162 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { UpdateFailureState as _envoy_admin_v3_UpdateFailureState, UpdateFailureState__Output as _envoy_admin_v3_UpdateFailureState__Output } from '../../../envoy/admin/v3/UpdateFailureState'; +import type { ClientResourceStatus as _envoy_admin_v3_ClientResourceStatus } from '../../../envoy/admin/v3/ClientResourceStatus'; + +/** + * DynamicSecret contains secret information fetched via SDS. + * [#next-free-field: 7] + */ +export interface _envoy_admin_v3_SecretsConfigDump_DynamicSecret { + /** + * The name assigned to the secret. + */ + 'name'?: (string); + /** + * This is the per-resource version information. + */ + 'version_info'?: (string); + /** + * The timestamp when the secret was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); + /** + * The actual secret information. + * Security sensitive information is redacted (replaced with "[redacted]") for + * private keys and passwords in TLS certificates. + */ + 'secret'?: (_google_protobuf_Any | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state'?: (_envoy_admin_v3_UpdateFailureState | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status'?: (_envoy_admin_v3_ClientResourceStatus | keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * DynamicSecret contains secret information fetched via SDS. + * [#next-free-field: 7] + */ +export interface _envoy_admin_v3_SecretsConfigDump_DynamicSecret__Output { + /** + * The name assigned to the secret. + */ + 'name': (string); + /** + * This is the per-resource version information. + */ + 'version_info': (string); + /** + * The timestamp when the secret was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); + /** + * The actual secret information. + * Security sensitive information is redacted (replaced with "[redacted]") for + * private keys and passwords in TLS certificates. + */ + 'secret': (_google_protobuf_Any__Output | null); + /** + * Set if the last update failed, cleared after the next successful update. + * The *error_state* field contains the rejected version of this particular + * resource along with the reason and timestamp. For successfully updated or + * acknowledged resource, this field should be empty. + * [#not-implemented-hide:] + */ + 'error_state': (_envoy_admin_v3_UpdateFailureState__Output | null); + /** + * The client status of this resource. + * [#not-implemented-hide:] + */ + 'client_status': (keyof typeof _envoy_admin_v3_ClientResourceStatus); +} + +/** + * StaticSecret specifies statically loaded secret in bootstrap. + */ +export interface _envoy_admin_v3_SecretsConfigDump_StaticSecret { + /** + * The name assigned to the secret. + */ + 'name'?: (string); + /** + * The timestamp when the secret was last updated. + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); + /** + * The actual secret information. + * Security sensitive information is redacted (replaced with "[redacted]") for + * private keys and passwords in TLS certificates. + */ + 'secret'?: (_google_protobuf_Any | null); +} + +/** + * StaticSecret specifies statically loaded secret in bootstrap. + */ +export interface _envoy_admin_v3_SecretsConfigDump_StaticSecret__Output { + /** + * The name assigned to the secret. + */ + 'name': (string); + /** + * The timestamp when the secret was last updated. + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); + /** + * The actual secret information. + * Security sensitive information is redacted (replaced with "[redacted]") for + * private keys and passwords in TLS certificates. + */ + 'secret': (_google_protobuf_Any__Output | null); +} + +/** + * Envoys SDS implementation fills this message with all secrets fetched dynamically via SDS. + */ +export interface SecretsConfigDump { + /** + * The statically loaded secrets. + */ + 'static_secrets'?: (_envoy_admin_v3_SecretsConfigDump_StaticSecret)[]; + /** + * The dynamically loaded active secrets. These are secrets that are available to service + * clusters or listeners. + */ + 'dynamic_active_secrets'?: (_envoy_admin_v3_SecretsConfigDump_DynamicSecret)[]; + /** + * The dynamically loaded warming secrets. These are secrets that are currently undergoing + * warming in preparation to service clusters or listeners. + */ + 'dynamic_warming_secrets'?: (_envoy_admin_v3_SecretsConfigDump_DynamicSecret)[]; +} + +/** + * Envoys SDS implementation fills this message with all secrets fetched dynamically via SDS. + */ +export interface SecretsConfigDump__Output { + /** + * The statically loaded secrets. + */ + 'static_secrets': (_envoy_admin_v3_SecretsConfigDump_StaticSecret__Output)[]; + /** + * The dynamically loaded active secrets. These are secrets that are available to service + * clusters or listeners. + */ + 'dynamic_active_secrets': (_envoy_admin_v3_SecretsConfigDump_DynamicSecret__Output)[]; + /** + * The dynamically loaded warming secrets. These are secrets that are currently undergoing + * warming in preparation to service clusters or listeners. + */ + 'dynamic_warming_secrets': (_envoy_admin_v3_SecretsConfigDump_DynamicSecret__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/admin/v3/UpdateFailureState.ts b/packages/grpc-js-xds/src/generated/envoy/admin/v3/UpdateFailureState.ts new file mode 100644 index 000000000..b98e8cd4d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/admin/v3/UpdateFailureState.ts @@ -0,0 +1,46 @@ +// Original file: deps/envoy-api/envoy/admin/v3/config_dump.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; + +export interface UpdateFailureState { + /** + * What the component configuration would have been if the update had succeeded. + * This field may not be populated by xDS clients due to storage overhead. + */ + 'failed_configuration'?: (_google_protobuf_Any | null); + /** + * Time of the latest failed update attempt. + */ + 'last_update_attempt'?: (_google_protobuf_Timestamp | null); + /** + * Details about the last failed update attempt. + */ + 'details'?: (string); + /** + * This is the version of the rejected resource. + * [#not-implemented-hide:] + */ + 'version_info'?: (string); +} + +export interface UpdateFailureState__Output { + /** + * What the component configuration would have been if the update had succeeded. + * This field may not be populated by xDS clients due to storage overhead. + */ + 'failed_configuration': (_google_protobuf_Any__Output | null); + /** + * Time of the latest failed update attempt. + */ + 'last_update_attempt': (_google_protobuf_Timestamp__Output | null); + /** + * Details about the last failed update attempt. + */ + 'details': (string); + /** + * This is the version of the rejected resource. + * [#not-implemented-hide:] + */ + 'version_info': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/Cluster.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/Cluster.ts deleted file mode 100644 index f077d2edc..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/Cluster.ts +++ /dev/null @@ -1,1679 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../google/protobuf/UInt32Value'; -import type { Address as _envoy_api_v2_core_Address, Address__Output as _envoy_api_v2_core_Address__Output } from '../../../envoy/api/v2/core/Address'; -import type { HealthCheck as _envoy_api_v2_core_HealthCheck, HealthCheck__Output as _envoy_api_v2_core_HealthCheck__Output } from '../../../envoy/api/v2/core/HealthCheck'; -import type { CircuitBreakers as _envoy_api_v2_cluster_CircuitBreakers, CircuitBreakers__Output as _envoy_api_v2_cluster_CircuitBreakers__Output } from '../../../envoy/api/v2/cluster/CircuitBreakers'; -import type { UpstreamTlsContext as _envoy_api_v2_auth_UpstreamTlsContext, UpstreamTlsContext__Output as _envoy_api_v2_auth_UpstreamTlsContext__Output } from '../../../envoy/api/v2/auth/UpstreamTlsContext'; -import type { Http1ProtocolOptions as _envoy_api_v2_core_Http1ProtocolOptions, Http1ProtocolOptions__Output as _envoy_api_v2_core_Http1ProtocolOptions__Output } from '../../../envoy/api/v2/core/Http1ProtocolOptions'; -import type { Http2ProtocolOptions as _envoy_api_v2_core_Http2ProtocolOptions, Http2ProtocolOptions__Output as _envoy_api_v2_core_Http2ProtocolOptions__Output } from '../../../envoy/api/v2/core/Http2ProtocolOptions'; -import type { OutlierDetection as _envoy_api_v2_cluster_OutlierDetection, OutlierDetection__Output as _envoy_api_v2_cluster_OutlierDetection__Output } from '../../../envoy/api/v2/cluster/OutlierDetection'; -import type { BindConfig as _envoy_api_v2_core_BindConfig, BindConfig__Output as _envoy_api_v2_core_BindConfig__Output } from '../../../envoy/api/v2/core/BindConfig'; -import type { TransportSocket as _envoy_api_v2_core_TransportSocket, TransportSocket__Output as _envoy_api_v2_core_TransportSocket__Output } from '../../../envoy/api/v2/core/TransportSocket'; -import type { Metadata as _envoy_api_v2_core_Metadata, Metadata__Output as _envoy_api_v2_core_Metadata__Output } from '../../../envoy/api/v2/core/Metadata'; -import type { HttpProtocolOptions as _envoy_api_v2_core_HttpProtocolOptions, HttpProtocolOptions__Output as _envoy_api_v2_core_HttpProtocolOptions__Output } from '../../../envoy/api/v2/core/HttpProtocolOptions'; -import type { UpstreamConnectionOptions as _envoy_api_v2_UpstreamConnectionOptions, UpstreamConnectionOptions__Output as _envoy_api_v2_UpstreamConnectionOptions__Output } from '../../../envoy/api/v2/UpstreamConnectionOptions'; -import type { ClusterLoadAssignment as _envoy_api_v2_ClusterLoadAssignment, ClusterLoadAssignment__Output as _envoy_api_v2_ClusterLoadAssignment__Output } from '../../../envoy/api/v2/ClusterLoadAssignment'; -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; -import type { Filter as _envoy_api_v2_cluster_Filter, Filter__Output as _envoy_api_v2_cluster_Filter__Output } from '../../../envoy/api/v2/cluster/Filter'; -import type { LoadBalancingPolicy as _envoy_api_v2_LoadBalancingPolicy, LoadBalancingPolicy__Output as _envoy_api_v2_LoadBalancingPolicy__Output } from '../../../envoy/api/v2/LoadBalancingPolicy'; -import type { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../envoy/api/v2/core/ConfigSource'; -import type { UpstreamHttpProtocolOptions as _envoy_api_v2_core_UpstreamHttpProtocolOptions, UpstreamHttpProtocolOptions__Output as _envoy_api_v2_core_UpstreamHttpProtocolOptions__Output } from '../../../envoy/api/v2/core/UpstreamHttpProtocolOptions'; -import type { UInt64Value as _google_protobuf_UInt64Value, UInt64Value__Output as _google_protobuf_UInt64Value__Output } from '../../../google/protobuf/UInt64Value'; -import type { Percent as _envoy_type_Percent, Percent__Output as _envoy_type_Percent__Output } from '../../../envoy/type/Percent'; -import type { Long } from '@grpc/proto-loader'; - -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -export enum _envoy_api_v2_Cluster_ClusterProtocolSelection { - /** - * Cluster can only operate on one of the possible upstream protocols (HTTP1.1, HTTP2). - * If :ref:`http2_protocol_options ` are - * present, HTTP2 will be used, otherwise HTTP1.1 will be used. - */ - USE_CONFIGURED_PROTOCOL = 0, - /** - * Use HTTP1.1 or HTTP2, depending on which one is used on the downstream connection. - */ - USE_DOWNSTREAM_PROTOCOL = 1, -} - -/** - * Common configuration for all load balancer implementations. - * [#next-free-field: 8] - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig { - /** - * Configures the :ref:`healthy panic threshold `. - * If not specified, the default is 50%. - * To disable panic mode, set to 0%. - * - * .. note:: - * The specified percent will be truncated to the nearest 1%. - */ - 'healthy_panic_threshold'?: (_envoy_type_Percent); - 'zone_aware_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig); - 'locality_weighted_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig); - /** - * If set, all health check/weight/metadata updates that happen within this duration will be - * merged and delivered in one shot when the duration expires. The start of the duration is when - * the first update happens. This is useful for big clusters, with potentially noisy deploys - * that might trigger excessive CPU usage due to a constant stream of healthcheck state changes - * or metadata updates. The first set of updates to be seen apply immediately (e.g.: a new - * cluster). Please always keep in mind that the use of sandbox technologies may change this - * behavior. - * - * If this is not set, we default to a merge window of 1000ms. To disable it, set the merge - * window to 0. - * - * Note: merging does not apply to cluster membership changes (e.g.: adds/removes); this is - * because merging those updates isn't currently safe. See - * https://github.com/envoyproxy/envoy/pull/3941. - */ - 'update_merge_window'?: (_google_protobuf_Duration); - /** - * If set to true, Envoy will not consider new hosts when computing load balancing weights until - * they have been health checked for the first time. This will have no effect unless - * active health checking is also configured. - * - * Ignoring a host means that for any load balancing calculations that adjust weights based - * on the ratio of eligible hosts and total hosts (priority spillover, locality weighting and - * panic mode) Envoy will exclude these hosts in the denominator. - * - * For example, with hosts in two priorities P0 and P1, where P0 looks like - * {healthy, unhealthy (new), unhealthy (new)} - * and where P1 looks like - * {healthy, healthy} - * all traffic will still hit P0, as 1 / (3 - 2) = 1. - * - * Enabling this will allow scaling up the number of hosts for a given cluster without entering - * panic mode or triggering priority spillover, assuming the hosts pass the first health check. - * - * If panic mode is triggered, new hosts are still eligible for traffic; they simply do not - * contribute to the calculation when deciding whether panic mode is enabled or not. - */ - 'ignore_new_hosts_until_first_hc'?: (boolean); - /** - * If set to `true`, the cluster manager will drain all existing - * connections to upstream hosts whenever hosts are added or removed from the cluster. - */ - 'close_connections_on_host_set_change'?: (boolean); - /** - * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) - */ - 'consistent_hashing_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig); - 'locality_config_specifier'?: "zone_aware_lb_config"|"locality_weighted_lb_config"; -} - -/** - * Common configuration for all load balancer implementations. - * [#next-free-field: 8] - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig__Output { - /** - * Configures the :ref:`healthy panic threshold `. - * If not specified, the default is 50%. - * To disable panic mode, set to 0%. - * - * .. note:: - * The specified percent will be truncated to the nearest 1%. - */ - 'healthy_panic_threshold'?: (_envoy_type_Percent__Output); - 'zone_aware_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig__Output); - 'locality_weighted_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig__Output); - /** - * If set, all health check/weight/metadata updates that happen within this duration will be - * merged and delivered in one shot when the duration expires. The start of the duration is when - * the first update happens. This is useful for big clusters, with potentially noisy deploys - * that might trigger excessive CPU usage due to a constant stream of healthcheck state changes - * or metadata updates. The first set of updates to be seen apply immediately (e.g.: a new - * cluster). Please always keep in mind that the use of sandbox technologies may change this - * behavior. - * - * If this is not set, we default to a merge window of 1000ms. To disable it, set the merge - * window to 0. - * - * Note: merging does not apply to cluster membership changes (e.g.: adds/removes); this is - * because merging those updates isn't currently safe. See - * https://github.com/envoyproxy/envoy/pull/3941. - */ - 'update_merge_window'?: (_google_protobuf_Duration__Output); - /** - * If set to true, Envoy will not consider new hosts when computing load balancing weights until - * they have been health checked for the first time. This will have no effect unless - * active health checking is also configured. - * - * Ignoring a host means that for any load balancing calculations that adjust weights based - * on the ratio of eligible hosts and total hosts (priority spillover, locality weighting and - * panic mode) Envoy will exclude these hosts in the denominator. - * - * For example, with hosts in two priorities P0 and P1, where P0 looks like - * {healthy, unhealthy (new), unhealthy (new)} - * and where P1 looks like - * {healthy, healthy} - * all traffic will still hit P0, as 1 / (3 - 2) = 1. - * - * Enabling this will allow scaling up the number of hosts for a given cluster without entering - * panic mode or triggering priority spillover, assuming the hosts pass the first health check. - * - * If panic mode is triggered, new hosts are still eligible for traffic; they simply do not - * contribute to the calculation when deciding whether panic mode is enabled or not. - */ - 'ignore_new_hosts_until_first_hc': (boolean); - /** - * If set to `true`, the cluster manager will drain all existing - * connections to upstream hosts whenever hosts are added or removed from the cluster. - */ - 'close_connections_on_host_set_change': (boolean); - /** - * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) - */ - 'consistent_hashing_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig__Output); - 'locality_config_specifier': "zone_aware_lb_config"|"locality_weighted_lb_config"; -} - -/** - * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig { - /** - * If set to `true`, the cluster will use hostname instead of the resolved - * address as the key to consistently hash to an upstream host. Only valid for StrictDNS clusters with hostnames which resolve to a single IP address. - */ - 'use_hostname_for_hashing'?: (boolean); -} - -/** - * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig_ConsistentHashingLbConfig__Output { - /** - * If set to `true`, the cluster will use hostname instead of the resolved - * address as the key to consistently hash to an upstream host. Only valid for StrictDNS clusters with hostnames which resolve to a single IP address. - */ - 'use_hostname_for_hashing': (boolean); -} - -/** - * Extended cluster type. - */ -export interface _envoy_api_v2_Cluster_CustomClusterType { - /** - * The type of the cluster to instantiate. The name must match a supported cluster type. - */ - 'name'?: (string); - /** - * Cluster specific configuration which depends on the cluster being instantiated. - * See the supported cluster for further documentation. - */ - 'typed_config'?: (_google_protobuf_Any); -} - -/** - * Extended cluster type. - */ -export interface _envoy_api_v2_Cluster_CustomClusterType__Output { - /** - * The type of the cluster to instantiate. The name must match a supported cluster type. - */ - 'name': (string); - /** - * Cluster specific configuration which depends on the cluster being instantiated. - * See the supported cluster for further documentation. - */ - 'typed_config'?: (_google_protobuf_Any__Output); -} - -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -/** - * Refer to :ref:`service discovery type ` - * for an explanation on each type. - */ -export enum _envoy_api_v2_Cluster_DiscoveryType { - /** - * Refer to the :ref:`static discovery type` - * for an explanation. - */ - STATIC = 0, - /** - * Refer to the :ref:`strict DNS discovery - * type` - * for an explanation. - */ - STRICT_DNS = 1, - /** - * Refer to the :ref:`logical DNS discovery - * type` - * for an explanation. - */ - LOGICAL_DNS = 2, - /** - * Refer to the :ref:`service discovery type` - * for an explanation. - */ - EDS = 3, - /** - * Refer to the :ref:`original destination discovery - * type` - * for an explanation. - */ - ORIGINAL_DST = 4, -} - -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -/** - * When V4_ONLY is selected, the DNS resolver will only perform a lookup for - * addresses in the IPv4 family. If V6_ONLY is selected, the DNS resolver will - * only perform a lookup for addresses in the IPv6 family. If AUTO is - * specified, the DNS resolver will first perform a lookup for addresses in - * the IPv6 family and fallback to a lookup for addresses in the IPv4 family. - * For cluster types other than - * :ref:`STRICT_DNS` and - * :ref:`LOGICAL_DNS`, - * this setting is - * ignored. - */ -export enum _envoy_api_v2_Cluster_DnsLookupFamily { - AUTO = 0, - V4_ONLY = 1, - V6_ONLY = 2, -} - -/** - * Only valid when discovery type is EDS. - */ -export interface _envoy_api_v2_Cluster_EdsClusterConfig { - /** - * Configuration for the source of EDS updates for this Cluster. - */ - 'eds_config'?: (_envoy_api_v2_core_ConfigSource); - /** - * Optional alternative to cluster name to present to EDS. This does not - * have the same restrictions as cluster name, i.e. it may be arbitrary - * length. - */ - 'service_name'?: (string); -} - -/** - * Only valid when discovery type is EDS. - */ -export interface _envoy_api_v2_Cluster_EdsClusterConfig__Output { - /** - * Configuration for the source of EDS updates for this Cluster. - */ - 'eds_config'?: (_envoy_api_v2_core_ConfigSource__Output); - /** - * Optional alternative to cluster name to present to EDS. This does not - * have the same restrictions as cluster name, i.e. it may be arbitrary - * length. - */ - 'service_name': (string); -} - -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -/** - * The hash function used to hash hosts onto the ketama ring. - */ -export enum _envoy_api_v2_Cluster_RingHashLbConfig_HashFunction { - /** - * Use `xxHash `_, this is the default hash function. - */ - XX_HASH = 0, - /** - * Use `MurmurHash2 `_, this is compatible with - * std:hash in GNU libstdc++ 3.4.20 or above. This is typically the case when compiled - * on Linux and not macOS. - */ - MURMUR_HASH_2 = 1, -} - -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -/** - * Refer to :ref:`load balancer type ` architecture - * overview section for information on each type. - */ -export enum _envoy_api_v2_Cluster_LbPolicy { - /** - * Refer to the :ref:`round robin load balancing - * policy` - * for an explanation. - */ - ROUND_ROBIN = 0, - /** - * Refer to the :ref:`least request load balancing - * policy` - * for an explanation. - */ - LEAST_REQUEST = 1, - /** - * Refer to the :ref:`ring hash load balancing - * policy` - * for an explanation. - */ - RING_HASH = 2, - /** - * Refer to the :ref:`random load balancing - * policy` - * for an explanation. - */ - RANDOM = 3, - /** - * Refer to the :ref:`original destination load balancing - * policy` - * for an explanation. - * - * .. attention:: - * - * **This load balancing policy is deprecated**. Use CLUSTER_PROVIDED instead. - */ - ORIGINAL_DST_LB = 4, - /** - * Refer to the :ref:`Maglev load balancing policy` - * for an explanation. - */ - MAGLEV = 5, - /** - * This load balancer type must be specified if the configured cluster provides a cluster - * specific load balancer. Consult the configured cluster's documentation for whether to set - * this option or not. - */ - CLUSTER_PROVIDED = 6, - /** - * [#not-implemented-hide:] Use the new :ref:`load_balancing_policy - * ` field to determine the LB policy. - * [#next-major-version: In the v3 API, we should consider deprecating the lb_policy field - * and instead using the new load_balancing_policy field as the one and only mechanism for - * configuring this.] - */ - LOAD_BALANCING_POLICY_CONFIG = 7, -} - -/** - * Optionally divide the endpoints in this cluster into subsets defined by - * endpoint metadata and selected by route and weighted cluster metadata. - * [#next-free-field: 8] - */ -export interface _envoy_api_v2_Cluster_LbSubsetConfig { - /** - * The behavior used when no endpoint subset matches the selected route's - * metadata. The value defaults to - * :ref:`NO_FALLBACK`. - */ - 'fallback_policy'?: (_envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy | keyof typeof _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy); - /** - * Specifies the default subset of endpoints used during fallback if - * fallback_policy is - * :ref:`DEFAULT_SUBSET`. - * Each field in default_subset is - * compared to the matching LbEndpoint.Metadata under the *envoy.lb* - * namespace. It is valid for no hosts to match, in which case the behavior - * is the same as a fallback_policy of - * :ref:`NO_FALLBACK`. - */ - 'default_subset'?: (_google_protobuf_Struct); - /** - * For each entry, LbEndpoint.Metadata's - * *envoy.lb* namespace is traversed and a subset is created for each unique - * combination of key and value. For example: - * - * .. code-block:: json - * - * { "subset_selectors": [ - * { "keys": [ "version" ] }, - * { "keys": [ "stage", "hardware_type" ] } - * ]} - * - * A subset is matched when the metadata from the selected route and - * weighted cluster contains the same keys and values as the subset's - * metadata. The same host may appear in multiple subsets. - */ - 'subset_selectors'?: (_envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector)[]; - /** - * If true, routing to subsets will take into account the localities and locality weights of the - * endpoints when making the routing decision. - * - * There are some potential pitfalls associated with enabling this feature, as the resulting - * traffic split after applying both a subset match and locality weights might be undesirable. - * - * Consider for example a situation in which you have 50/50 split across two localities X/Y - * which have 100 hosts each without subsetting. If the subset LB results in X having only 1 - * host selected but Y having 100, then a lot more load is being dumped on the single host in X - * than originally anticipated in the load balancing assignment delivered via EDS. - */ - 'locality_weight_aware'?: (boolean); - /** - * When used with locality_weight_aware, scales the weight of each locality by the ratio - * of hosts in the subset vs hosts in the original subset. This aims to even out the load - * going to an individual locality if said locality is disproportionately affected by the - * subset predicate. - */ - 'scale_locality_weight'?: (boolean); - /** - * If true, when a fallback policy is configured and its corresponding subset fails to find - * a host this will cause any host to be selected instead. - * - * This is useful when using the default subset as the fallback policy, given the default - * subset might become empty. With this option enabled, if that happens the LB will attempt - * to select a host from the entire cluster. - */ - 'panic_mode_any'?: (boolean); - /** - * If true, metadata specified for a metadata key will be matched against the corresponding - * endpoint metadata if the endpoint metadata matches the value exactly OR it is a list value - * and any of the elements in the list matches the criteria. - */ - 'list_as_any'?: (boolean); -} - -/** - * Optionally divide the endpoints in this cluster into subsets defined by - * endpoint metadata and selected by route and weighted cluster metadata. - * [#next-free-field: 8] - */ -export interface _envoy_api_v2_Cluster_LbSubsetConfig__Output { - /** - * The behavior used when no endpoint subset matches the selected route's - * metadata. The value defaults to - * :ref:`NO_FALLBACK`. - */ - 'fallback_policy': (keyof typeof _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy); - /** - * Specifies the default subset of endpoints used during fallback if - * fallback_policy is - * :ref:`DEFAULT_SUBSET`. - * Each field in default_subset is - * compared to the matching LbEndpoint.Metadata under the *envoy.lb* - * namespace. It is valid for no hosts to match, in which case the behavior - * is the same as a fallback_policy of - * :ref:`NO_FALLBACK`. - */ - 'default_subset'?: (_google_protobuf_Struct__Output); - /** - * For each entry, LbEndpoint.Metadata's - * *envoy.lb* namespace is traversed and a subset is created for each unique - * combination of key and value. For example: - * - * .. code-block:: json - * - * { "subset_selectors": [ - * { "keys": [ "version" ] }, - * { "keys": [ "stage", "hardware_type" ] } - * ]} - * - * A subset is matched when the metadata from the selected route and - * weighted cluster contains the same keys and values as the subset's - * metadata. The same host may appear in multiple subsets. - */ - 'subset_selectors': (_envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector__Output)[]; - /** - * If true, routing to subsets will take into account the localities and locality weights of the - * endpoints when making the routing decision. - * - * There are some potential pitfalls associated with enabling this feature, as the resulting - * traffic split after applying both a subset match and locality weights might be undesirable. - * - * Consider for example a situation in which you have 50/50 split across two localities X/Y - * which have 100 hosts each without subsetting. If the subset LB results in X having only 1 - * host selected but Y having 100, then a lot more load is being dumped on the single host in X - * than originally anticipated in the load balancing assignment delivered via EDS. - */ - 'locality_weight_aware': (boolean); - /** - * When used with locality_weight_aware, scales the weight of each locality by the ratio - * of hosts in the subset vs hosts in the original subset. This aims to even out the load - * going to an individual locality if said locality is disproportionately affected by the - * subset predicate. - */ - 'scale_locality_weight': (boolean); - /** - * If true, when a fallback policy is configured and its corresponding subset fails to find - * a host this will cause any host to be selected instead. - * - * This is useful when using the default subset as the fallback policy, given the default - * subset might become empty. With this option enabled, if that happens the LB will attempt - * to select a host from the entire cluster. - */ - 'panic_mode_any': (boolean); - /** - * If true, metadata specified for a metadata key will be matched against the corresponding - * endpoint metadata if the endpoint metadata matches the value exactly OR it is a list value - * and any of the elements in the list matches the criteria. - */ - 'list_as_any': (boolean); -} - -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -/** - * If NO_FALLBACK is selected, a result - * equivalent to no healthy hosts is reported. If ANY_ENDPOINT is selected, - * any cluster endpoint may be returned (subject to policy, health checks, - * etc). If DEFAULT_SUBSET is selected, load balancing is performed over the - * endpoints matching the values from the default_subset field. - */ -export enum _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy { - NO_FALLBACK = 0, - ANY_ENDPOINT = 1, - DEFAULT_SUBSET = 2, -} - -/** - * Specifications for subsets. - */ -export interface _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector { - /** - * List of keys to match with the weighted cluster metadata. - */ - 'keys'?: (string)[]; - /** - * The behavior used when no endpoint subset matches the selected route's - * metadata. - */ - 'fallback_policy'?: (_envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy | keyof typeof _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy); - /** - * Subset of - * :ref:`keys` used by - * :ref:`KEYS_SUBSET` - * fallback policy. - * It has to be a non empty list if KEYS_SUBSET fallback policy is selected. - * For any other fallback policy the parameter is not used and should not be set. - * Only values also present in - * :ref:`keys` are allowed, but - * `fallback_keys_subset` cannot be equal to `keys`. - */ - 'fallback_keys_subset'?: (string)[]; -} - -/** - * Specifications for subsets. - */ -export interface _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector__Output { - /** - * List of keys to match with the weighted cluster metadata. - */ - 'keys': (string)[]; - /** - * The behavior used when no endpoint subset matches the selected route's - * metadata. - */ - 'fallback_policy': (keyof typeof _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy); - /** - * Subset of - * :ref:`keys` used by - * :ref:`KEYS_SUBSET` - * fallback policy. - * It has to be a non empty list if KEYS_SUBSET fallback policy is selected. - * For any other fallback policy the parameter is not used and should not be set. - * Only values also present in - * :ref:`keys` are allowed, but - * `fallback_keys_subset` cannot be equal to `keys`. - */ - 'fallback_keys_subset': (string)[]; -} - -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -/** - * Allows to override top level fallback policy per selector. - */ -export enum _envoy_api_v2_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy { - /** - * If NOT_DEFINED top level config fallback policy is used instead. - */ - NOT_DEFINED = 0, - /** - * If NO_FALLBACK is selected, a result equivalent to no healthy hosts is reported. - */ - NO_FALLBACK = 1, - /** - * If ANY_ENDPOINT is selected, any cluster endpoint may be returned - * (subject to policy, health checks, etc). - */ - ANY_ENDPOINT = 2, - /** - * If DEFAULT_SUBSET is selected, load balancing is performed over the - * endpoints matching the values from the default_subset field. - */ - DEFAULT_SUBSET = 3, - /** - * If KEYS_SUBSET is selected, subset selector matching is performed again with metadata - * keys reduced to - * :ref:`fallback_keys_subset`. - * It allows for a fallback to a different, less specific selector if some of the keys of - * the selector are considered optional. - */ - KEYS_SUBSET = 4, -} - -/** - * Specific configuration for the LeastRequest load balancing policy. - */ -export interface _envoy_api_v2_Cluster_LeastRequestLbConfig { - /** - * The number of random healthy hosts from which the host with the fewest active requests will - * be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. - */ - 'choice_count'?: (_google_protobuf_UInt32Value); -} - -/** - * Specific configuration for the LeastRequest load balancing policy. - */ -export interface _envoy_api_v2_Cluster_LeastRequestLbConfig__Output { - /** - * The number of random healthy hosts from which the host with the fewest active requests will - * be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. - */ - 'choice_count'?: (_google_protobuf_UInt32Value__Output); -} - -/** - * Configuration for :ref:`locality weighted load balancing - * ` - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig { -} - -/** - * Configuration for :ref:`locality weighted load balancing - * ` - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig_LocalityWeightedLbConfig__Output { -} - -/** - * Specific configuration for the - * :ref:`Original Destination ` - * load balancing policy. - */ -export interface _envoy_api_v2_Cluster_OriginalDstLbConfig { - /** - * When true, :ref:`x-envoy-original-dst-host - * ` can be used to override destination - * address. - * - * .. attention:: - * - * This header isn't sanitized by default, so enabling this feature allows HTTP clients to - * route traffic to arbitrary hosts and/or ports, which may have serious security - * consequences. - */ - 'use_http_header'?: (boolean); -} - -/** - * Specific configuration for the - * :ref:`Original Destination ` - * load balancing policy. - */ -export interface _envoy_api_v2_Cluster_OriginalDstLbConfig__Output { - /** - * When true, :ref:`x-envoy-original-dst-host - * ` can be used to override destination - * address. - * - * .. attention:: - * - * This header isn't sanitized by default, so enabling this feature allows HTTP clients to - * route traffic to arbitrary hosts and/or ports, which may have serious security - * consequences. - */ - 'use_http_header': (boolean); -} - -export interface _envoy_api_v2_Cluster_RefreshRate { - /** - * Specifies the base interval between refreshes. This parameter is required and must be greater - * than zero and less than - * :ref:`max_interval `. - */ - 'base_interval'?: (_google_protobuf_Duration); - /** - * Specifies the maximum interval between refreshes. This parameter is optional, but must be - * greater than or equal to the - * :ref:`base_interval ` if set. The default - * is 10 times the :ref:`base_interval `. - */ - 'max_interval'?: (_google_protobuf_Duration); -} - -export interface _envoy_api_v2_Cluster_RefreshRate__Output { - /** - * Specifies the base interval between refreshes. This parameter is required and must be greater - * than zero and less than - * :ref:`max_interval `. - */ - 'base_interval'?: (_google_protobuf_Duration__Output); - /** - * Specifies the maximum interval between refreshes. This parameter is optional, but must be - * greater than or equal to the - * :ref:`base_interval ` if set. The default - * is 10 times the :ref:`base_interval `. - */ - 'max_interval'?: (_google_protobuf_Duration__Output); -} - -/** - * Specific configuration for the :ref:`RingHash` - * load balancing policy. - */ -export interface _envoy_api_v2_Cluster_RingHashLbConfig { - /** - * Minimum hash ring size. The larger the ring is (that is, the more hashes there are for each - * provided host) the better the request distribution will reflect the desired weights. Defaults - * to 1024 entries, and limited to 8M entries. See also - * :ref:`maximum_ring_size`. - */ - 'minimum_ring_size'?: (_google_protobuf_UInt64Value); - /** - * The hash function used to hash hosts onto the ketama ring. The value defaults to - * :ref:`XX_HASH`. - */ - 'hash_function'?: (_envoy_api_v2_Cluster_RingHashLbConfig_HashFunction | keyof typeof _envoy_api_v2_Cluster_RingHashLbConfig_HashFunction); - /** - * Maximum hash ring size. Defaults to 8M entries, and limited to 8M entries, but can be lowered - * to further constrain resource use. See also - * :ref:`minimum_ring_size`. - */ - 'maximum_ring_size'?: (_google_protobuf_UInt64Value); -} - -/** - * Specific configuration for the :ref:`RingHash` - * load balancing policy. - */ -export interface _envoy_api_v2_Cluster_RingHashLbConfig__Output { - /** - * Minimum hash ring size. The larger the ring is (that is, the more hashes there are for each - * provided host) the better the request distribution will reflect the desired weights. Defaults - * to 1024 entries, and limited to 8M entries. See also - * :ref:`maximum_ring_size`. - */ - 'minimum_ring_size'?: (_google_protobuf_UInt64Value__Output); - /** - * The hash function used to hash hosts onto the ketama ring. The value defaults to - * :ref:`XX_HASH`. - */ - 'hash_function': (keyof typeof _envoy_api_v2_Cluster_RingHashLbConfig_HashFunction); - /** - * Maximum hash ring size. Defaults to 8M entries, and limited to 8M entries, but can be lowered - * to further constrain resource use. See also - * :ref:`minimum_ring_size`. - */ - 'maximum_ring_size'?: (_google_protobuf_UInt64Value__Output); -} - -/** - * TransportSocketMatch specifies what transport socket config will be used - * when the match conditions are satisfied. - */ -export interface _envoy_api_v2_Cluster_TransportSocketMatch { - /** - * The name of the match, used in stats generation. - */ - 'name'?: (string); - /** - * Optional endpoint metadata match criteria. - * The connection to the endpoint with metadata matching what is set in this field - * will use the transport socket configuration specified here. - * The endpoint's metadata entry in *envoy.transport_socket_match* is used to match - * against the values specified in this field. - */ - 'match'?: (_google_protobuf_Struct); - /** - * The configuration of the transport socket. - */ - 'transport_socket'?: (_envoy_api_v2_core_TransportSocket); -} - -/** - * TransportSocketMatch specifies what transport socket config will be used - * when the match conditions are satisfied. - */ -export interface _envoy_api_v2_Cluster_TransportSocketMatch__Output { - /** - * The name of the match, used in stats generation. - */ - 'name': (string); - /** - * Optional endpoint metadata match criteria. - * The connection to the endpoint with metadata matching what is set in this field - * will use the transport socket configuration specified here. - * The endpoint's metadata entry in *envoy.transport_socket_match* is used to match - * against the values specified in this field. - */ - 'match'?: (_google_protobuf_Struct__Output); - /** - * The configuration of the transport socket. - */ - 'transport_socket'?: (_envoy_api_v2_core_TransportSocket__Output); -} - -/** - * Configuration for :ref:`zone aware routing - * `. - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig { - /** - * Configures percentage of requests that will be considered for zone aware routing - * if zone aware routing is configured. If not specified, the default is 100%. - * * :ref:`runtime values `. - * * :ref:`Zone aware routing support `. - */ - 'routing_enabled'?: (_envoy_type_Percent); - /** - * Configures minimum upstream cluster size required for zone aware routing - * If upstream cluster size is less than specified, zone aware routing is not performed - * even if zone aware routing is configured. If not specified, the default is 6. - * * :ref:`runtime values `. - * * :ref:`Zone aware routing support `. - */ - 'min_cluster_size'?: (_google_protobuf_UInt64Value); - /** - * If set to true, Envoy will not consider any hosts when the cluster is in :ref:`panic - * mode`. Instead, the cluster will fail all - * requests as if all hosts are unhealthy. This can help avoid potentially overwhelming a - * failing service. - */ - 'fail_traffic_on_panic'?: (boolean); -} - -/** - * Configuration for :ref:`zone aware routing - * `. - */ -export interface _envoy_api_v2_Cluster_CommonLbConfig_ZoneAwareLbConfig__Output { - /** - * Configures percentage of requests that will be considered for zone aware routing - * if zone aware routing is configured. If not specified, the default is 100%. - * * :ref:`runtime values `. - * * :ref:`Zone aware routing support `. - */ - 'routing_enabled'?: (_envoy_type_Percent__Output); - /** - * Configures minimum upstream cluster size required for zone aware routing - * If upstream cluster size is less than specified, zone aware routing is not performed - * even if zone aware routing is configured. If not specified, the default is 6. - * * :ref:`runtime values `. - * * :ref:`Zone aware routing support `. - */ - 'min_cluster_size'?: (_google_protobuf_UInt64Value__Output); - /** - * If set to true, Envoy will not consider any hosts when the cluster is in :ref:`panic - * mode`. Instead, the cluster will fail all - * requests as if all hosts are unhealthy. This can help avoid potentially overwhelming a - * failing service. - */ - 'fail_traffic_on_panic': (boolean); -} - -/** - * Configuration for a single upstream cluster. - * [#next-free-field: 48] - */ -export interface Cluster { - /** - * Supplies the name of the cluster which must be unique across all clusters. - * The cluster name is used when emitting - * :ref:`statistics ` if :ref:`alt_stat_name - * ` is not provided. - * Any ``:`` in the cluster name will be converted to ``_`` when emitting statistics. - */ - 'name'?: (string); - /** - * The :ref:`service discovery type ` - * to use for resolving the cluster. - */ - 'type'?: (_envoy_api_v2_Cluster_DiscoveryType | keyof typeof _envoy_api_v2_Cluster_DiscoveryType); - /** - * Configuration to use for EDS updates for the Cluster. - */ - 'eds_cluster_config'?: (_envoy_api_v2_Cluster_EdsClusterConfig); - /** - * The timeout for new network connections to hosts in the cluster. - */ - 'connect_timeout'?: (_google_protobuf_Duration); - /** - * Soft limit on size of the cluster’s connections read and write buffers. If - * unspecified, an implementation defined default is applied (1MiB). - */ - 'per_connection_buffer_limit_bytes'?: (_google_protobuf_UInt32Value); - /** - * The :ref:`load balancer type ` to use - * when picking a host in the cluster. - */ - 'lb_policy'?: (_envoy_api_v2_Cluster_LbPolicy | keyof typeof _envoy_api_v2_Cluster_LbPolicy); - /** - * If the service discovery type is - * :ref:`STATIC`, - * :ref:`STRICT_DNS` - * or :ref:`LOGICAL_DNS`, - * then hosts is required. - * - * .. attention:: - * - * **This field is deprecated**. Set the - * :ref:`load_assignment` field instead. - */ - 'hosts'?: (_envoy_api_v2_core_Address)[]; - /** - * Optional :ref:`active health checking ` - * configuration for the cluster. If no - * configuration is specified no health checking will be done and all cluster - * members will be considered healthy at all times. - */ - 'health_checks'?: (_envoy_api_v2_core_HealthCheck)[]; - /** - * Optional maximum requests for a single upstream connection. This parameter - * is respected by both the HTTP/1.1 and HTTP/2 connection pool - * implementations. If not specified, there is no limit. Setting this - * parameter to 1 will effectively disable keep alive. - */ - 'max_requests_per_connection'?: (_google_protobuf_UInt32Value); - /** - * Optional :ref:`circuit breaking ` for the cluster. - */ - 'circuit_breakers'?: (_envoy_api_v2_cluster_CircuitBreakers); - /** - * The TLS configuration for connections to the upstream cluster. - * - * .. attention:: - * - * **This field is deprecated**. Use `transport_socket` with name `tls` instead. If both are - * set, `transport_socket` takes priority. - */ - 'tls_context'?: (_envoy_api_v2_auth_UpstreamTlsContext); - /** - * Additional options when handling HTTP1 requests. - */ - 'http_protocol_options'?: (_envoy_api_v2_core_Http1ProtocolOptions); - /** - * Even if default HTTP2 protocol options are desired, this field must be - * set so that Envoy will assume that the upstream supports HTTP/2 when - * making new HTTP connection pool connections. Currently, Envoy only - * supports prior knowledge for upstream connections. Even if TLS is used - * with ALPN, `http2_protocol_options` must be specified. As an aside this allows HTTP/2 - * connections to happen over plain text. - */ - 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions); - /** - * If the DNS refresh rate is specified and the cluster type is either - * :ref:`STRICT_DNS`, - * or :ref:`LOGICAL_DNS`, - * this value is used as the cluster’s DNS refresh - * rate. The value configured must be at least 1ms. If this setting is not specified, the - * value defaults to 5000ms. For cluster types other than - * :ref:`STRICT_DNS` - * and :ref:`LOGICAL_DNS` - * this setting is ignored. - */ - 'dns_refresh_rate'?: (_google_protobuf_Duration); - /** - * The DNS IP address resolution policy. If this setting is not specified, the - * value defaults to - * :ref:`AUTO`. - */ - 'dns_lookup_family'?: (_envoy_api_v2_Cluster_DnsLookupFamily | keyof typeof _envoy_api_v2_Cluster_DnsLookupFamily); - /** - * If DNS resolvers are specified and the cluster type is either - * :ref:`STRICT_DNS`, - * or :ref:`LOGICAL_DNS`, - * this value is used to specify the cluster’s dns resolvers. - * If this setting is not specified, the value defaults to the default - * resolver, which uses /etc/resolv.conf for configuration. For cluster types - * other than - * :ref:`STRICT_DNS` - * and :ref:`LOGICAL_DNS` - * this setting is ignored. - */ - 'dns_resolvers'?: (_envoy_api_v2_core_Address)[]; - /** - * If specified, outlier detection will be enabled for this upstream cluster. - * Each of the configuration values can be overridden via - * :ref:`runtime values `. - */ - 'outlier_detection'?: (_envoy_api_v2_cluster_OutlierDetection); - /** - * The interval for removing stale hosts from a cluster type - * :ref:`ORIGINAL_DST`. - * Hosts are considered stale if they have not been used - * as upstream destinations during this interval. New hosts are added - * to original destination clusters on demand as new connections are - * redirected to Envoy, causing the number of hosts in the cluster to - * grow over time. Hosts that are not stale (they are actively used as - * destinations) are kept in the cluster, which allows connections to - * them remain open, saving the latency that would otherwise be spent - * on opening new connections. If this setting is not specified, the - * value defaults to 5000ms. For cluster types other than - * :ref:`ORIGINAL_DST` - * this setting is ignored. - */ - 'cleanup_interval'?: (_google_protobuf_Duration); - /** - * Optional configuration used to bind newly established upstream connections. - * This overrides any bind_config specified in the bootstrap proto. - * If the address and port are empty, no bind will be performed. - */ - 'upstream_bind_config'?: (_envoy_api_v2_core_BindConfig); - /** - * Configuration for load balancing subsetting. - */ - 'lb_subset_config'?: (_envoy_api_v2_Cluster_LbSubsetConfig); - /** - * Optional configuration for the Ring Hash load balancing policy. - */ - 'ring_hash_lb_config'?: (_envoy_api_v2_Cluster_RingHashLbConfig); - /** - * Optional custom transport socket implementation to use for upstream connections. - * To setup TLS, set a transport socket with name `tls` and - * :ref:`UpstreamTlsContexts ` in the `typed_config`. - * If no transport socket configuration is specified, new connections - * will be set up with plaintext. - */ - 'transport_socket'?: (_envoy_api_v2_core_TransportSocket); - /** - * The Metadata field can be used to provide additional information about the - * cluster. It can be used for stats, logging, and varying filter behavior. - * Fields should use reverse DNS notation to denote which entity within Envoy - * will need the information. For instance, if the metadata is intended for - * the Router filter, the filter name should be specified as *envoy.filters.http.router*. - */ - 'metadata'?: (_envoy_api_v2_core_Metadata); - /** - * Determines how Envoy selects the protocol used to speak to upstream hosts. - */ - 'protocol_selection'?: (_envoy_api_v2_Cluster_ClusterProtocolSelection | keyof typeof _envoy_api_v2_Cluster_ClusterProtocolSelection); - /** - * Common configuration for all load balancer implementations. - */ - 'common_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig); - /** - * An optional alternative to the cluster name to be used while emitting stats. - * Any ``:`` in the name will be converted to ``_`` when emitting statistics. This should not be - * confused with :ref:`Router Filter Header - * `. - */ - 'alt_stat_name'?: (string); - /** - * Additional options when handling HTTP requests upstream. These options will be applicable to - * both HTTP1 and HTTP2 requests. - */ - 'common_http_protocol_options'?: (_envoy_api_v2_core_HttpProtocolOptions); - /** - * Optional options for upstream connections. - */ - 'upstream_connection_options'?: (_envoy_api_v2_UpstreamConnectionOptions); - /** - * If an upstream host becomes unhealthy (as determined by the configured health checks - * or outlier detection), immediately close all connections to the failed host. - * - * .. note:: - * - * This is currently only supported for connections created by tcp_proxy. - * - * .. note:: - * - * The current implementation of this feature closes all connections immediately when - * the unhealthy status is detected. If there are a large number of connections open - * to an upstream host that becomes unhealthy, Envoy may spend a substantial amount of - * time exclusively closing these connections, and not processing any other traffic. - */ - 'close_connections_on_host_health_failure'?: (boolean); - /** - * If set to true, Envoy will ignore the health value of a host when processing its removal - * from service discovery. This means that if active health checking is used, Envoy will *not* - * wait for the endpoint to go unhealthy before removing it. - */ - 'drain_connections_on_host_removal'?: (boolean); - /** - * Setting this is required for specifying members of - * :ref:`STATIC`, - * :ref:`STRICT_DNS` - * or :ref:`LOGICAL_DNS` clusters. - * This field supersedes the *hosts* field in the v2 API. - * - * .. attention:: - * - * Setting this allows non-EDS cluster types to contain embedded EDS equivalent - * :ref:`endpoint assignments`. - */ - 'load_assignment'?: (_envoy_api_v2_ClusterLoadAssignment); - /** - * Optional configuration for the Original Destination load balancing policy. - */ - 'original_dst_lb_config'?: (_envoy_api_v2_Cluster_OriginalDstLbConfig); - /** - * The extension_protocol_options field is used to provide extension-specific protocol options - * for upstream connections. The key should match the extension filter name, such as - * "envoy.filters.network.thrift_proxy". See the extension's documentation for details on - * specific options. - */ - 'extension_protocol_options'?: ({[key: string]: _google_protobuf_Struct}); - /** - * The extension_protocol_options field is used to provide extension-specific protocol options - * for upstream connections. The key should match the extension filter name, such as - * "envoy.filters.network.thrift_proxy". See the extension's documentation for details on - * specific options. - */ - 'typed_extension_protocol_options'?: ({[key: string]: _google_protobuf_Any}); - /** - * Optional configuration for the LeastRequest load balancing policy. - */ - 'least_request_lb_config'?: (_envoy_api_v2_Cluster_LeastRequestLbConfig); - /** - * The custom cluster type. - */ - 'cluster_type'?: (_envoy_api_v2_Cluster_CustomClusterType); - /** - * Optional configuration for setting cluster's DNS refresh rate. If the value is set to true, - * cluster's DNS refresh rate will be set to resource record's TTL which comes from DNS - * resolution. - */ - 'respect_dns_ttl'?: (boolean); - /** - * An (optional) network filter chain, listed in the order the filters should be applied. - * The chain will be applied to all outgoing connections that Envoy makes to the upstream - * servers of this cluster. - */ - 'filters'?: (_envoy_api_v2_cluster_Filter)[]; - /** - * [#not-implemented-hide:] New mechanism for LB policy configuration. Used only if the - * :ref:`lb_policy` field has the value - * :ref:`LOAD_BALANCING_POLICY_CONFIG`. - */ - 'load_balancing_policy'?: (_envoy_api_v2_LoadBalancingPolicy); - /** - * [#not-implemented-hide:] - * If present, tells the client where to send load reports via LRS. If not present, the - * client will fall back to a client-side default, which may be either (a) don't send any - * load reports or (b) send load reports for all clusters to a single default server - * (which may be configured in the bootstrap file). - * - * Note that if multiple clusters point to the same LRS server, the client may choose to - * create a separate stream for each cluster or it may choose to coalesce the data for - * multiple clusters onto a single stream. Either way, the client must make sure to send - * the data for any given cluster on no more than one stream. - * - * [#next-major-version: In the v3 API, we should consider restructuring this somehow, - * maybe by allowing LRS to go on the ADS stream, or maybe by moving some of the negotiation - * from the LRS stream here.] - */ - 'lrs_server'?: (_envoy_api_v2_core_ConfigSource); - /** - * Configuration to use different transport sockets for different endpoints. - * The entry of *envoy.transport_socket_match* in the - * :ref:`LbEndpoint.Metadata ` - * is used to match against the transport sockets as they appear in the list. The first - * :ref:`match ` is used. - * For example, with the following match - * - * .. code-block:: yaml - * - * transport_socket_matches: - * - name: "enableMTLS" - * match: - * acceptMTLS: true - * transport_socket: - * name: envoy.transport_sockets.tls - * config: { ... } # tls socket configuration - * - name: "defaultToPlaintext" - * match: {} - * transport_socket: - * name: envoy.transport_sockets.raw_buffer - * - * Connections to the endpoints whose metadata value under *envoy.transport_socket_match* - * having "acceptMTLS"/"true" key/value pair use the "enableMTLS" socket configuration. - * - * If a :ref:`socket match ` with empty match - * criteria is provided, that always match any endpoint. For example, the "defaultToPlaintext" - * socket match in case above. - * - * If an endpoint metadata's value under *envoy.transport_socket_match* does not match any - * *TransportSocketMatch*, socket configuration fallbacks to use the *tls_context* or - * *transport_socket* specified in this cluster. - * - * This field allows gradual and flexible transport socket configuration changes. - * - * The metadata of endpoints in EDS can indicate transport socket capabilities. For example, - * an endpoint's metadata can have two key value pairs as "acceptMTLS": "true", - * "acceptPlaintext": "true". While some other endpoints, only accepting plaintext traffic - * has "acceptPlaintext": "true" metadata information. - * - * Then the xDS server can configure the CDS to a client, Envoy A, to send mutual TLS - * traffic for endpoints with "acceptMTLS": "true", by adding a corresponding - * *TransportSocketMatch* in this field. Other client Envoys receive CDS without - * *transport_socket_match* set, and still send plain text traffic to the same cluster. - * - * [#comment:TODO(incfly): add a detailed architecture doc on intended usage.] - */ - 'transport_socket_matches'?: (_envoy_api_v2_Cluster_TransportSocketMatch)[]; - /** - * If the DNS failure refresh rate is specified and the cluster type is either - * :ref:`STRICT_DNS`, - * or :ref:`LOGICAL_DNS`, - * this is used as the cluster’s DNS refresh rate when requests are failing. If this setting is - * not specified, the failure refresh rate defaults to the DNS refresh rate. For cluster types - * other than :ref:`STRICT_DNS` and - * :ref:`LOGICAL_DNS` this setting is - * ignored. - */ - 'dns_failure_refresh_rate'?: (_envoy_api_v2_Cluster_RefreshRate); - /** - * [#next-major-version: Reconcile DNS options in a single message.] - * Always use TCP queries instead of UDP queries for DNS lookups. - */ - 'use_tcp_for_dns_lookups'?: (boolean); - /** - * HTTP protocol options that are applied only to upstream HTTP connections. - * These options apply to all HTTP versions. - */ - 'upstream_http_protocol_options'?: (_envoy_api_v2_core_UpstreamHttpProtocolOptions); - /** - * If track_timeout_budgets is true, the :ref:`timeout budget histograms - * ` will be published for each - * request. These show what percentage of a request's per try and global timeout was used. A value - * of 0 would indicate that none of the timeout was used or that the timeout was infinite. A value - * of 100 would indicate that the request took the entirety of the timeout given to it. - */ - 'track_timeout_budgets'?: (boolean); - 'cluster_discovery_type'?: "type"|"cluster_type"; - /** - * Optional configuration for the load balancing algorithm selected by - * LbPolicy. Currently only - * :ref:`RING_HASH` and - * :ref:`LEAST_REQUEST` - * has additional configuration options. - * Specifying ring_hash_lb_config or least_request_lb_config without setting the corresponding - * LbPolicy will generate an error at runtime. - */ - 'lb_config'?: "ring_hash_lb_config"|"original_dst_lb_config"|"least_request_lb_config"; -} - -/** - * Configuration for a single upstream cluster. - * [#next-free-field: 48] - */ -export interface Cluster__Output { - /** - * Supplies the name of the cluster which must be unique across all clusters. - * The cluster name is used when emitting - * :ref:`statistics ` if :ref:`alt_stat_name - * ` is not provided. - * Any ``:`` in the cluster name will be converted to ``_`` when emitting statistics. - */ - 'name': (string); - /** - * The :ref:`service discovery type ` - * to use for resolving the cluster. - */ - 'type'?: (keyof typeof _envoy_api_v2_Cluster_DiscoveryType); - /** - * Configuration to use for EDS updates for the Cluster. - */ - 'eds_cluster_config'?: (_envoy_api_v2_Cluster_EdsClusterConfig__Output); - /** - * The timeout for new network connections to hosts in the cluster. - */ - 'connect_timeout'?: (_google_protobuf_Duration__Output); - /** - * Soft limit on size of the cluster’s connections read and write buffers. If - * unspecified, an implementation defined default is applied (1MiB). - */ - 'per_connection_buffer_limit_bytes'?: (_google_protobuf_UInt32Value__Output); - /** - * The :ref:`load balancer type ` to use - * when picking a host in the cluster. - */ - 'lb_policy': (keyof typeof _envoy_api_v2_Cluster_LbPolicy); - /** - * If the service discovery type is - * :ref:`STATIC`, - * :ref:`STRICT_DNS` - * or :ref:`LOGICAL_DNS`, - * then hosts is required. - * - * .. attention:: - * - * **This field is deprecated**. Set the - * :ref:`load_assignment` field instead. - */ - 'hosts': (_envoy_api_v2_core_Address__Output)[]; - /** - * Optional :ref:`active health checking ` - * configuration for the cluster. If no - * configuration is specified no health checking will be done and all cluster - * members will be considered healthy at all times. - */ - 'health_checks': (_envoy_api_v2_core_HealthCheck__Output)[]; - /** - * Optional maximum requests for a single upstream connection. This parameter - * is respected by both the HTTP/1.1 and HTTP/2 connection pool - * implementations. If not specified, there is no limit. Setting this - * parameter to 1 will effectively disable keep alive. - */ - 'max_requests_per_connection'?: (_google_protobuf_UInt32Value__Output); - /** - * Optional :ref:`circuit breaking ` for the cluster. - */ - 'circuit_breakers'?: (_envoy_api_v2_cluster_CircuitBreakers__Output); - /** - * The TLS configuration for connections to the upstream cluster. - * - * .. attention:: - * - * **This field is deprecated**. Use `transport_socket` with name `tls` instead. If both are - * set, `transport_socket` takes priority. - */ - 'tls_context'?: (_envoy_api_v2_auth_UpstreamTlsContext__Output); - /** - * Additional options when handling HTTP1 requests. - */ - 'http_protocol_options'?: (_envoy_api_v2_core_Http1ProtocolOptions__Output); - /** - * Even if default HTTP2 protocol options are desired, this field must be - * set so that Envoy will assume that the upstream supports HTTP/2 when - * making new HTTP connection pool connections. Currently, Envoy only - * supports prior knowledge for upstream connections. Even if TLS is used - * with ALPN, `http2_protocol_options` must be specified. As an aside this allows HTTP/2 - * connections to happen over plain text. - */ - 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions__Output); - /** - * If the DNS refresh rate is specified and the cluster type is either - * :ref:`STRICT_DNS`, - * or :ref:`LOGICAL_DNS`, - * this value is used as the cluster’s DNS refresh - * rate. The value configured must be at least 1ms. If this setting is not specified, the - * value defaults to 5000ms. For cluster types other than - * :ref:`STRICT_DNS` - * and :ref:`LOGICAL_DNS` - * this setting is ignored. - */ - 'dns_refresh_rate'?: (_google_protobuf_Duration__Output); - /** - * The DNS IP address resolution policy. If this setting is not specified, the - * value defaults to - * :ref:`AUTO`. - */ - 'dns_lookup_family': (keyof typeof _envoy_api_v2_Cluster_DnsLookupFamily); - /** - * If DNS resolvers are specified and the cluster type is either - * :ref:`STRICT_DNS`, - * or :ref:`LOGICAL_DNS`, - * this value is used to specify the cluster’s dns resolvers. - * If this setting is not specified, the value defaults to the default - * resolver, which uses /etc/resolv.conf for configuration. For cluster types - * other than - * :ref:`STRICT_DNS` - * and :ref:`LOGICAL_DNS` - * this setting is ignored. - */ - 'dns_resolvers': (_envoy_api_v2_core_Address__Output)[]; - /** - * If specified, outlier detection will be enabled for this upstream cluster. - * Each of the configuration values can be overridden via - * :ref:`runtime values `. - */ - 'outlier_detection'?: (_envoy_api_v2_cluster_OutlierDetection__Output); - /** - * The interval for removing stale hosts from a cluster type - * :ref:`ORIGINAL_DST`. - * Hosts are considered stale if they have not been used - * as upstream destinations during this interval. New hosts are added - * to original destination clusters on demand as new connections are - * redirected to Envoy, causing the number of hosts in the cluster to - * grow over time. Hosts that are not stale (they are actively used as - * destinations) are kept in the cluster, which allows connections to - * them remain open, saving the latency that would otherwise be spent - * on opening new connections. If this setting is not specified, the - * value defaults to 5000ms. For cluster types other than - * :ref:`ORIGINAL_DST` - * this setting is ignored. - */ - 'cleanup_interval'?: (_google_protobuf_Duration__Output); - /** - * Optional configuration used to bind newly established upstream connections. - * This overrides any bind_config specified in the bootstrap proto. - * If the address and port are empty, no bind will be performed. - */ - 'upstream_bind_config'?: (_envoy_api_v2_core_BindConfig__Output); - /** - * Configuration for load balancing subsetting. - */ - 'lb_subset_config'?: (_envoy_api_v2_Cluster_LbSubsetConfig__Output); - /** - * Optional configuration for the Ring Hash load balancing policy. - */ - 'ring_hash_lb_config'?: (_envoy_api_v2_Cluster_RingHashLbConfig__Output); - /** - * Optional custom transport socket implementation to use for upstream connections. - * To setup TLS, set a transport socket with name `tls` and - * :ref:`UpstreamTlsContexts ` in the `typed_config`. - * If no transport socket configuration is specified, new connections - * will be set up with plaintext. - */ - 'transport_socket'?: (_envoy_api_v2_core_TransportSocket__Output); - /** - * The Metadata field can be used to provide additional information about the - * cluster. It can be used for stats, logging, and varying filter behavior. - * Fields should use reverse DNS notation to denote which entity within Envoy - * will need the information. For instance, if the metadata is intended for - * the Router filter, the filter name should be specified as *envoy.filters.http.router*. - */ - 'metadata'?: (_envoy_api_v2_core_Metadata__Output); - /** - * Determines how Envoy selects the protocol used to speak to upstream hosts. - */ - 'protocol_selection': (keyof typeof _envoy_api_v2_Cluster_ClusterProtocolSelection); - /** - * Common configuration for all load balancer implementations. - */ - 'common_lb_config'?: (_envoy_api_v2_Cluster_CommonLbConfig__Output); - /** - * An optional alternative to the cluster name to be used while emitting stats. - * Any ``:`` in the name will be converted to ``_`` when emitting statistics. This should not be - * confused with :ref:`Router Filter Header - * `. - */ - 'alt_stat_name': (string); - /** - * Additional options when handling HTTP requests upstream. These options will be applicable to - * both HTTP1 and HTTP2 requests. - */ - 'common_http_protocol_options'?: (_envoy_api_v2_core_HttpProtocolOptions__Output); - /** - * Optional options for upstream connections. - */ - 'upstream_connection_options'?: (_envoy_api_v2_UpstreamConnectionOptions__Output); - /** - * If an upstream host becomes unhealthy (as determined by the configured health checks - * or outlier detection), immediately close all connections to the failed host. - * - * .. note:: - * - * This is currently only supported for connections created by tcp_proxy. - * - * .. note:: - * - * The current implementation of this feature closes all connections immediately when - * the unhealthy status is detected. If there are a large number of connections open - * to an upstream host that becomes unhealthy, Envoy may spend a substantial amount of - * time exclusively closing these connections, and not processing any other traffic. - */ - 'close_connections_on_host_health_failure': (boolean); - /** - * If set to true, Envoy will ignore the health value of a host when processing its removal - * from service discovery. This means that if active health checking is used, Envoy will *not* - * wait for the endpoint to go unhealthy before removing it. - */ - 'drain_connections_on_host_removal': (boolean); - /** - * Setting this is required for specifying members of - * :ref:`STATIC`, - * :ref:`STRICT_DNS` - * or :ref:`LOGICAL_DNS` clusters. - * This field supersedes the *hosts* field in the v2 API. - * - * .. attention:: - * - * Setting this allows non-EDS cluster types to contain embedded EDS equivalent - * :ref:`endpoint assignments`. - */ - 'load_assignment'?: (_envoy_api_v2_ClusterLoadAssignment__Output); - /** - * Optional configuration for the Original Destination load balancing policy. - */ - 'original_dst_lb_config'?: (_envoy_api_v2_Cluster_OriginalDstLbConfig__Output); - /** - * The extension_protocol_options field is used to provide extension-specific protocol options - * for upstream connections. The key should match the extension filter name, such as - * "envoy.filters.network.thrift_proxy". See the extension's documentation for details on - * specific options. - */ - 'extension_protocol_options'?: ({[key: string]: _google_protobuf_Struct__Output}); - /** - * The extension_protocol_options field is used to provide extension-specific protocol options - * for upstream connections. The key should match the extension filter name, such as - * "envoy.filters.network.thrift_proxy". See the extension's documentation for details on - * specific options. - */ - 'typed_extension_protocol_options'?: ({[key: string]: _google_protobuf_Any__Output}); - /** - * Optional configuration for the LeastRequest load balancing policy. - */ - 'least_request_lb_config'?: (_envoy_api_v2_Cluster_LeastRequestLbConfig__Output); - /** - * The custom cluster type. - */ - 'cluster_type'?: (_envoy_api_v2_Cluster_CustomClusterType__Output); - /** - * Optional configuration for setting cluster's DNS refresh rate. If the value is set to true, - * cluster's DNS refresh rate will be set to resource record's TTL which comes from DNS - * resolution. - */ - 'respect_dns_ttl': (boolean); - /** - * An (optional) network filter chain, listed in the order the filters should be applied. - * The chain will be applied to all outgoing connections that Envoy makes to the upstream - * servers of this cluster. - */ - 'filters': (_envoy_api_v2_cluster_Filter__Output)[]; - /** - * [#not-implemented-hide:] New mechanism for LB policy configuration. Used only if the - * :ref:`lb_policy` field has the value - * :ref:`LOAD_BALANCING_POLICY_CONFIG`. - */ - 'load_balancing_policy'?: (_envoy_api_v2_LoadBalancingPolicy__Output); - /** - * [#not-implemented-hide:] - * If present, tells the client where to send load reports via LRS. If not present, the - * client will fall back to a client-side default, which may be either (a) don't send any - * load reports or (b) send load reports for all clusters to a single default server - * (which may be configured in the bootstrap file). - * - * Note that if multiple clusters point to the same LRS server, the client may choose to - * create a separate stream for each cluster or it may choose to coalesce the data for - * multiple clusters onto a single stream. Either way, the client must make sure to send - * the data for any given cluster on no more than one stream. - * - * [#next-major-version: In the v3 API, we should consider restructuring this somehow, - * maybe by allowing LRS to go on the ADS stream, or maybe by moving some of the negotiation - * from the LRS stream here.] - */ - 'lrs_server'?: (_envoy_api_v2_core_ConfigSource__Output); - /** - * Configuration to use different transport sockets for different endpoints. - * The entry of *envoy.transport_socket_match* in the - * :ref:`LbEndpoint.Metadata ` - * is used to match against the transport sockets as they appear in the list. The first - * :ref:`match ` is used. - * For example, with the following match - * - * .. code-block:: yaml - * - * transport_socket_matches: - * - name: "enableMTLS" - * match: - * acceptMTLS: true - * transport_socket: - * name: envoy.transport_sockets.tls - * config: { ... } # tls socket configuration - * - name: "defaultToPlaintext" - * match: {} - * transport_socket: - * name: envoy.transport_sockets.raw_buffer - * - * Connections to the endpoints whose metadata value under *envoy.transport_socket_match* - * having "acceptMTLS"/"true" key/value pair use the "enableMTLS" socket configuration. - * - * If a :ref:`socket match ` with empty match - * criteria is provided, that always match any endpoint. For example, the "defaultToPlaintext" - * socket match in case above. - * - * If an endpoint metadata's value under *envoy.transport_socket_match* does not match any - * *TransportSocketMatch*, socket configuration fallbacks to use the *tls_context* or - * *transport_socket* specified in this cluster. - * - * This field allows gradual and flexible transport socket configuration changes. - * - * The metadata of endpoints in EDS can indicate transport socket capabilities. For example, - * an endpoint's metadata can have two key value pairs as "acceptMTLS": "true", - * "acceptPlaintext": "true". While some other endpoints, only accepting plaintext traffic - * has "acceptPlaintext": "true" metadata information. - * - * Then the xDS server can configure the CDS to a client, Envoy A, to send mutual TLS - * traffic for endpoints with "acceptMTLS": "true", by adding a corresponding - * *TransportSocketMatch* in this field. Other client Envoys receive CDS without - * *transport_socket_match* set, and still send plain text traffic to the same cluster. - * - * [#comment:TODO(incfly): add a detailed architecture doc on intended usage.] - */ - 'transport_socket_matches': (_envoy_api_v2_Cluster_TransportSocketMatch__Output)[]; - /** - * If the DNS failure refresh rate is specified and the cluster type is either - * :ref:`STRICT_DNS`, - * or :ref:`LOGICAL_DNS`, - * this is used as the cluster’s DNS refresh rate when requests are failing. If this setting is - * not specified, the failure refresh rate defaults to the DNS refresh rate. For cluster types - * other than :ref:`STRICT_DNS` and - * :ref:`LOGICAL_DNS` this setting is - * ignored. - */ - 'dns_failure_refresh_rate'?: (_envoy_api_v2_Cluster_RefreshRate__Output); - /** - * [#next-major-version: Reconcile DNS options in a single message.] - * Always use TCP queries instead of UDP queries for DNS lookups. - */ - 'use_tcp_for_dns_lookups': (boolean); - /** - * HTTP protocol options that are applied only to upstream HTTP connections. - * These options apply to all HTTP versions. - */ - 'upstream_http_protocol_options'?: (_envoy_api_v2_core_UpstreamHttpProtocolOptions__Output); - /** - * If track_timeout_budgets is true, the :ref:`timeout budget histograms - * ` will be published for each - * request. These show what percentage of a request's per try and global timeout was used. A value - * of 0 would indicate that none of the timeout was used or that the timeout was infinite. A value - * of 100 would indicate that the request took the entirety of the timeout given to it. - */ - 'track_timeout_budgets': (boolean); - 'cluster_discovery_type': "type"|"cluster_type"; - /** - * Optional configuration for the load balancing algorithm selected by - * LbPolicy. Currently only - * :ref:`RING_HASH` and - * :ref:`LEAST_REQUEST` - * has additional configuration options. - * Specifying ring_hash_lb_config or least_request_lb_config without setting the corresponding - * LbPolicy will generate an error at runtime. - */ - 'lb_config': "ring_hash_lb_config"|"original_dst_lb_config"|"least_request_lb_config"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/Resource.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/Resource.ts deleted file mode 100644 index 4804201bd..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/Resource.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/discovery.proto - -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; - -export interface Resource { - /** - * The resource level version. It allows xDS to track the state of individual - * resources. - */ - 'version'?: (string); - /** - * The resource being tracked. - */ - 'resource'?: (_google_protobuf_Any); - /** - * The resource's name, to distinguish it from others of the same type of resource. - */ - 'name'?: (string); - /** - * The aliases are a list of other names that this resource can go by. - */ - 'aliases'?: (string)[]; -} - -export interface Resource__Output { - /** - * The resource level version. It allows xDS to track the state of individual - * resources. - */ - 'version': (string); - /** - * The resource being tracked. - */ - 'resource'?: (_google_protobuf_Any__Output); - /** - * The resource's name, to distinguish it from others of the same type of resource. - */ - 'name': (string); - /** - * The aliases are a list of other names that this resource can go by. - */ - 'aliases': (string)[]; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/UpstreamConnectionOptions.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/UpstreamConnectionOptions.ts deleted file mode 100644 index e46a2cd06..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/UpstreamConnectionOptions.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto - -import type { TcpKeepalive as _envoy_api_v2_core_TcpKeepalive, TcpKeepalive__Output as _envoy_api_v2_core_TcpKeepalive__Output } from '../../../envoy/api/v2/core/TcpKeepalive'; - -export interface UpstreamConnectionOptions { - /** - * If set then set SO_KEEPALIVE on the socket to enable TCP Keepalives. - */ - 'tcp_keepalive'?: (_envoy_api_v2_core_TcpKeepalive); -} - -export interface UpstreamConnectionOptions__Output { - /** - * If set then set SO_KEEPALIVE on the socket to enable TCP Keepalives. - */ - 'tcp_keepalive'?: (_envoy_api_v2_core_TcpKeepalive__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/Vhds.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/Vhds.ts deleted file mode 100644 index f2ec45d2d..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/Vhds.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/route.proto - -import type { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../envoy/api/v2/core/ConfigSource'; - -export interface Vhds { - /** - * Configuration source specifier for VHDS. - */ - 'config_source'?: (_envoy_api_v2_core_ConfigSource); -} - -export interface Vhds__Output { - /** - * Configuration source specifier for VHDS. - */ - 'config_source'?: (_envoy_api_v2_core_ConfigSource__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/CertificateValidationContext.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/CertificateValidationContext.ts deleted file mode 100644 index 0272f3b5c..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/CertificateValidationContext.ts +++ /dev/null @@ -1,315 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/common.proto - -import type { DataSource as _envoy_api_v2_core_DataSource, DataSource__Output as _envoy_api_v2_core_DataSource__Output } from '../../../../envoy/api/v2/core/DataSource'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { StringMatcher as _envoy_type_matcher_StringMatcher, StringMatcher__Output as _envoy_type_matcher_StringMatcher__Output } from '../../../../envoy/type/matcher/StringMatcher'; - -// Original file: deps/envoy-api/envoy/api/v2/auth/common.proto - -/** - * Peer certificate verification mode. - */ -export enum _envoy_api_v2_auth_CertificateValidationContext_TrustChainVerification { - /** - * Perform default certificate verification (e.g., against CA / verification lists) - */ - VERIFY_TRUST_CHAIN = 0, - /** - * Connections where the certificate fails verification will be permitted. - * For HTTP connections, the result of certificate verification can be used in route matching. ( - * see :ref:`validated ` ). - */ - ACCEPT_UNTRUSTED = 1, -} - -/** - * [#next-free-field: 11] - */ -export interface CertificateValidationContext { - /** - * TLS certificate data containing certificate authority certificates to use in verifying - * a presented peer certificate (e.g. server certificate for clusters or client certificate - * for listeners). If not specified and a peer certificate is presented it will not be - * verified. By default, a client certificate is optional, unless one of the additional - * options (:ref:`require_client_certificate - * `, - * :ref:`verify_certificate_spki - * `, - * :ref:`verify_certificate_hash - * `, or - * :ref:`match_subject_alt_names - * `) is also - * specified. - * - * It can optionally contain certificate revocation lists, in which case Envoy will verify - * that the presented peer certificate has not been revoked by one of the included CRLs. - * - * See :ref:`the TLS overview ` for a list of common - * system CA locations. - */ - 'trusted_ca'?: (_envoy_api_v2_core_DataSource); - /** - * An optional list of hex-encoded SHA-256 hashes. If specified, Envoy will verify that - * the SHA-256 of the DER-encoded presented certificate matches one of the specified values. - * - * A hex-encoded SHA-256 of the certificate can be generated with the following command: - * - * .. code-block:: bash - * - * $ openssl x509 -in path/to/client.crt -outform DER | openssl dgst -sha256 | cut -d" " -f2 - * df6ff72fe9116521268f6f2dd4966f51df479883fe7037b39f75916ac3049d1a - * - * A long hex-encoded and colon-separated SHA-256 (a.k.a. "fingerprint") of the certificate - * can be generated with the following command: - * - * .. code-block:: bash - * - * $ openssl x509 -in path/to/client.crt -noout -fingerprint -sha256 | cut -d"=" -f2 - * DF:6F:F7:2F:E9:11:65:21:26:8F:6F:2D:D4:96:6F:51:DF:47:98:83:FE:70:37:B3:9F:75:91:6A:C3:04:9D:1A - * - * Both of those formats are acceptable. - * - * When both: - * :ref:`verify_certificate_hash - * ` and - * :ref:`verify_certificate_spki - * ` are specified, - * a hash matching value from either of the lists will result in the certificate being accepted. - */ - 'verify_certificate_hash'?: (string)[]; - /** - * An optional list of base64-encoded SHA-256 hashes. If specified, Envoy will verify that the - * SHA-256 of the DER-encoded Subject Public Key Information (SPKI) of the presented certificate - * matches one of the specified values. - * - * A base64-encoded SHA-256 of the Subject Public Key Information (SPKI) of the certificate - * can be generated with the following command: - * - * .. code-block:: bash - * - * $ openssl x509 -in path/to/client.crt -noout -pubkey - * | openssl pkey -pubin -outform DER - * | openssl dgst -sha256 -binary - * | openssl enc -base64 - * NvqYIYSbgK2vCJpQhObf77vv+bQWtc5ek5RIOwPiC9A= - * - * This is the format used in HTTP Public Key Pinning. - * - * When both: - * :ref:`verify_certificate_hash - * ` and - * :ref:`verify_certificate_spki - * ` are specified, - * a hash matching value from either of the lists will result in the certificate being accepted. - * - * .. attention:: - * - * This option is preferred over :ref:`verify_certificate_hash - * `, - * because SPKI is tied to a private key, so it doesn't change when the certificate - * is renewed using the same private key. - */ - 'verify_certificate_spki'?: (string)[]; - /** - * An optional list of Subject Alternative Names. If specified, Envoy will verify that the - * Subject Alternative Name of the presented certificate matches one of the specified values. - * - * .. attention:: - * - * Subject Alternative Names are easily spoofable and verifying only them is insecure, - * therefore this option must be used together with :ref:`trusted_ca - * `. - */ - 'verify_subject_alt_name'?: (string)[]; - /** - * [#not-implemented-hide:] Must present a signed time-stamped OCSP response. - */ - 'require_ocsp_staple'?: (_google_protobuf_BoolValue); - /** - * [#not-implemented-hide:] Must present signed certificate time-stamp. - */ - 'require_signed_certificate_timestamp'?: (_google_protobuf_BoolValue); - /** - * An optional `certificate revocation list - * `_ - * (in PEM format). If specified, Envoy will verify that the presented peer - * certificate has not been revoked by this CRL. If this DataSource contains - * multiple CRLs, all of them will be used. - */ - 'crl'?: (_envoy_api_v2_core_DataSource); - /** - * If specified, Envoy will not reject expired certificates. - */ - 'allow_expired_certificate'?: (boolean); - /** - * An optional list of Subject Alternative name matchers. Envoy will verify that the - * Subject Alternative Name of the presented certificate matches one of the specified matches. - * - * When a certificate has wildcard DNS SAN entries, to match a specific client, it should be - * configured with exact match type in the :ref:`string matcher `. - * For example if the certificate has "\*.example.com" as DNS SAN entry, to allow only "api.example.com", - * it should be configured as shown below. - * - * .. code-block:: yaml - * - * match_subject_alt_names: - * exact: "api.example.com" - * - * .. attention:: - * - * Subject Alternative Names are easily spoofable and verifying only them is insecure, - * therefore this option must be used together with :ref:`trusted_ca - * `. - */ - 'match_subject_alt_names'?: (_envoy_type_matcher_StringMatcher)[]; - /** - * Certificate trust chain verification mode. - */ - 'trust_chain_verification'?: (_envoy_api_v2_auth_CertificateValidationContext_TrustChainVerification | keyof typeof _envoy_api_v2_auth_CertificateValidationContext_TrustChainVerification); -} - -/** - * [#next-free-field: 11] - */ -export interface CertificateValidationContext__Output { - /** - * TLS certificate data containing certificate authority certificates to use in verifying - * a presented peer certificate (e.g. server certificate for clusters or client certificate - * for listeners). If not specified and a peer certificate is presented it will not be - * verified. By default, a client certificate is optional, unless one of the additional - * options (:ref:`require_client_certificate - * `, - * :ref:`verify_certificate_spki - * `, - * :ref:`verify_certificate_hash - * `, or - * :ref:`match_subject_alt_names - * `) is also - * specified. - * - * It can optionally contain certificate revocation lists, in which case Envoy will verify - * that the presented peer certificate has not been revoked by one of the included CRLs. - * - * See :ref:`the TLS overview ` for a list of common - * system CA locations. - */ - 'trusted_ca'?: (_envoy_api_v2_core_DataSource__Output); - /** - * An optional list of hex-encoded SHA-256 hashes. If specified, Envoy will verify that - * the SHA-256 of the DER-encoded presented certificate matches one of the specified values. - * - * A hex-encoded SHA-256 of the certificate can be generated with the following command: - * - * .. code-block:: bash - * - * $ openssl x509 -in path/to/client.crt -outform DER | openssl dgst -sha256 | cut -d" " -f2 - * df6ff72fe9116521268f6f2dd4966f51df479883fe7037b39f75916ac3049d1a - * - * A long hex-encoded and colon-separated SHA-256 (a.k.a. "fingerprint") of the certificate - * can be generated with the following command: - * - * .. code-block:: bash - * - * $ openssl x509 -in path/to/client.crt -noout -fingerprint -sha256 | cut -d"=" -f2 - * DF:6F:F7:2F:E9:11:65:21:26:8F:6F:2D:D4:96:6F:51:DF:47:98:83:FE:70:37:B3:9F:75:91:6A:C3:04:9D:1A - * - * Both of those formats are acceptable. - * - * When both: - * :ref:`verify_certificate_hash - * ` and - * :ref:`verify_certificate_spki - * ` are specified, - * a hash matching value from either of the lists will result in the certificate being accepted. - */ - 'verify_certificate_hash': (string)[]; - /** - * An optional list of base64-encoded SHA-256 hashes. If specified, Envoy will verify that the - * SHA-256 of the DER-encoded Subject Public Key Information (SPKI) of the presented certificate - * matches one of the specified values. - * - * A base64-encoded SHA-256 of the Subject Public Key Information (SPKI) of the certificate - * can be generated with the following command: - * - * .. code-block:: bash - * - * $ openssl x509 -in path/to/client.crt -noout -pubkey - * | openssl pkey -pubin -outform DER - * | openssl dgst -sha256 -binary - * | openssl enc -base64 - * NvqYIYSbgK2vCJpQhObf77vv+bQWtc5ek5RIOwPiC9A= - * - * This is the format used in HTTP Public Key Pinning. - * - * When both: - * :ref:`verify_certificate_hash - * ` and - * :ref:`verify_certificate_spki - * ` are specified, - * a hash matching value from either of the lists will result in the certificate being accepted. - * - * .. attention:: - * - * This option is preferred over :ref:`verify_certificate_hash - * `, - * because SPKI is tied to a private key, so it doesn't change when the certificate - * is renewed using the same private key. - */ - 'verify_certificate_spki': (string)[]; - /** - * An optional list of Subject Alternative Names. If specified, Envoy will verify that the - * Subject Alternative Name of the presented certificate matches one of the specified values. - * - * .. attention:: - * - * Subject Alternative Names are easily spoofable and verifying only them is insecure, - * therefore this option must be used together with :ref:`trusted_ca - * `. - */ - 'verify_subject_alt_name': (string)[]; - /** - * [#not-implemented-hide:] Must present a signed time-stamped OCSP response. - */ - 'require_ocsp_staple'?: (_google_protobuf_BoolValue__Output); - /** - * [#not-implemented-hide:] Must present signed certificate time-stamp. - */ - 'require_signed_certificate_timestamp'?: (_google_protobuf_BoolValue__Output); - /** - * An optional `certificate revocation list - * `_ - * (in PEM format). If specified, Envoy will verify that the presented peer - * certificate has not been revoked by this CRL. If this DataSource contains - * multiple CRLs, all of them will be used. - */ - 'crl'?: (_envoy_api_v2_core_DataSource__Output); - /** - * If specified, Envoy will not reject expired certificates. - */ - 'allow_expired_certificate': (boolean); - /** - * An optional list of Subject Alternative name matchers. Envoy will verify that the - * Subject Alternative Name of the presented certificate matches one of the specified matches. - * - * When a certificate has wildcard DNS SAN entries, to match a specific client, it should be - * configured with exact match type in the :ref:`string matcher `. - * For example if the certificate has "\*.example.com" as DNS SAN entry, to allow only "api.example.com", - * it should be configured as shown below. - * - * .. code-block:: yaml - * - * match_subject_alt_names: - * exact: "api.example.com" - * - * .. attention:: - * - * Subject Alternative Names are easily spoofable and verifying only them is insecure, - * therefore this option must be used together with :ref:`trusted_ca - * `. - */ - 'match_subject_alt_names': (_envoy_type_matcher_StringMatcher__Output)[]; - /** - * Certificate trust chain verification mode. - */ - 'trust_chain_verification': (keyof typeof _envoy_api_v2_auth_CertificateValidationContext_TrustChainVerification); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/CommonTlsContext.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/CommonTlsContext.ts deleted file mode 100644 index 784e3d2ce..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/CommonTlsContext.ts +++ /dev/null @@ -1,140 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/tls.proto - -import type { TlsParameters as _envoy_api_v2_auth_TlsParameters, TlsParameters__Output as _envoy_api_v2_auth_TlsParameters__Output } from '../../../../envoy/api/v2/auth/TlsParameters'; -import type { TlsCertificate as _envoy_api_v2_auth_TlsCertificate, TlsCertificate__Output as _envoy_api_v2_auth_TlsCertificate__Output } from '../../../../envoy/api/v2/auth/TlsCertificate'; -import type { CertificateValidationContext as _envoy_api_v2_auth_CertificateValidationContext, CertificateValidationContext__Output as _envoy_api_v2_auth_CertificateValidationContext__Output } from '../../../../envoy/api/v2/auth/CertificateValidationContext'; -import type { SdsSecretConfig as _envoy_api_v2_auth_SdsSecretConfig, SdsSecretConfig__Output as _envoy_api_v2_auth_SdsSecretConfig__Output } from '../../../../envoy/api/v2/auth/SdsSecretConfig'; - -export interface _envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext { - /** - * How to validate peer certificates. - */ - 'default_validation_context'?: (_envoy_api_v2_auth_CertificateValidationContext); - /** - * Config for fetching validation context via SDS API. - */ - 'validation_context_sds_secret_config'?: (_envoy_api_v2_auth_SdsSecretConfig); -} - -export interface _envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext__Output { - /** - * How to validate peer certificates. - */ - 'default_validation_context'?: (_envoy_api_v2_auth_CertificateValidationContext__Output); - /** - * Config for fetching validation context via SDS API. - */ - 'validation_context_sds_secret_config'?: (_envoy_api_v2_auth_SdsSecretConfig__Output); -} - -/** - * TLS context shared by both client and server TLS contexts. - * [#next-free-field: 9] - */ -export interface CommonTlsContext { - /** - * TLS protocol versions, cipher suites etc. - */ - 'tls_params'?: (_envoy_api_v2_auth_TlsParameters); - /** - * :ref:`Multiple TLS certificates ` can be associated with the - * same context to allow both RSA and ECDSA certificates. - * - * Only a single TLS certificate is supported in client contexts. In server contexts, the first - * RSA certificate is used for clients that only support RSA and the first ECDSA certificate is - * used for clients that support ECDSA. - */ - 'tls_certificates'?: (_envoy_api_v2_auth_TlsCertificate)[]; - /** - * How to validate peer certificates. - */ - 'validation_context'?: (_envoy_api_v2_auth_CertificateValidationContext); - /** - * Supplies the list of ALPN protocols that the listener should expose. In - * practice this is likely to be set to one of two values (see the - * :ref:`codec_type - * ` - * parameter in the HTTP connection manager for more information): - * - * * "h2,http/1.1" If the listener is going to support both HTTP/2 and HTTP/1.1. - * * "http/1.1" If the listener is only going to support HTTP/1.1. - * - * There is no default for this parameter. If empty, Envoy will not expose ALPN. - */ - 'alpn_protocols'?: (string)[]; - /** - * Configs for fetching TLS certificates via SDS API. - */ - 'tls_certificate_sds_secret_configs'?: (_envoy_api_v2_auth_SdsSecretConfig)[]; - /** - * Config for fetching validation context via SDS API. - */ - 'validation_context_sds_secret_config'?: (_envoy_api_v2_auth_SdsSecretConfig); - /** - * Combined certificate validation context holds a default CertificateValidationContext - * and SDS config. When SDS server returns dynamic CertificateValidationContext, both dynamic - * and default CertificateValidationContext are merged into a new CertificateValidationContext - * for validation. This merge is done by Message::MergeFrom(), so dynamic - * CertificateValidationContext overwrites singular fields in default - * CertificateValidationContext, and concatenates repeated fields to default - * CertificateValidationContext, and logical OR is applied to boolean fields. - */ - 'combined_validation_context'?: (_envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext); - 'validation_context_type'?: "validation_context"|"validation_context_sds_secret_config"|"combined_validation_context"; -} - -/** - * TLS context shared by both client and server TLS contexts. - * [#next-free-field: 9] - */ -export interface CommonTlsContext__Output { - /** - * TLS protocol versions, cipher suites etc. - */ - 'tls_params'?: (_envoy_api_v2_auth_TlsParameters__Output); - /** - * :ref:`Multiple TLS certificates ` can be associated with the - * same context to allow both RSA and ECDSA certificates. - * - * Only a single TLS certificate is supported in client contexts. In server contexts, the first - * RSA certificate is used for clients that only support RSA and the first ECDSA certificate is - * used for clients that support ECDSA. - */ - 'tls_certificates': (_envoy_api_v2_auth_TlsCertificate__Output)[]; - /** - * How to validate peer certificates. - */ - 'validation_context'?: (_envoy_api_v2_auth_CertificateValidationContext__Output); - /** - * Supplies the list of ALPN protocols that the listener should expose. In - * practice this is likely to be set to one of two values (see the - * :ref:`codec_type - * ` - * parameter in the HTTP connection manager for more information): - * - * * "h2,http/1.1" If the listener is going to support both HTTP/2 and HTTP/1.1. - * * "http/1.1" If the listener is only going to support HTTP/1.1. - * - * There is no default for this parameter. If empty, Envoy will not expose ALPN. - */ - 'alpn_protocols': (string)[]; - /** - * Configs for fetching TLS certificates via SDS API. - */ - 'tls_certificate_sds_secret_configs': (_envoy_api_v2_auth_SdsSecretConfig__Output)[]; - /** - * Config for fetching validation context via SDS API. - */ - 'validation_context_sds_secret_config'?: (_envoy_api_v2_auth_SdsSecretConfig__Output); - /** - * Combined certificate validation context holds a default CertificateValidationContext - * and SDS config. When SDS server returns dynamic CertificateValidationContext, both dynamic - * and default CertificateValidationContext are merged into a new CertificateValidationContext - * for validation. This merge is done by Message::MergeFrom(), so dynamic - * CertificateValidationContext overwrites singular fields in default - * CertificateValidationContext, and concatenates repeated fields to default - * CertificateValidationContext, and logical OR is applied to boolean fields. - */ - 'combined_validation_context'?: (_envoy_api_v2_auth_CommonTlsContext_CombinedCertificateValidationContext__Output); - 'validation_context_type': "validation_context"|"validation_context_sds_secret_config"|"combined_validation_context"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/DownstreamTlsContext.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/DownstreamTlsContext.ts deleted file mode 100644 index ef9a6f9a4..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/DownstreamTlsContext.ts +++ /dev/null @@ -1,101 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/tls.proto - -import type { CommonTlsContext as _envoy_api_v2_auth_CommonTlsContext, CommonTlsContext__Output as _envoy_api_v2_auth_CommonTlsContext__Output } from '../../../../envoy/api/v2/auth/CommonTlsContext'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { TlsSessionTicketKeys as _envoy_api_v2_auth_TlsSessionTicketKeys, TlsSessionTicketKeys__Output as _envoy_api_v2_auth_TlsSessionTicketKeys__Output } from '../../../../envoy/api/v2/auth/TlsSessionTicketKeys'; -import type { SdsSecretConfig as _envoy_api_v2_auth_SdsSecretConfig, SdsSecretConfig__Output as _envoy_api_v2_auth_SdsSecretConfig__Output } from '../../../../envoy/api/v2/auth/SdsSecretConfig'; -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; - -/** - * [#next-free-field: 8] - */ -export interface DownstreamTlsContext { - /** - * Common TLS context settings. - */ - 'common_tls_context'?: (_envoy_api_v2_auth_CommonTlsContext); - /** - * If specified, Envoy will reject connections without a valid client - * certificate. - */ - 'require_client_certificate'?: (_google_protobuf_BoolValue); - /** - * If specified, Envoy will reject connections without a valid and matching SNI. - * [#not-implemented-hide:] - */ - 'require_sni'?: (_google_protobuf_BoolValue); - /** - * TLS session ticket key settings. - */ - 'session_ticket_keys'?: (_envoy_api_v2_auth_TlsSessionTicketKeys); - /** - * Config for fetching TLS session ticket keys via SDS API. - */ - 'session_ticket_keys_sds_secret_config'?: (_envoy_api_v2_auth_SdsSecretConfig); - /** - * If specified, session_timeout will change maximum lifetime (in seconds) of TLS session - * Currently this value is used as a hint to `TLS session ticket lifetime (for TLSv1.2) - * ` - * only seconds could be specified (fractional seconds are going to be ignored). - */ - 'session_timeout'?: (_google_protobuf_Duration); - /** - * Config for controlling stateless TLS session resumption: setting this to true will cause the TLS - * server to not issue TLS session tickets for the purposes of stateless TLS session resumption. - * If set to false, the TLS server will issue TLS session tickets and encrypt/decrypt them using - * the keys specified through either :ref:`session_ticket_keys ` - * or :ref:`session_ticket_keys_sds_secret_config `. - * If this config is set to false and no keys are explicitly configured, the TLS server will issue - * TLS session tickets and encrypt/decrypt them using an internally-generated and managed key, with the - * implication that sessions cannot be resumed across hot restarts or on different hosts. - */ - 'disable_stateless_session_resumption'?: (boolean); - 'session_ticket_keys_type'?: "session_ticket_keys"|"session_ticket_keys_sds_secret_config"|"disable_stateless_session_resumption"; -} - -/** - * [#next-free-field: 8] - */ -export interface DownstreamTlsContext__Output { - /** - * Common TLS context settings. - */ - 'common_tls_context'?: (_envoy_api_v2_auth_CommonTlsContext__Output); - /** - * If specified, Envoy will reject connections without a valid client - * certificate. - */ - 'require_client_certificate'?: (_google_protobuf_BoolValue__Output); - /** - * If specified, Envoy will reject connections without a valid and matching SNI. - * [#not-implemented-hide:] - */ - 'require_sni'?: (_google_protobuf_BoolValue__Output); - /** - * TLS session ticket key settings. - */ - 'session_ticket_keys'?: (_envoy_api_v2_auth_TlsSessionTicketKeys__Output); - /** - * Config for fetching TLS session ticket keys via SDS API. - */ - 'session_ticket_keys_sds_secret_config'?: (_envoy_api_v2_auth_SdsSecretConfig__Output); - /** - * If specified, session_timeout will change maximum lifetime (in seconds) of TLS session - * Currently this value is used as a hint to `TLS session ticket lifetime (for TLSv1.2) - * ` - * only seconds could be specified (fractional seconds are going to be ignored). - */ - 'session_timeout'?: (_google_protobuf_Duration__Output); - /** - * Config for controlling stateless TLS session resumption: setting this to true will cause the TLS - * server to not issue TLS session tickets for the purposes of stateless TLS session resumption. - * If set to false, the TLS server will issue TLS session tickets and encrypt/decrypt them using - * the keys specified through either :ref:`session_ticket_keys ` - * or :ref:`session_ticket_keys_sds_secret_config `. - * If this config is set to false and no keys are explicitly configured, the TLS server will issue - * TLS session tickets and encrypt/decrypt them using an internally-generated and managed key, with the - * implication that sessions cannot be resumed across hot restarts or on different hosts. - */ - 'disable_stateless_session_resumption'?: (boolean); - 'session_ticket_keys_type': "session_ticket_keys"|"session_ticket_keys_sds_secret_config"|"disable_stateless_session_resumption"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/GenericSecret.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/GenericSecret.ts deleted file mode 100644 index d7b712525..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/GenericSecret.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/secret.proto - -import type { DataSource as _envoy_api_v2_core_DataSource, DataSource__Output as _envoy_api_v2_core_DataSource__Output } from '../../../../envoy/api/v2/core/DataSource'; - -export interface GenericSecret { - /** - * Secret of generic type and is available to filters. - */ - 'secret'?: (_envoy_api_v2_core_DataSource); -} - -export interface GenericSecret__Output { - /** - * Secret of generic type and is available to filters. - */ - 'secret'?: (_envoy_api_v2_core_DataSource__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/SdsSecretConfig.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/SdsSecretConfig.ts deleted file mode 100644 index 888059332..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/SdsSecretConfig.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/secret.proto - -import type { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../../envoy/api/v2/core/ConfigSource'; - -export interface SdsSecretConfig { - /** - * Name (FQDN, UUID, SPKI, SHA256, etc.) by which the secret can be uniquely referred to. - * When both name and config are specified, then secret can be fetched and/or reloaded via - * SDS. When only name is specified, then secret will be loaded from static resources. - */ - 'name'?: (string); - 'sds_config'?: (_envoy_api_v2_core_ConfigSource); -} - -export interface SdsSecretConfig__Output { - /** - * Name (FQDN, UUID, SPKI, SHA256, etc.) by which the secret can be uniquely referred to. - * When both name and config are specified, then secret can be fetched and/or reloaded via - * SDS. When only name is specified, then secret will be loaded from static resources. - */ - 'name': (string); - 'sds_config'?: (_envoy_api_v2_core_ConfigSource__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/Secret.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/Secret.ts deleted file mode 100644 index 0768daed8..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/Secret.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/secret.proto - -import type { TlsCertificate as _envoy_api_v2_auth_TlsCertificate, TlsCertificate__Output as _envoy_api_v2_auth_TlsCertificate__Output } from '../../../../envoy/api/v2/auth/TlsCertificate'; -import type { TlsSessionTicketKeys as _envoy_api_v2_auth_TlsSessionTicketKeys, TlsSessionTicketKeys__Output as _envoy_api_v2_auth_TlsSessionTicketKeys__Output } from '../../../../envoy/api/v2/auth/TlsSessionTicketKeys'; -import type { CertificateValidationContext as _envoy_api_v2_auth_CertificateValidationContext, CertificateValidationContext__Output as _envoy_api_v2_auth_CertificateValidationContext__Output } from '../../../../envoy/api/v2/auth/CertificateValidationContext'; -import type { GenericSecret as _envoy_api_v2_auth_GenericSecret, GenericSecret__Output as _envoy_api_v2_auth_GenericSecret__Output } from '../../../../envoy/api/v2/auth/GenericSecret'; - -/** - * [#next-free-field: 6] - */ -export interface Secret { - /** - * Name (FQDN, UUID, SPKI, SHA256, etc.) by which the secret can be uniquely referred to. - */ - 'name'?: (string); - 'tls_certificate'?: (_envoy_api_v2_auth_TlsCertificate); - 'session_ticket_keys'?: (_envoy_api_v2_auth_TlsSessionTicketKeys); - 'validation_context'?: (_envoy_api_v2_auth_CertificateValidationContext); - 'generic_secret'?: (_envoy_api_v2_auth_GenericSecret); - 'type'?: "tls_certificate"|"session_ticket_keys"|"validation_context"|"generic_secret"; -} - -/** - * [#next-free-field: 6] - */ -export interface Secret__Output { - /** - * Name (FQDN, UUID, SPKI, SHA256, etc.) by which the secret can be uniquely referred to. - */ - 'name': (string); - 'tls_certificate'?: (_envoy_api_v2_auth_TlsCertificate__Output); - 'session_ticket_keys'?: (_envoy_api_v2_auth_TlsSessionTicketKeys__Output); - 'validation_context'?: (_envoy_api_v2_auth_CertificateValidationContext__Output); - 'generic_secret'?: (_envoy_api_v2_auth_GenericSecret__Output); - 'type': "tls_certificate"|"session_ticket_keys"|"validation_context"|"generic_secret"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsCertificate.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsCertificate.ts deleted file mode 100644 index dd7efcf21..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsCertificate.ts +++ /dev/null @@ -1,78 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/common.proto - -import type { DataSource as _envoy_api_v2_core_DataSource, DataSource__Output as _envoy_api_v2_core_DataSource__Output } from '../../../../envoy/api/v2/core/DataSource'; -import type { PrivateKeyProvider as _envoy_api_v2_auth_PrivateKeyProvider, PrivateKeyProvider__Output as _envoy_api_v2_auth_PrivateKeyProvider__Output } from '../../../../envoy/api/v2/auth/PrivateKeyProvider'; - -/** - * [#next-free-field: 7] - */ -export interface TlsCertificate { - /** - * The TLS certificate chain. - */ - 'certificate_chain'?: (_envoy_api_v2_core_DataSource); - /** - * The TLS private key. - */ - 'private_key'?: (_envoy_api_v2_core_DataSource); - /** - * The password to decrypt the TLS private key. If this field is not set, it is assumed that the - * TLS private key is not password encrypted. - */ - 'password'?: (_envoy_api_v2_core_DataSource); - /** - * [#not-implemented-hide:] - */ - 'ocsp_staple'?: (_envoy_api_v2_core_DataSource); - /** - * [#not-implemented-hide:] - */ - 'signed_certificate_timestamp'?: (_envoy_api_v2_core_DataSource)[]; - /** - * BoringSSL private key method provider. This is an alternative to :ref:`private_key - * ` field. This can't be - * marked as ``oneof`` due to API compatibility reasons. Setting both :ref:`private_key - * ` and - * :ref:`private_key_provider - * ` fields will result in an - * error. - */ - 'private_key_provider'?: (_envoy_api_v2_auth_PrivateKeyProvider); -} - -/** - * [#next-free-field: 7] - */ -export interface TlsCertificate__Output { - /** - * The TLS certificate chain. - */ - 'certificate_chain'?: (_envoy_api_v2_core_DataSource__Output); - /** - * The TLS private key. - */ - 'private_key'?: (_envoy_api_v2_core_DataSource__Output); - /** - * The password to decrypt the TLS private key. If this field is not set, it is assumed that the - * TLS private key is not password encrypted. - */ - 'password'?: (_envoy_api_v2_core_DataSource__Output); - /** - * [#not-implemented-hide:] - */ - 'ocsp_staple'?: (_envoy_api_v2_core_DataSource__Output); - /** - * [#not-implemented-hide:] - */ - 'signed_certificate_timestamp': (_envoy_api_v2_core_DataSource__Output)[]; - /** - * BoringSSL private key method provider. This is an alternative to :ref:`private_key - * ` field. This can't be - * marked as ``oneof`` due to API compatibility reasons. Setting both :ref:`private_key - * ` and - * :ref:`private_key_provider - * ` fields will result in an - * error. - */ - 'private_key_provider'?: (_envoy_api_v2_auth_PrivateKeyProvider__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/UpstreamTlsContext.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/UpstreamTlsContext.ts deleted file mode 100644 index b9dc4414f..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/UpstreamTlsContext.ts +++ /dev/null @@ -1,68 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/tls.proto - -import type { CommonTlsContext as _envoy_api_v2_auth_CommonTlsContext, CommonTlsContext__Output as _envoy_api_v2_auth_CommonTlsContext__Output } from '../../../../envoy/api/v2/auth/CommonTlsContext'; -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; - -export interface UpstreamTlsContext { - /** - * Common TLS context settings. - * - * .. attention:: - * - * Server certificate verification is not enabled by default. Configure - * :ref:`trusted_ca` to enable - * verification. - */ - 'common_tls_context'?: (_envoy_api_v2_auth_CommonTlsContext); - /** - * SNI string to use when creating TLS backend connections. - */ - 'sni'?: (string); - /** - * If true, server-initiated TLS renegotiation will be allowed. - * - * .. attention:: - * - * TLS renegotiation is considered insecure and shouldn't be used unless absolutely necessary. - */ - 'allow_renegotiation'?: (boolean); - /** - * Maximum number of session keys (Pre-Shared Keys for TLSv1.3+, Session IDs and Session Tickets - * for TLSv1.2 and older) to store for the purpose of session resumption. - * - * Defaults to 1, setting this to 0 disables session resumption. - */ - 'max_session_keys'?: (_google_protobuf_UInt32Value); -} - -export interface UpstreamTlsContext__Output { - /** - * Common TLS context settings. - * - * .. attention:: - * - * Server certificate verification is not enabled by default. Configure - * :ref:`trusted_ca` to enable - * verification. - */ - 'common_tls_context'?: (_envoy_api_v2_auth_CommonTlsContext__Output); - /** - * SNI string to use when creating TLS backend connections. - */ - 'sni': (string); - /** - * If true, server-initiated TLS renegotiation will be allowed. - * - * .. attention:: - * - * TLS renegotiation is considered insecure and shouldn't be used unless absolutely necessary. - */ - 'allow_renegotiation': (boolean); - /** - * Maximum number of session keys (Pre-Shared Keys for TLSv1.3+, Session IDs and Session Tickets - * for TLSv1.2 and older) to store for the purpose of session resumption. - * - * Defaults to 1, setting this to 0 disables session resumption. - */ - 'max_session_keys'?: (_google_protobuf_UInt32Value__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Address.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Address.ts deleted file mode 100644 index b12c8d9b0..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Address.ts +++ /dev/null @@ -1,26 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/address.proto - -import type { SocketAddress as _envoy_api_v2_core_SocketAddress, SocketAddress__Output as _envoy_api_v2_core_SocketAddress__Output } from '../../../../envoy/api/v2/core/SocketAddress'; -import type { Pipe as _envoy_api_v2_core_Pipe, Pipe__Output as _envoy_api_v2_core_Pipe__Output } from '../../../../envoy/api/v2/core/Pipe'; - -/** - * Addresses specify either a logical or physical address and port, which are - * used to tell Envoy where to bind/listen, connect to upstream and find - * management servers. - */ -export interface Address { - 'socket_address'?: (_envoy_api_v2_core_SocketAddress); - 'pipe'?: (_envoy_api_v2_core_Pipe); - 'address'?: "socket_address"|"pipe"; -} - -/** - * Addresses specify either a logical or physical address and port, which are - * used to tell Envoy where to bind/listen, connect to upstream and find - * management servers. - */ -export interface Address__Output { - 'socket_address'?: (_envoy_api_v2_core_SocketAddress__Output); - 'pipe'?: (_envoy_api_v2_core_Pipe__Output); - 'address': "socket_address"|"pipe"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/AsyncDataSource.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/AsyncDataSource.ts deleted file mode 100644 index fb312bb40..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/AsyncDataSource.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto - -import type { DataSource as _envoy_api_v2_core_DataSource, DataSource__Output as _envoy_api_v2_core_DataSource__Output } from '../../../../envoy/api/v2/core/DataSource'; -import type { RemoteDataSource as _envoy_api_v2_core_RemoteDataSource, RemoteDataSource__Output as _envoy_api_v2_core_RemoteDataSource__Output } from '../../../../envoy/api/v2/core/RemoteDataSource'; - -/** - * Async data source which support async data fetch. - */ -export interface AsyncDataSource { - /** - * Local async data source. - */ - 'local'?: (_envoy_api_v2_core_DataSource); - /** - * Remote async data source. - */ - 'remote'?: (_envoy_api_v2_core_RemoteDataSource); - 'specifier'?: "local"|"remote"; -} - -/** - * Async data source which support async data fetch. - */ -export interface AsyncDataSource__Output { - /** - * Local async data source. - */ - 'local'?: (_envoy_api_v2_core_DataSource__Output); - /** - * Remote async data source. - */ - 'remote'?: (_envoy_api_v2_core_RemoteDataSource__Output); - 'specifier': "local"|"remote"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/GrpcProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/GrpcProtocolOptions.ts deleted file mode 100644 index 66723801e..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/GrpcProtocolOptions.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/protocol.proto - -import type { Http2ProtocolOptions as _envoy_api_v2_core_Http2ProtocolOptions, Http2ProtocolOptions__Output as _envoy_api_v2_core_Http2ProtocolOptions__Output } from '../../../../envoy/api/v2/core/Http2ProtocolOptions'; - -/** - * [#not-implemented-hide:] - */ -export interface GrpcProtocolOptions { - 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions); -} - -/** - * [#not-implemented-hide:] - */ -export interface GrpcProtocolOptions__Output { - 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderMap.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderMap.ts deleted file mode 100644 index e093d4761..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderMap.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto - -import type { HeaderValue as _envoy_api_v2_core_HeaderValue, HeaderValue__Output as _envoy_api_v2_core_HeaderValue__Output } from '../../../../envoy/api/v2/core/HeaderValue'; - -/** - * Wrapper for a set of headers. - */ -export interface HeaderMap { - 'headers'?: (_envoy_api_v2_core_HeaderValue)[]; -} - -/** - * Wrapper for a set of headers. - */ -export interface HeaderMap__Output { - 'headers': (_envoy_api_v2_core_HeaderValue__Output)[]; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderValueOption.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderValueOption.ts deleted file mode 100644 index b90bd85e1..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderValueOption.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto - -import type { HeaderValue as _envoy_api_v2_core_HeaderValue, HeaderValue__Output as _envoy_api_v2_core_HeaderValue__Output } from '../../../../envoy/api/v2/core/HeaderValue'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; - -/** - * Header name/value pair plus option to control append behavior. - */ -export interface HeaderValueOption { - /** - * Header name/value pair that this option applies to. - */ - 'header'?: (_envoy_api_v2_core_HeaderValue); - /** - * Should the value be appended? If true (default), the value is appended to - * existing values. - */ - 'append'?: (_google_protobuf_BoolValue); -} - -/** - * Header name/value pair plus option to control append behavior. - */ -export interface HeaderValueOption__Output { - /** - * Header name/value pair that this option applies to. - */ - 'header'?: (_envoy_api_v2_core_HeaderValue__Output); - /** - * Should the value be appended? If true (default), the value is appended to - * existing values. - */ - 'append'?: (_google_protobuf_BoolValue__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Http1ProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Http1ProtocolOptions.ts deleted file mode 100644 index b9bb0ce54..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Http1ProtocolOptions.ts +++ /dev/null @@ -1,119 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/protocol.proto - -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; - -export interface _envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat { - /** - * Formats the header by proper casing words: the first character and any character following - * a special character will be capitalized if it's an alpha character. For example, - * "content-type" becomes "Content-Type", and "foo$b#$are" becomes "Foo$B#$Are". - * Note that while this results in most headers following conventional casing, certain headers - * are not covered. For example, the "TE" header will be formatted as "Te". - */ - 'proper_case_words'?: (_envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords); - 'header_format'?: "proper_case_words"; -} - -export interface _envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat__Output { - /** - * Formats the header by proper casing words: the first character and any character following - * a special character will be capitalized if it's an alpha character. For example, - * "content-type" becomes "Content-Type", and "foo$b#$are" becomes "Foo$B#$Are". - * Note that while this results in most headers following conventional casing, certain headers - * are not covered. For example, the "TE" header will be formatted as "Te". - */ - 'proper_case_words'?: (_envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords__Output); - 'header_format': "proper_case_words"; -} - -export interface _envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords { -} - -export interface _envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords__Output { -} - -/** - * [#next-free-field: 6] - */ -export interface Http1ProtocolOptions { - /** - * Handle HTTP requests with absolute URLs in the requests. These requests - * are generally sent by clients to forward/explicit proxies. This allows clients to configure - * envoy as their HTTP proxy. In Unix, for example, this is typically done by setting the - * *http_proxy* environment variable. - */ - 'allow_absolute_url'?: (_google_protobuf_BoolValue); - /** - * Handle incoming HTTP/1.0 and HTTP 0.9 requests. - * This is off by default, and not fully standards compliant. There is support for pre-HTTP/1.1 - * style connect logic, dechunking, and handling lack of client host iff - * *default_host_for_http_10* is configured. - */ - 'accept_http_10'?: (boolean); - /** - * A default host for HTTP/1.0 requests. This is highly suggested if *accept_http_10* is true as - * Envoy does not otherwise support HTTP/1.0 without a Host header. - * This is a no-op if *accept_http_10* is not true. - */ - 'default_host_for_http_10'?: (string); - /** - * Describes how the keys for response headers should be formatted. By default, all header keys - * are lower cased. - */ - 'header_key_format'?: (_envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat); - /** - * Enables trailers for HTTP/1. By default the HTTP/1 codec drops proxied trailers. - * - * .. attention:: - * - * Note that this only happens when Envoy is chunk encoding which occurs when: - * - The request is HTTP/1.1. - * - Is neither a HEAD only request nor a HTTP Upgrade. - * - Not a response to a HEAD request. - * - The content length header is not present. - */ - 'enable_trailers'?: (boolean); -} - -/** - * [#next-free-field: 6] - */ -export interface Http1ProtocolOptions__Output { - /** - * Handle HTTP requests with absolute URLs in the requests. These requests - * are generally sent by clients to forward/explicit proxies. This allows clients to configure - * envoy as their HTTP proxy. In Unix, for example, this is typically done by setting the - * *http_proxy* environment variable. - */ - 'allow_absolute_url'?: (_google_protobuf_BoolValue__Output); - /** - * Handle incoming HTTP/1.0 and HTTP 0.9 requests. - * This is off by default, and not fully standards compliant. There is support for pre-HTTP/1.1 - * style connect logic, dechunking, and handling lack of client host iff - * *default_host_for_http_10* is configured. - */ - 'accept_http_10': (boolean); - /** - * A default host for HTTP/1.0 requests. This is highly suggested if *accept_http_10* is true as - * Envoy does not otherwise support HTTP/1.0 without a Host header. - * This is a no-op if *accept_http_10* is not true. - */ - 'default_host_for_http_10': (string); - /** - * Describes how the keys for response headers should be formatted. By default, all header keys - * are lower cased. - */ - 'header_key_format'?: (_envoy_api_v2_core_Http1ProtocolOptions_HeaderKeyFormat__Output); - /** - * Enables trailers for HTTP/1. By default the HTTP/1 codec drops proxied trailers. - * - * .. attention:: - * - * Note that this only happens when Envoy is chunk encoding which occurs when: - * - The request is HTTP/1.1. - * - Is neither a HEAD only request nor a HTTP Upgrade. - * - Not a response to a HEAD request. - * - The content length header is not present. - */ - 'enable_trailers': (boolean); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RemoteDataSource.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RemoteDataSource.ts deleted file mode 100644 index 93e722eef..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RemoteDataSource.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto - -import type { HttpUri as _envoy_api_v2_core_HttpUri, HttpUri__Output as _envoy_api_v2_core_HttpUri__Output } from '../../../../envoy/api/v2/core/HttpUri'; -import type { RetryPolicy as _envoy_api_v2_core_RetryPolicy, RetryPolicy__Output as _envoy_api_v2_core_RetryPolicy__Output } from '../../../../envoy/api/v2/core/RetryPolicy'; - -/** - * The message specifies how to fetch data from remote and how to verify it. - */ -export interface RemoteDataSource { - /** - * The HTTP URI to fetch the remote data. - */ - 'http_uri'?: (_envoy_api_v2_core_HttpUri); - /** - * SHA256 string for verifying data. - */ - 'sha256'?: (string); - /** - * Retry policy for fetching remote data. - */ - 'retry_policy'?: (_envoy_api_v2_core_RetryPolicy); -} - -/** - * The message specifies how to fetch data from remote and how to verify it. - */ -export interface RemoteDataSource__Output { - /** - * The HTTP URI to fetch the remote data. - */ - 'http_uri'?: (_envoy_api_v2_core_HttpUri__Output); - /** - * SHA256 string for verifying data. - */ - 'sha256': (string); - /** - * Retry policy for fetching remote data. - */ - 'retry_policy'?: (_envoy_api_v2_core_RetryPolicy__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/SelfConfigSource.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/SelfConfigSource.ts deleted file mode 100644 index 144cfdf5a..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/SelfConfigSource.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/config_source.proto - - -/** - * [#not-implemented-hide:] - * Self-referencing config source options. This is currently empty, but when - * set in :ref:`ConfigSource ` can be used to - * specify that other data can be obtained from the same server. - */ -export interface SelfConfigSource { -} - -/** - * [#not-implemented-hide:] - * Self-referencing config source options. This is currently empty, but when - * set in :ref:`ConfigSource ` can be used to - * specify that other data can be obtained from the same server. - */ -export interface SelfConfigSource__Output { -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/UpstreamHttpProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/core/UpstreamHttpProtocolOptions.ts deleted file mode 100644 index 9c55560e8..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/UpstreamHttpProtocolOptions.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/protocol.proto - - -export interface UpstreamHttpProtocolOptions { - /** - * Set transport socket `SNI `_ for new - * upstream connections based on the downstream HTTP host/authority header, as seen by the - * :ref:`router filter `. - */ - 'auto_sni'?: (boolean); - /** - * Automatic validate upstream presented certificate for new upstream connections based on the - * downstream HTTP host/authority header, as seen by the - * :ref:`router filter `. - * This field is intended to set with `auto_sni` field. - */ - 'auto_san_validation'?: (boolean); -} - -export interface UpstreamHttpProtocolOptions__Output { - /** - * Set transport socket `SNI `_ for new - * upstream connections based on the downstream HTTP host/authority header, as seen by the - * :ref:`router filter `. - */ - 'auto_sni': (boolean); - /** - * Automatic validate upstream presented certificate for new upstream connections based on the - * downstream HTTP host/authority header, as seen by the - * :ref:`router filter `. - * This field is intended to set with `auto_sni` field. - */ - 'auto_san_validation': (boolean); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/Filter.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/Filter.ts deleted file mode 100644 index 2c6e0d087..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/Filter.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener/listener_components.proto - -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; - -export interface Filter { - /** - * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. - */ - 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - /** - * Filter specific configuration which depends on the filter being - * instantiated. See the supported filters for further documentation. - */ - 'config_type'?: "config"|"typed_config"; -} - -export interface Filter__Output { - /** - * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. - */ - 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - /** - * Filter specific configuration which depends on the filter being - * instantiated. See the supported filters for further documentation. - */ - 'config_type': "config"|"typed_config"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/FilterChain.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/FilterChain.ts deleted file mode 100644 index 1e98abe50..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/FilterChain.ts +++ /dev/null @@ -1,118 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener/listener_components.proto - -import type { FilterChainMatch as _envoy_api_v2_listener_FilterChainMatch, FilterChainMatch__Output as _envoy_api_v2_listener_FilterChainMatch__Output } from '../../../../envoy/api/v2/listener/FilterChainMatch'; -import type { DownstreamTlsContext as _envoy_api_v2_auth_DownstreamTlsContext, DownstreamTlsContext__Output as _envoy_api_v2_auth_DownstreamTlsContext__Output } from '../../../../envoy/api/v2/auth/DownstreamTlsContext'; -import type { Filter as _envoy_api_v2_listener_Filter, Filter__Output as _envoy_api_v2_listener_Filter__Output } from '../../../../envoy/api/v2/listener/Filter'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { Metadata as _envoy_api_v2_core_Metadata, Metadata__Output as _envoy_api_v2_core_Metadata__Output } from '../../../../envoy/api/v2/core/Metadata'; -import type { TransportSocket as _envoy_api_v2_core_TransportSocket, TransportSocket__Output as _envoy_api_v2_core_TransportSocket__Output } from '../../../../envoy/api/v2/core/TransportSocket'; - -/** - * A filter chain wraps a set of match criteria, an option TLS context, a set of filters, and - * various other parameters. - * [#next-free-field: 8] - */ -export interface FilterChain { - /** - * The criteria to use when matching a connection to this filter chain. - */ - 'filter_chain_match'?: (_envoy_api_v2_listener_FilterChainMatch); - /** - * The TLS context for this filter chain. - * - * .. attention:: - * - * **This field is deprecated**. Use `transport_socket` with name `tls` instead. If both are - * set, `transport_socket` takes priority. - */ - 'tls_context'?: (_envoy_api_v2_auth_DownstreamTlsContext); - /** - * A list of individual network filters that make up the filter chain for - * connections established with the listener. Order matters as the filters are - * processed sequentially as connection events happen. Note: If the filter - * list is empty, the connection will close by default. - */ - 'filters'?: (_envoy_api_v2_listener_Filter)[]; - /** - * Whether the listener should expect a PROXY protocol V1 header on new - * connections. If this option is enabled, the listener will assume that that - * remote address of the connection is the one specified in the header. Some - * load balancers including the AWS ELB support this option. If the option is - * absent or set to false, Envoy will use the physical peer address of the - * connection as the remote address. - */ - 'use_proxy_proto'?: (_google_protobuf_BoolValue); - /** - * [#not-implemented-hide:] filter chain metadata. - */ - 'metadata'?: (_envoy_api_v2_core_Metadata); - /** - * Optional custom transport socket implementation to use for downstream connections. - * To setup TLS, set a transport socket with name `tls` and - * :ref:`DownstreamTlsContext ` in the `typed_config`. - * If no transport socket configuration is specified, new connections - * will be set up with plaintext. - */ - 'transport_socket'?: (_envoy_api_v2_core_TransportSocket); - /** - * [#not-implemented-hide:] The unique name (or empty) by which this filter chain is known. If no - * name is provided, Envoy will allocate an internal UUID for the filter chain. If the filter - * chain is to be dynamically updated or removed via FCDS a unique name must be provided. - */ - 'name'?: (string); -} - -/** - * A filter chain wraps a set of match criteria, an option TLS context, a set of filters, and - * various other parameters. - * [#next-free-field: 8] - */ -export interface FilterChain__Output { - /** - * The criteria to use when matching a connection to this filter chain. - */ - 'filter_chain_match'?: (_envoy_api_v2_listener_FilterChainMatch__Output); - /** - * The TLS context for this filter chain. - * - * .. attention:: - * - * **This field is deprecated**. Use `transport_socket` with name `tls` instead. If both are - * set, `transport_socket` takes priority. - */ - 'tls_context'?: (_envoy_api_v2_auth_DownstreamTlsContext__Output); - /** - * A list of individual network filters that make up the filter chain for - * connections established with the listener. Order matters as the filters are - * processed sequentially as connection events happen. Note: If the filter - * list is empty, the connection will close by default. - */ - 'filters': (_envoy_api_v2_listener_Filter__Output)[]; - /** - * Whether the listener should expect a PROXY protocol V1 header on new - * connections. If this option is enabled, the listener will assume that that - * remote address of the connection is the one specified in the header. Some - * load balancers including the AWS ELB support this option. If the option is - * absent or set to false, Envoy will use the physical peer address of the - * connection as the remote address. - */ - 'use_proxy_proto'?: (_google_protobuf_BoolValue__Output); - /** - * [#not-implemented-hide:] filter chain metadata. - */ - 'metadata'?: (_envoy_api_v2_core_Metadata__Output); - /** - * Optional custom transport socket implementation to use for downstream connections. - * To setup TLS, set a transport socket with name `tls` and - * :ref:`DownstreamTlsContext ` in the `typed_config`. - * If no transport socket configuration is specified, new connections - * will be set up with plaintext. - */ - 'transport_socket'?: (_envoy_api_v2_core_TransportSocket__Output); - /** - * [#not-implemented-hide:] The unique name (or empty) by which this filter chain is known. If no - * name is provided, Envoy will allocate an internal UUID for the filter chain. If the filter - * chain is to be dynamically updated or removed via FCDS a unique name must be provided. - */ - 'name': (string); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ListenerFilter.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ListenerFilter.ts deleted file mode 100644 index 080d922b1..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ListenerFilter.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener/listener_components.proto - -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; -import type { ListenerFilterChainMatchPredicate as _envoy_api_v2_listener_ListenerFilterChainMatchPredicate, ListenerFilterChainMatchPredicate__Output as _envoy_api_v2_listener_ListenerFilterChainMatchPredicate__Output } from '../../../../envoy/api/v2/listener/ListenerFilterChainMatchPredicate'; - -export interface ListenerFilter { - /** - * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. - */ - 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - /** - * Optional match predicate used to disable the filter. The filter is enabled when this field is empty. - * See :ref:`ListenerFilterChainMatchPredicate ` - * for further examples. - */ - 'filter_disabled'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate); - /** - * Filter specific configuration which depends on the filter being instantiated. - * See the supported filters for further documentation. - */ - 'config_type'?: "config"|"typed_config"; -} - -export interface ListenerFilter__Output { - /** - * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. - */ - 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - /** - * Optional match predicate used to disable the filter. The filter is enabled when this field is empty. - * See :ref:`ListenerFilterChainMatchPredicate ` - * for further examples. - */ - 'filter_disabled'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate__Output); - /** - * Filter specific configuration which depends on the filter being instantiated. - * See the supported filters for further documentation. - */ - 'config_type': "config"|"typed_config"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/UdpListenerConfig.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/UdpListenerConfig.ts deleted file mode 100644 index 2299c5719..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/UdpListenerConfig.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener/udp_listener_config.proto - -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; - -export interface UdpListenerConfig { - /** - * Used to look up UDP listener factory, matches "raw_udp_listener" or - * "quic_listener" to create a specific udp listener. - * If not specified, treat as "raw_udp_listener". - */ - 'udp_listener_name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - /** - * Used to create a specific listener factory. To some factory, e.g. - * "raw_udp_listener", config is not needed. - */ - 'config_type'?: "config"|"typed_config"; -} - -export interface UdpListenerConfig__Output { - /** - * Used to look up UDP listener factory, matches "raw_udp_listener" or - * "quic_listener" to create a specific udp listener. - * If not specified, treat as "raw_udp_listener". - */ - 'udp_listener_name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - /** - * Used to create a specific listener factory. To some factory, e.g. - * "raw_udp_listener", config is not needed. - */ - 'config_type': "config"|"typed_config"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/CorsPolicy.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/route/CorsPolicy.ts deleted file mode 100644 index 7b76b9d85..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/CorsPolicy.ts +++ /dev/null @@ -1,169 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto - -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { RuntimeFractionalPercent as _envoy_api_v2_core_RuntimeFractionalPercent, RuntimeFractionalPercent__Output as _envoy_api_v2_core_RuntimeFractionalPercent__Output } from '../../../../envoy/api/v2/core/RuntimeFractionalPercent'; -import type { StringMatcher as _envoy_type_matcher_StringMatcher, StringMatcher__Output as _envoy_type_matcher_StringMatcher__Output } from '../../../../envoy/type/matcher/StringMatcher'; - -/** - * [#next-free-field: 12] - */ -export interface CorsPolicy { - /** - * Specifies the origins that will be allowed to do CORS requests. - * - * An origin is allowed if either allow_origin or allow_origin_regex match. - * - * .. attention:: - * This field has been deprecated in favor of `allow_origin_string_match`. - */ - 'allow_origin'?: (string)[]; - /** - * Specifies the content for the *access-control-allow-methods* header. - */ - 'allow_methods'?: (string); - /** - * Specifies the content for the *access-control-allow-headers* header. - */ - 'allow_headers'?: (string); - /** - * Specifies the content for the *access-control-expose-headers* header. - */ - 'expose_headers'?: (string); - /** - * Specifies the content for the *access-control-max-age* header. - */ - 'max_age'?: (string); - /** - * Specifies whether the resource allows credentials. - */ - 'allow_credentials'?: (_google_protobuf_BoolValue); - /** - * Specifies if the CORS filter is enabled. Defaults to true. Only effective on route. - * - * .. attention:: - * - * **This field is deprecated**. Set the - * :ref:`filter_enabled` field instead. - */ - 'enabled'?: (_google_protobuf_BoolValue); - /** - * Specifies regex patterns that match allowed origins. - * - * An origin is allowed if either allow_origin or allow_origin_regex match. - * - * .. attention:: - * This field has been deprecated in favor of `allow_origin_string_match` as it is not safe for - * use with untrusted input in all cases. - */ - 'allow_origin_regex'?: (string)[]; - /** - * Specifies the % of requests for which the CORS filter is enabled. - * - * If neither ``enabled``, ``filter_enabled``, nor ``shadow_enabled`` are specified, the CORS - * filter will be enabled for 100% of the requests. - * - * If :ref:`runtime_key ` is - * specified, Envoy will lookup the runtime key to get the percentage of requests to filter. - */ - 'filter_enabled'?: (_envoy_api_v2_core_RuntimeFractionalPercent); - /** - * Specifies the % of requests for which the CORS policies will be evaluated and tracked, but not - * enforced. - * - * This field is intended to be used when ``filter_enabled`` and ``enabled`` are off. One of those - * fields have to explicitly disable the filter in order for this setting to take effect. - * - * If :ref:`runtime_key ` is specified, - * Envoy will lookup the runtime key to get the percentage of requests for which it will evaluate - * and track the request's *Origin* to determine if it's valid but will not enforce any policies. - */ - 'shadow_enabled'?: (_envoy_api_v2_core_RuntimeFractionalPercent); - /** - * Specifies string patterns that match allowed origins. An origin is allowed if any of the - * string matchers match. - */ - 'allow_origin_string_match'?: (_envoy_type_matcher_StringMatcher)[]; - 'enabled_specifier'?: "enabled"|"filter_enabled"; -} - -/** - * [#next-free-field: 12] - */ -export interface CorsPolicy__Output { - /** - * Specifies the origins that will be allowed to do CORS requests. - * - * An origin is allowed if either allow_origin or allow_origin_regex match. - * - * .. attention:: - * This field has been deprecated in favor of `allow_origin_string_match`. - */ - 'allow_origin': (string)[]; - /** - * Specifies the content for the *access-control-allow-methods* header. - */ - 'allow_methods': (string); - /** - * Specifies the content for the *access-control-allow-headers* header. - */ - 'allow_headers': (string); - /** - * Specifies the content for the *access-control-expose-headers* header. - */ - 'expose_headers': (string); - /** - * Specifies the content for the *access-control-max-age* header. - */ - 'max_age': (string); - /** - * Specifies whether the resource allows credentials. - */ - 'allow_credentials'?: (_google_protobuf_BoolValue__Output); - /** - * Specifies if the CORS filter is enabled. Defaults to true. Only effective on route. - * - * .. attention:: - * - * **This field is deprecated**. Set the - * :ref:`filter_enabled` field instead. - */ - 'enabled'?: (_google_protobuf_BoolValue__Output); - /** - * Specifies regex patterns that match allowed origins. - * - * An origin is allowed if either allow_origin or allow_origin_regex match. - * - * .. attention:: - * This field has been deprecated in favor of `allow_origin_string_match` as it is not safe for - * use with untrusted input in all cases. - */ - 'allow_origin_regex': (string)[]; - /** - * Specifies the % of requests for which the CORS filter is enabled. - * - * If neither ``enabled``, ``filter_enabled``, nor ``shadow_enabled`` are specified, the CORS - * filter will be enabled for 100% of the requests. - * - * If :ref:`runtime_key ` is - * specified, Envoy will lookup the runtime key to get the percentage of requests to filter. - */ - 'filter_enabled'?: (_envoy_api_v2_core_RuntimeFractionalPercent__Output); - /** - * Specifies the % of requests for which the CORS policies will be evaluated and tracked, but not - * enforced. - * - * This field is intended to be used when ``filter_enabled`` and ``enabled`` are off. One of those - * fields have to explicitly disable the filter in order for this setting to take effect. - * - * If :ref:`runtime_key ` is specified, - * Envoy will lookup the runtime key to get the percentage of requests for which it will evaluate - * and track the request's *Origin* to determine if it's valid but will not enforce any policies. - */ - 'shadow_enabled'?: (_envoy_api_v2_core_RuntimeFractionalPercent__Output); - /** - * Specifies string patterns that match allowed origins. An origin is allowed if any of the - * string matchers match. - */ - 'allow_origin_string_match': (_envoy_type_matcher_StringMatcher__Output)[]; - 'enabled_specifier': "enabled"|"filter_enabled"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/HedgePolicy.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/route/HedgePolicy.ts deleted file mode 100644 index 8134fc359..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/HedgePolicy.ts +++ /dev/null @@ -1,66 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto - -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -import type { FractionalPercent as _envoy_type_FractionalPercent, FractionalPercent__Output as _envoy_type_FractionalPercent__Output } from '../../../../envoy/type/FractionalPercent'; - -/** - * HTTP request hedging :ref:`architecture overview `. - */ -export interface HedgePolicy { - /** - * Specifies the number of initial requests that should be sent upstream. - * Must be at least 1. - * Defaults to 1. - * [#not-implemented-hide:] - */ - 'initial_requests'?: (_google_protobuf_UInt32Value); - /** - * Specifies a probability that an additional upstream request should be sent - * on top of what is specified by initial_requests. - * Defaults to 0. - * [#not-implemented-hide:] - */ - 'additional_request_chance'?: (_envoy_type_FractionalPercent); - /** - * Indicates that a hedged request should be sent when the per-try timeout - * is hit. This will only occur if the retry policy also indicates that a - * timed out request should be retried. - * Once a timed out request is retried due to per try timeout, the router - * filter will ensure that it is not retried again even if the returned - * response headers would otherwise be retried according the specified - * :ref:`RetryPolicy `. - * Defaults to false. - */ - 'hedge_on_per_try_timeout'?: (boolean); -} - -/** - * HTTP request hedging :ref:`architecture overview `. - */ -export interface HedgePolicy__Output { - /** - * Specifies the number of initial requests that should be sent upstream. - * Must be at least 1. - * Defaults to 1. - * [#not-implemented-hide:] - */ - 'initial_requests'?: (_google_protobuf_UInt32Value__Output); - /** - * Specifies a probability that an additional upstream request should be sent - * on top of what is specified by initial_requests. - * Defaults to 0. - * [#not-implemented-hide:] - */ - 'additional_request_chance'?: (_envoy_type_FractionalPercent__Output); - /** - * Indicates that a hedged request should be sent when the per-try timeout - * is hit. This will only occur if the retry policy also indicates that a - * timed out request should be retried. - * Once a timed out request is retried due to per try timeout, the router - * filter will ensure that it is not retried again even if the returned - * response headers would otherwise be retried according the specified - * :ref:`RetryPolicy `. - * Defaults to false. - */ - 'hedge_on_per_try_timeout': (boolean); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/QueryParameterMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/route/QueryParameterMatcher.ts deleted file mode 100644 index 68f4fbcaa..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/QueryParameterMatcher.ts +++ /dev/null @@ -1,86 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto - -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { StringMatcher as _envoy_type_matcher_StringMatcher, StringMatcher__Output as _envoy_type_matcher_StringMatcher__Output } from '../../../../envoy/type/matcher/StringMatcher'; - -/** - * Query parameter matching treats the query string of a request's :path header - * as an ampersand-separated list of keys and/or key=value elements. - * [#next-free-field: 7] - */ -export interface QueryParameterMatcher { - /** - * Specifies the name of a key that must be present in the requested - * *path*'s query string. - */ - 'name'?: (string); - /** - * Specifies the value of the key. If the value is absent, a request - * that contains the key in its query string will match, whether the - * key appears with a value (e.g., "?debug=true") or not (e.g., "?debug") - * - * ..attention:: - * This field is deprecated. Use an `exact` match inside the `string_match` field. - */ - 'value'?: (string); - /** - * Specifies whether the query parameter value is a regular expression. - * Defaults to false. The entire query parameter value (i.e., the part to - * the right of the equals sign in "key=value") must match the regex. - * E.g., the regex ``\d+$`` will match *123* but not *a123* or *123a*. - * - * ..attention:: - * This field is deprecated. Use a `safe_regex` match inside the `string_match` field. - */ - 'regex'?: (_google_protobuf_BoolValue); - /** - * Specifies whether a query parameter value should match against a string. - */ - 'string_match'?: (_envoy_type_matcher_StringMatcher); - /** - * Specifies whether a query parameter should be present. - */ - 'present_match'?: (boolean); - 'query_parameter_match_specifier'?: "string_match"|"present_match"; -} - -/** - * Query parameter matching treats the query string of a request's :path header - * as an ampersand-separated list of keys and/or key=value elements. - * [#next-free-field: 7] - */ -export interface QueryParameterMatcher__Output { - /** - * Specifies the name of a key that must be present in the requested - * *path*'s query string. - */ - 'name': (string); - /** - * Specifies the value of the key. If the value is absent, a request - * that contains the key in its query string will match, whether the - * key appears with a value (e.g., "?debug=true") or not (e.g., "?debug") - * - * ..attention:: - * This field is deprecated. Use an `exact` match inside the `string_match` field. - */ - 'value': (string); - /** - * Specifies whether the query parameter value is a regular expression. - * Defaults to false. The entire query parameter value (i.e., the part to - * the right of the equals sign in "key=value") must match the regex. - * E.g., the regex ``\d+$`` will match *123* but not *a123* or *123a*. - * - * ..attention:: - * This field is deprecated. Use a `safe_regex` match inside the `string_match` field. - */ - 'regex'?: (_google_protobuf_BoolValue__Output); - /** - * Specifies whether a query parameter value should match against a string. - */ - 'string_match'?: (_envoy_type_matcher_StringMatcher__Output); - /** - * Specifies whether a query parameter should be present. - */ - 'present_match'?: (boolean); - 'query_parameter_match_specifier': "string_match"|"present_match"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RateLimit.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RateLimit.ts deleted file mode 100644 index 998d94e53..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RateLimit.ts +++ /dev/null @@ -1,341 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto - -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { HeaderMatcher as _envoy_api_v2_route_HeaderMatcher, HeaderMatcher__Output as _envoy_api_v2_route_HeaderMatcher__Output } from '../../../../envoy/api/v2/route/HeaderMatcher'; - -/** - * [#next-free-field: 7] - */ -export interface _envoy_api_v2_route_RateLimit_Action { - /** - * Rate limit on source cluster. - */ - 'source_cluster'?: (_envoy_api_v2_route_RateLimit_Action_SourceCluster); - /** - * Rate limit on destination cluster. - */ - 'destination_cluster'?: (_envoy_api_v2_route_RateLimit_Action_DestinationCluster); - /** - * Rate limit on request headers. - */ - 'request_headers'?: (_envoy_api_v2_route_RateLimit_Action_RequestHeaders); - /** - * Rate limit on remote address. - */ - 'remote_address'?: (_envoy_api_v2_route_RateLimit_Action_RemoteAddress); - /** - * Rate limit on a generic key. - */ - 'generic_key'?: (_envoy_api_v2_route_RateLimit_Action_GenericKey); - /** - * Rate limit on the existence of request headers. - */ - 'header_value_match'?: (_envoy_api_v2_route_RateLimit_Action_HeaderValueMatch); - 'action_specifier'?: "source_cluster"|"destination_cluster"|"request_headers"|"remote_address"|"generic_key"|"header_value_match"; -} - -/** - * [#next-free-field: 7] - */ -export interface _envoy_api_v2_route_RateLimit_Action__Output { - /** - * Rate limit on source cluster. - */ - 'source_cluster'?: (_envoy_api_v2_route_RateLimit_Action_SourceCluster__Output); - /** - * Rate limit on destination cluster. - */ - 'destination_cluster'?: (_envoy_api_v2_route_RateLimit_Action_DestinationCluster__Output); - /** - * Rate limit on request headers. - */ - 'request_headers'?: (_envoy_api_v2_route_RateLimit_Action_RequestHeaders__Output); - /** - * Rate limit on remote address. - */ - 'remote_address'?: (_envoy_api_v2_route_RateLimit_Action_RemoteAddress__Output); - /** - * Rate limit on a generic key. - */ - 'generic_key'?: (_envoy_api_v2_route_RateLimit_Action_GenericKey__Output); - /** - * Rate limit on the existence of request headers. - */ - 'header_value_match'?: (_envoy_api_v2_route_RateLimit_Action_HeaderValueMatch__Output); - 'action_specifier': "source_cluster"|"destination_cluster"|"request_headers"|"remote_address"|"generic_key"|"header_value_match"; -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("destination_cluster", "") - * - * Once a request matches against a route table rule, a routed cluster is determined by one of - * the following :ref:`route table configuration ` - * settings: - * - * * :ref:`cluster ` indicates the upstream cluster - * to route to. - * * :ref:`weighted_clusters ` - * chooses a cluster randomly from a set of clusters with attributed weight. - * * :ref:`cluster_header ` indicates which - * header in the request contains the target cluster. - */ -export interface _envoy_api_v2_route_RateLimit_Action_DestinationCluster { -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("destination_cluster", "") - * - * Once a request matches against a route table rule, a routed cluster is determined by one of - * the following :ref:`route table configuration ` - * settings: - * - * * :ref:`cluster ` indicates the upstream cluster - * to route to. - * * :ref:`weighted_clusters ` - * chooses a cluster randomly from a set of clusters with attributed weight. - * * :ref:`cluster_header ` indicates which - * header in the request contains the target cluster. - */ -export interface _envoy_api_v2_route_RateLimit_Action_DestinationCluster__Output { -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("generic_key", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_GenericKey { - /** - * The value to use in the descriptor entry. - */ - 'descriptor_value'?: (string); -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("generic_key", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_GenericKey__Output { - /** - * The value to use in the descriptor entry. - */ - 'descriptor_value': (string); -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("header_match", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_HeaderValueMatch { - /** - * The value to use in the descriptor entry. - */ - 'descriptor_value'?: (string); - /** - * If set to true, the action will append a descriptor entry when the - * request matches the headers. If set to false, the action will append a - * descriptor entry when the request does not match the headers. The - * default value is true. - */ - 'expect_match'?: (_google_protobuf_BoolValue); - /** - * Specifies a set of headers that the rate limit action should match - * on. The action will check the request’s headers against all the - * specified headers in the config. A match will happen if all the - * headers in the config are present in the request with the same values - * (or based on presence if the value field is not in the config). - */ - 'headers'?: (_envoy_api_v2_route_HeaderMatcher)[]; -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("header_match", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_HeaderValueMatch__Output { - /** - * The value to use in the descriptor entry. - */ - 'descriptor_value': (string); - /** - * If set to true, the action will append a descriptor entry when the - * request matches the headers. If set to false, the action will append a - * descriptor entry when the request does not match the headers. The - * default value is true. - */ - 'expect_match'?: (_google_protobuf_BoolValue__Output); - /** - * Specifies a set of headers that the rate limit action should match - * on. The action will check the request’s headers against all the - * specified headers in the config. A match will happen if all the - * headers in the config are present in the request with the same values - * (or based on presence if the value field is not in the config). - */ - 'headers': (_envoy_api_v2_route_HeaderMatcher__Output)[]; -} - -/** - * The following descriptor entry is appended to the descriptor and is populated using the - * trusted address from :ref:`x-forwarded-for `: - * - * .. code-block:: cpp - * - * ("remote_address", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_RemoteAddress { -} - -/** - * The following descriptor entry is appended to the descriptor and is populated using the - * trusted address from :ref:`x-forwarded-for `: - * - * .. code-block:: cpp - * - * ("remote_address", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_RemoteAddress__Output { -} - -/** - * The following descriptor entry is appended when a header contains a key that matches the - * *header_name*: - * - * .. code-block:: cpp - * - * ("", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_RequestHeaders { - /** - * The header name to be queried from the request headers. The header’s - * value is used to populate the value of the descriptor entry for the - * descriptor_key. - */ - 'header_name'?: (string); - /** - * The key to use in the descriptor entry. - */ - 'descriptor_key'?: (string); -} - -/** - * The following descriptor entry is appended when a header contains a key that matches the - * *header_name*: - * - * .. code-block:: cpp - * - * ("", "") - */ -export interface _envoy_api_v2_route_RateLimit_Action_RequestHeaders__Output { - /** - * The header name to be queried from the request headers. The header’s - * value is used to populate the value of the descriptor entry for the - * descriptor_key. - */ - 'header_name': (string); - /** - * The key to use in the descriptor entry. - */ - 'descriptor_key': (string); -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("source_cluster", "") - * - * is derived from the :option:`--service-cluster` option. - */ -export interface _envoy_api_v2_route_RateLimit_Action_SourceCluster { -} - -/** - * The following descriptor entry is appended to the descriptor: - * - * .. code-block:: cpp - * - * ("source_cluster", "") - * - * is derived from the :option:`--service-cluster` option. - */ -export interface _envoy_api_v2_route_RateLimit_Action_SourceCluster__Output { -} - -/** - * Global rate limiting :ref:`architecture overview `. - */ -export interface RateLimit { - /** - * Refers to the stage set in the filter. The rate limit configuration only - * applies to filters with the same stage number. The default stage number is - * 0. - * - * .. note:: - * - * The filter supports a range of 0 - 10 inclusively for stage numbers. - */ - 'stage'?: (_google_protobuf_UInt32Value); - /** - * The key to be set in runtime to disable this rate limit configuration. - */ - 'disable_key'?: (string); - /** - * A list of actions that are to be applied for this rate limit configuration. - * Order matters as the actions are processed sequentially and the descriptor - * is composed by appending descriptor entries in that sequence. If an action - * cannot append a descriptor entry, no descriptor is generated for the - * configuration. See :ref:`composing actions - * ` for additional documentation. - */ - 'actions'?: (_envoy_api_v2_route_RateLimit_Action)[]; -} - -/** - * Global rate limiting :ref:`architecture overview `. - */ -export interface RateLimit__Output { - /** - * Refers to the stage set in the filter. The rate limit configuration only - * applies to filters with the same stage number. The default stage number is - * 0. - * - * .. note:: - * - * The filter supports a range of 0 - 10 inclusively for stage numbers. - */ - 'stage'?: (_google_protobuf_UInt32Value__Output); - /** - * The key to be set in runtime to disable this rate limit configuration. - */ - 'disable_key': (string); - /** - * A list of actions that are to be applied for this rate limit configuration. - * Order matters as the actions are processed sequentially and the descriptor - * is composed by appending descriptor entries in that sequence. If an action - * cannot append a descriptor entry, no descriptor is generated for the - * configuration. See :ref:`composing actions - * ` for additional documentation. - */ - 'actions': (_envoy_api_v2_route_RateLimit_Action__Output)[]; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RedirectAction.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RedirectAction.ts deleted file mode 100644 index de7105a54..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RedirectAction.ts +++ /dev/null @@ -1,139 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto - - -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto - -export enum _envoy_api_v2_route_RedirectAction_RedirectResponseCode { - /** - * Moved Permanently HTTP Status Code - 301. - */ - MOVED_PERMANENTLY = 0, - /** - * Found HTTP Status Code - 302. - */ - FOUND = 1, - /** - * See Other HTTP Status Code - 303. - */ - SEE_OTHER = 2, - /** - * Temporary Redirect HTTP Status Code - 307. - */ - TEMPORARY_REDIRECT = 3, - /** - * Permanent Redirect HTTP Status Code - 308. - */ - PERMANENT_REDIRECT = 4, -} - -/** - * [#next-free-field: 9] - */ -export interface RedirectAction { - /** - * The host portion of the URL will be swapped with this value. - */ - 'host_redirect'?: (string); - /** - * The path portion of the URL will be swapped with this value. - */ - 'path_redirect'?: (string); - /** - * The HTTP status code to use in the redirect response. The default response - * code is MOVED_PERMANENTLY (301). - */ - 'response_code'?: (_envoy_api_v2_route_RedirectAction_RedirectResponseCode | keyof typeof _envoy_api_v2_route_RedirectAction_RedirectResponseCode); - /** - * The scheme portion of the URL will be swapped with "https". - */ - 'https_redirect'?: (boolean); - /** - * Indicates that during redirection, the matched prefix (or path) - * should be swapped with this value. This option allows redirect URLs be dynamically created - * based on the request. - * - * .. attention:: - * - * Pay attention to the use of trailing slashes as mentioned in - * :ref:`RouteAction's prefix_rewrite `. - */ - 'prefix_rewrite'?: (string); - /** - * Indicates that during redirection, the query portion of the URL will - * be removed. Default value is false. - */ - 'strip_query'?: (boolean); - /** - * The scheme portion of the URL will be swapped with this value. - */ - 'scheme_redirect'?: (string); - /** - * The port value of the URL will be swapped with this value. - */ - 'port_redirect'?: (number); - /** - * When the scheme redirection take place, the following rules apply: - * 1. If the source URI scheme is `http` and the port is explicitly - * set to `:80`, the port will be removed after the redirection - * 2. If the source URI scheme is `https` and the port is explicitly - * set to `:443`, the port will be removed after the redirection - */ - 'scheme_rewrite_specifier'?: "https_redirect"|"scheme_redirect"; - 'path_rewrite_specifier'?: "path_redirect"|"prefix_rewrite"; -} - -/** - * [#next-free-field: 9] - */ -export interface RedirectAction__Output { - /** - * The host portion of the URL will be swapped with this value. - */ - 'host_redirect': (string); - /** - * The path portion of the URL will be swapped with this value. - */ - 'path_redirect'?: (string); - /** - * The HTTP status code to use in the redirect response. The default response - * code is MOVED_PERMANENTLY (301). - */ - 'response_code': (keyof typeof _envoy_api_v2_route_RedirectAction_RedirectResponseCode); - /** - * The scheme portion of the URL will be swapped with "https". - */ - 'https_redirect'?: (boolean); - /** - * Indicates that during redirection, the matched prefix (or path) - * should be swapped with this value. This option allows redirect URLs be dynamically created - * based on the request. - * - * .. attention:: - * - * Pay attention to the use of trailing slashes as mentioned in - * :ref:`RouteAction's prefix_rewrite `. - */ - 'prefix_rewrite'?: (string); - /** - * Indicates that during redirection, the query portion of the URL will - * be removed. Default value is false. - */ - 'strip_query': (boolean); - /** - * The scheme portion of the URL will be swapped with this value. - */ - 'scheme_redirect'?: (string); - /** - * The port value of the URL will be swapped with this value. - */ - 'port_redirect': (number); - /** - * When the scheme redirection take place, the following rules apply: - * 1. If the source URI scheme is `http` and the port is explicitly - * set to `:80`, the port will be removed after the redirection - * 2. If the source URI scheme is `https` and the port is explicitly - * set to `:443`, the port will be removed after the redirection - */ - 'scheme_rewrite_specifier': "https_redirect"|"scheme_redirect"; - 'path_rewrite_specifier': "path_redirect"|"prefix_rewrite"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RetryPolicy.ts b/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RetryPolicy.ts deleted file mode 100644 index 63b7deb5a..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RetryPolicy.ts +++ /dev/null @@ -1,218 +0,0 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto - -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; -import type { HeaderMatcher as _envoy_api_v2_route_HeaderMatcher, HeaderMatcher__Output as _envoy_api_v2_route_HeaderMatcher__Output } from '../../../../envoy/api/v2/route/HeaderMatcher'; -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; -import type { Long } from '@grpc/proto-loader'; - -export interface _envoy_api_v2_route_RetryPolicy_RetryBackOff { - /** - * Specifies the base interval between retries. This parameter is required and must be greater - * than zero. Values less than 1 ms are rounded up to 1 ms. - * See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion of Envoy's - * back-off algorithm. - */ - 'base_interval'?: (_google_protobuf_Duration); - /** - * Specifies the maximum interval between retries. This parameter is optional, but must be - * greater than or equal to the `base_interval` if set. The default is 10 times the - * `base_interval`. See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion - * of Envoy's back-off algorithm. - */ - 'max_interval'?: (_google_protobuf_Duration); -} - -export interface _envoy_api_v2_route_RetryPolicy_RetryBackOff__Output { - /** - * Specifies the base interval between retries. This parameter is required and must be greater - * than zero. Values less than 1 ms are rounded up to 1 ms. - * See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion of Envoy's - * back-off algorithm. - */ - 'base_interval'?: (_google_protobuf_Duration__Output); - /** - * Specifies the maximum interval between retries. This parameter is optional, but must be - * greater than or equal to the `base_interval` if set. The default is 10 times the - * `base_interval`. See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion - * of Envoy's back-off algorithm. - */ - 'max_interval'?: (_google_protobuf_Duration__Output); -} - -export interface _envoy_api_v2_route_RetryPolicy_RetryHostPredicate { - 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - 'config_type'?: "config"|"typed_config"; -} - -export interface _envoy_api_v2_route_RetryPolicy_RetryHostPredicate__Output { - 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - 'config_type': "config"|"typed_config"; -} - -export interface _envoy_api_v2_route_RetryPolicy_RetryPriority { - 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - 'config_type'?: "config"|"typed_config"; -} - -export interface _envoy_api_v2_route_RetryPolicy_RetryPriority__Output { - 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - 'config_type': "config"|"typed_config"; -} - -/** - * HTTP retry :ref:`architecture overview `. - * [#next-free-field: 11] - */ -export interface RetryPolicy { - /** - * Specifies the conditions under which retry takes place. These are the same - * conditions documented for :ref:`config_http_filters_router_x-envoy-retry-on` and - * :ref:`config_http_filters_router_x-envoy-retry-grpc-on`. - */ - 'retry_on'?: (string); - /** - * Specifies the allowed number of retries. This parameter is optional and - * defaults to 1. These are the same conditions documented for - * :ref:`config_http_filters_router_x-envoy-max-retries`. - */ - 'num_retries'?: (_google_protobuf_UInt32Value); - /** - * Specifies a non-zero upstream timeout per retry attempt. This parameter is optional. The - * same conditions documented for - * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms` apply. - * - * .. note:: - * - * If left unspecified, Envoy will use the global - * :ref:`route timeout ` for the request. - * Consequently, when using a :ref:`5xx ` based - * retry policy, a request that times out will not be retried as the total timeout budget - * would have been exhausted. - */ - 'per_try_timeout'?: (_google_protobuf_Duration); - /** - * Specifies an implementation of a RetryPriority which is used to determine the - * distribution of load across priorities used for retries. Refer to - * :ref:`retry plugin configuration ` for more details. - */ - 'retry_priority'?: (_envoy_api_v2_route_RetryPolicy_RetryPriority); - /** - * Specifies a collection of RetryHostPredicates that will be consulted when selecting a host - * for retries. If any of the predicates reject the host, host selection will be reattempted. - * Refer to :ref:`retry plugin configuration ` for more - * details. - */ - 'retry_host_predicate'?: (_envoy_api_v2_route_RetryPolicy_RetryHostPredicate)[]; - /** - * The maximum number of times host selection will be reattempted before giving up, at which - * point the host that was last selected will be routed to. If unspecified, this will default to - * retrying once. - */ - 'host_selection_retry_max_attempts'?: (number | string | Long); - /** - * HTTP status codes that should trigger a retry in addition to those specified by retry_on. - */ - 'retriable_status_codes'?: (number)[]; - /** - * Specifies parameters that control retry back off. This parameter is optional, in which case the - * default base interval is 25 milliseconds or, if set, the current value of the - * `upstream.base_retry_backoff_ms` runtime parameter. The default maximum interval is 10 times - * the base interval. The documentation for :ref:`config_http_filters_router_x-envoy-max-retries` - * describes Envoy's back-off algorithm. - */ - 'retry_back_off'?: (_envoy_api_v2_route_RetryPolicy_RetryBackOff); - /** - * HTTP response headers that trigger a retry if present in the response. A retry will be - * triggered if any of the header matches match the upstream response headers. - * The field is only consulted if 'retriable-headers' retry policy is active. - */ - 'retriable_headers'?: (_envoy_api_v2_route_HeaderMatcher)[]; - /** - * HTTP headers which must be present in the request for retries to be attempted. - */ - 'retriable_request_headers'?: (_envoy_api_v2_route_HeaderMatcher)[]; -} - -/** - * HTTP retry :ref:`architecture overview `. - * [#next-free-field: 11] - */ -export interface RetryPolicy__Output { - /** - * Specifies the conditions under which retry takes place. These are the same - * conditions documented for :ref:`config_http_filters_router_x-envoy-retry-on` and - * :ref:`config_http_filters_router_x-envoy-retry-grpc-on`. - */ - 'retry_on': (string); - /** - * Specifies the allowed number of retries. This parameter is optional and - * defaults to 1. These are the same conditions documented for - * :ref:`config_http_filters_router_x-envoy-max-retries`. - */ - 'num_retries'?: (_google_protobuf_UInt32Value__Output); - /** - * Specifies a non-zero upstream timeout per retry attempt. This parameter is optional. The - * same conditions documented for - * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms` apply. - * - * .. note:: - * - * If left unspecified, Envoy will use the global - * :ref:`route timeout ` for the request. - * Consequently, when using a :ref:`5xx ` based - * retry policy, a request that times out will not be retried as the total timeout budget - * would have been exhausted. - */ - 'per_try_timeout'?: (_google_protobuf_Duration__Output); - /** - * Specifies an implementation of a RetryPriority which is used to determine the - * distribution of load across priorities used for retries. Refer to - * :ref:`retry plugin configuration ` for more details. - */ - 'retry_priority'?: (_envoy_api_v2_route_RetryPolicy_RetryPriority__Output); - /** - * Specifies a collection of RetryHostPredicates that will be consulted when selecting a host - * for retries. If any of the predicates reject the host, host selection will be reattempted. - * Refer to :ref:`retry plugin configuration ` for more - * details. - */ - 'retry_host_predicate': (_envoy_api_v2_route_RetryPolicy_RetryHostPredicate__Output)[]; - /** - * The maximum number of times host selection will be reattempted before giving up, at which - * point the host that was last selected will be routed to. If unspecified, this will default to - * retrying once. - */ - 'host_selection_retry_max_attempts': (string); - /** - * HTTP status codes that should trigger a retry in addition to those specified by retry_on. - */ - 'retriable_status_codes': (number)[]; - /** - * Specifies parameters that control retry back off. This parameter is optional, in which case the - * default base interval is 25 milliseconds or, if set, the current value of the - * `upstream.base_retry_backoff_ms` runtime parameter. The default maximum interval is 10 times - * the base interval. The documentation for :ref:`config_http_filters_router_x-envoy-max-retries` - * describes Envoy's back-off algorithm. - */ - 'retry_back_off'?: (_envoy_api_v2_route_RetryPolicy_RetryBackOff__Output); - /** - * HTTP response headers that trigger a retry if present in the response. A retry will be - * triggered if any of the header matches match the upstream response headers. - * The field is only consulted if 'retriable-headers' retry policy is active. - */ - 'retriable_headers': (_envoy_api_v2_route_HeaderMatcher__Output)[]; - /** - * HTTP headers which must be present in the request for retries to be attempted. - */ - 'retriable_request_headers': (_envoy_api_v2_route_HeaderMatcher__Output)[]; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AccessLog.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AccessLog.ts new file mode 100644 index 000000000..367d8f302 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AccessLog.ts @@ -0,0 +1,42 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { AccessLogFilter as _envoy_config_accesslog_v3_AccessLogFilter, AccessLogFilter__Output as _envoy_config_accesslog_v3_AccessLogFilter__Output } from '../../../../envoy/config/accesslog/v3/AccessLogFilter'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +export interface AccessLog { + /** + * The name of the access log extension to instantiate. + * The name must match one of the compiled in loggers. + * See the :ref:`extensions listed in typed_config below ` for the default list of available loggers. + */ + 'name'?: (string); + /** + * Filter which is used to determine if the access log needs to be written. + */ + 'filter'?: (_envoy_config_accesslog_v3_AccessLogFilter | null); + 'typed_config'?: (_google_protobuf_Any | null); + /** + * Custom configuration that must be set according to the access logger extension being instantiated. + * [#extension-category: envoy.access_loggers] + */ + 'config_type'?: "typed_config"; +} + +export interface AccessLog__Output { + /** + * The name of the access log extension to instantiate. + * The name must match one of the compiled in loggers. + * See the :ref:`extensions listed in typed_config below ` for the default list of available loggers. + */ + 'name': (string); + /** + * Filter which is used to determine if the access log needs to be written. + */ + 'filter': (_envoy_config_accesslog_v3_AccessLogFilter__Output | null); + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * Custom configuration that must be set according to the access logger extension being instantiated. + * [#extension-category: envoy.access_loggers] + */ + 'config_type': "typed_config"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AccessLogFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AccessLogFilter.ts new file mode 100644 index 000000000..85a952c9c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AccessLogFilter.ts @@ -0,0 +1,124 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { StatusCodeFilter as _envoy_config_accesslog_v3_StatusCodeFilter, StatusCodeFilter__Output as _envoy_config_accesslog_v3_StatusCodeFilter__Output } from '../../../../envoy/config/accesslog/v3/StatusCodeFilter'; +import type { DurationFilter as _envoy_config_accesslog_v3_DurationFilter, DurationFilter__Output as _envoy_config_accesslog_v3_DurationFilter__Output } from '../../../../envoy/config/accesslog/v3/DurationFilter'; +import type { NotHealthCheckFilter as _envoy_config_accesslog_v3_NotHealthCheckFilter, NotHealthCheckFilter__Output as _envoy_config_accesslog_v3_NotHealthCheckFilter__Output } from '../../../../envoy/config/accesslog/v3/NotHealthCheckFilter'; +import type { TraceableFilter as _envoy_config_accesslog_v3_TraceableFilter, TraceableFilter__Output as _envoy_config_accesslog_v3_TraceableFilter__Output } from '../../../../envoy/config/accesslog/v3/TraceableFilter'; +import type { RuntimeFilter as _envoy_config_accesslog_v3_RuntimeFilter, RuntimeFilter__Output as _envoy_config_accesslog_v3_RuntimeFilter__Output } from '../../../../envoy/config/accesslog/v3/RuntimeFilter'; +import type { AndFilter as _envoy_config_accesslog_v3_AndFilter, AndFilter__Output as _envoy_config_accesslog_v3_AndFilter__Output } from '../../../../envoy/config/accesslog/v3/AndFilter'; +import type { OrFilter as _envoy_config_accesslog_v3_OrFilter, OrFilter__Output as _envoy_config_accesslog_v3_OrFilter__Output } from '../../../../envoy/config/accesslog/v3/OrFilter'; +import type { HeaderFilter as _envoy_config_accesslog_v3_HeaderFilter, HeaderFilter__Output as _envoy_config_accesslog_v3_HeaderFilter__Output } from '../../../../envoy/config/accesslog/v3/HeaderFilter'; +import type { ResponseFlagFilter as _envoy_config_accesslog_v3_ResponseFlagFilter, ResponseFlagFilter__Output as _envoy_config_accesslog_v3_ResponseFlagFilter__Output } from '../../../../envoy/config/accesslog/v3/ResponseFlagFilter'; +import type { GrpcStatusFilter as _envoy_config_accesslog_v3_GrpcStatusFilter, GrpcStatusFilter__Output as _envoy_config_accesslog_v3_GrpcStatusFilter__Output } from '../../../../envoy/config/accesslog/v3/GrpcStatusFilter'; +import type { ExtensionFilter as _envoy_config_accesslog_v3_ExtensionFilter, ExtensionFilter__Output as _envoy_config_accesslog_v3_ExtensionFilter__Output } from '../../../../envoy/config/accesslog/v3/ExtensionFilter'; +import type { MetadataFilter as _envoy_config_accesslog_v3_MetadataFilter, MetadataFilter__Output as _envoy_config_accesslog_v3_MetadataFilter__Output } from '../../../../envoy/config/accesslog/v3/MetadataFilter'; + +/** + * [#next-free-field: 13] + */ +export interface AccessLogFilter { + /** + * Status code filter. + */ + 'status_code_filter'?: (_envoy_config_accesslog_v3_StatusCodeFilter | null); + /** + * Duration filter. + */ + 'duration_filter'?: (_envoy_config_accesslog_v3_DurationFilter | null); + /** + * Not health check filter. + */ + 'not_health_check_filter'?: (_envoy_config_accesslog_v3_NotHealthCheckFilter | null); + /** + * Traceable filter. + */ + 'traceable_filter'?: (_envoy_config_accesslog_v3_TraceableFilter | null); + /** + * Runtime filter. + */ + 'runtime_filter'?: (_envoy_config_accesslog_v3_RuntimeFilter | null); + /** + * And filter. + */ + 'and_filter'?: (_envoy_config_accesslog_v3_AndFilter | null); + /** + * Or filter. + */ + 'or_filter'?: (_envoy_config_accesslog_v3_OrFilter | null); + /** + * Header filter. + */ + 'header_filter'?: (_envoy_config_accesslog_v3_HeaderFilter | null); + /** + * Response flag filter. + */ + 'response_flag_filter'?: (_envoy_config_accesslog_v3_ResponseFlagFilter | null); + /** + * gRPC status filter. + */ + 'grpc_status_filter'?: (_envoy_config_accesslog_v3_GrpcStatusFilter | null); + /** + * Extension filter. + */ + 'extension_filter'?: (_envoy_config_accesslog_v3_ExtensionFilter | null); + /** + * Metadata Filter + */ + 'metadata_filter'?: (_envoy_config_accesslog_v3_MetadataFilter | null); + 'filter_specifier'?: "status_code_filter"|"duration_filter"|"not_health_check_filter"|"traceable_filter"|"runtime_filter"|"and_filter"|"or_filter"|"header_filter"|"response_flag_filter"|"grpc_status_filter"|"extension_filter"|"metadata_filter"; +} + +/** + * [#next-free-field: 13] + */ +export interface AccessLogFilter__Output { + /** + * Status code filter. + */ + 'status_code_filter'?: (_envoy_config_accesslog_v3_StatusCodeFilter__Output | null); + /** + * Duration filter. + */ + 'duration_filter'?: (_envoy_config_accesslog_v3_DurationFilter__Output | null); + /** + * Not health check filter. + */ + 'not_health_check_filter'?: (_envoy_config_accesslog_v3_NotHealthCheckFilter__Output | null); + /** + * Traceable filter. + */ + 'traceable_filter'?: (_envoy_config_accesslog_v3_TraceableFilter__Output | null); + /** + * Runtime filter. + */ + 'runtime_filter'?: (_envoy_config_accesslog_v3_RuntimeFilter__Output | null); + /** + * And filter. + */ + 'and_filter'?: (_envoy_config_accesslog_v3_AndFilter__Output | null); + /** + * Or filter. + */ + 'or_filter'?: (_envoy_config_accesslog_v3_OrFilter__Output | null); + /** + * Header filter. + */ + 'header_filter'?: (_envoy_config_accesslog_v3_HeaderFilter__Output | null); + /** + * Response flag filter. + */ + 'response_flag_filter'?: (_envoy_config_accesslog_v3_ResponseFlagFilter__Output | null); + /** + * gRPC status filter. + */ + 'grpc_status_filter'?: (_envoy_config_accesslog_v3_GrpcStatusFilter__Output | null); + /** + * Extension filter. + */ + 'extension_filter'?: (_envoy_config_accesslog_v3_ExtensionFilter__Output | null); + /** + * Metadata Filter + */ + 'metadata_filter'?: (_envoy_config_accesslog_v3_MetadataFilter__Output | null); + 'filter_specifier': "status_code_filter"|"duration_filter"|"not_health_check_filter"|"traceable_filter"|"runtime_filter"|"and_filter"|"or_filter"|"header_filter"|"response_flag_filter"|"grpc_status_filter"|"extension_filter"|"metadata_filter"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AndFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AndFilter.ts similarity index 51% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AndFilter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AndFilter.ts index 7cf1cb98c..c3c2ac8b4 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AndFilter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/AndFilter.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto -import type { AccessLogFilter as _envoy_config_filter_accesslog_v2_AccessLogFilter, AccessLogFilter__Output as _envoy_config_filter_accesslog_v2_AccessLogFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/AccessLogFilter'; +import type { AccessLogFilter as _envoy_config_accesslog_v3_AccessLogFilter, AccessLogFilter__Output as _envoy_config_accesslog_v3_AccessLogFilter__Output } from '../../../../envoy/config/accesslog/v3/AccessLogFilter'; /** * Performs a logical “and” operation on the result of each filter in filters. @@ -8,7 +8,7 @@ import type { AccessLogFilter as _envoy_config_filter_accesslog_v2_AccessLogFilt * filter returns false immediately. */ export interface AndFilter { - 'filters'?: (_envoy_config_filter_accesslog_v2_AccessLogFilter)[]; + 'filters'?: (_envoy_config_accesslog_v3_AccessLogFilter)[]; } /** @@ -17,5 +17,5 @@ export interface AndFilter { * filter returns false immediately. */ export interface AndFilter__Output { - 'filters': (_envoy_config_filter_accesslog_v2_AccessLogFilter__Output)[]; + 'filters': (_envoy_config_accesslog_v3_AccessLogFilter__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ComparisonFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ComparisonFilter.ts new file mode 100644 index 000000000..07893f2dd --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ComparisonFilter.ts @@ -0,0 +1,48 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { RuntimeUInt32 as _envoy_config_core_v3_RuntimeUInt32, RuntimeUInt32__Output as _envoy_config_core_v3_RuntimeUInt32__Output } from '../../../../envoy/config/core/v3/RuntimeUInt32'; + +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +export enum _envoy_config_accesslog_v3_ComparisonFilter_Op { + /** + * = + */ + EQ = 0, + /** + * >= + */ + GE = 1, + /** + * <= + */ + LE = 2, +} + +/** + * Filter on an integer comparison. + */ +export interface ComparisonFilter { + /** + * Comparison operator. + */ + 'op'?: (_envoy_config_accesslog_v3_ComparisonFilter_Op | keyof typeof _envoy_config_accesslog_v3_ComparisonFilter_Op); + /** + * Value to compare against. + */ + 'value'?: (_envoy_config_core_v3_RuntimeUInt32 | null); +} + +/** + * Filter on an integer comparison. + */ +export interface ComparisonFilter__Output { + /** + * Comparison operator. + */ + 'op': (keyof typeof _envoy_config_accesslog_v3_ComparisonFilter_Op); + /** + * Value to compare against. + */ + 'value': (_envoy_config_core_v3_RuntimeUInt32__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/DurationFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/DurationFilter.ts new file mode 100644 index 000000000..ee61e55fa --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/DurationFilter.ts @@ -0,0 +1,23 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { ComparisonFilter as _envoy_config_accesslog_v3_ComparisonFilter, ComparisonFilter__Output as _envoy_config_accesslog_v3_ComparisonFilter__Output } from '../../../../envoy/config/accesslog/v3/ComparisonFilter'; + +/** + * Filters on total request duration in milliseconds. + */ +export interface DurationFilter { + /** + * Comparison. + */ + 'comparison'?: (_envoy_config_accesslog_v3_ComparisonFilter | null); +} + +/** + * Filters on total request duration in milliseconds. + */ +export interface DurationFilter__Output { + /** + * Comparison. + */ + 'comparison': (_envoy_config_accesslog_v3_ComparisonFilter__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ExtensionFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ExtensionFilter.ts similarity index 56% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ExtensionFilter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ExtensionFilter.ts index 184c76eb6..19edb671b 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ExtensionFilter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ExtensionFilter.ts @@ -1,7 +1,6 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../google/protobuf/Any'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; /** * Extension filter is statically registered at runtime. @@ -12,12 +11,11 @@ export interface ExtensionFilter { * match a statically registered filter. */ 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); + 'typed_config'?: (_google_protobuf_Any | null); /** * Custom configuration that depends on the filter being instantiated. */ - 'config_type'?: "config"|"typed_config"; + 'config_type'?: "typed_config"; } /** @@ -29,10 +27,9 @@ export interface ExtensionFilter__Output { * match a statically registered filter. */ 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); + 'typed_config'?: (_google_protobuf_Any__Output | null); /** * Custom configuration that depends on the filter being instantiated. */ - 'config_type': "config"|"typed_config"; + 'config_type': "typed_config"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/GrpcStatusFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/GrpcStatusFilter.ts similarity index 51% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/GrpcStatusFilter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/GrpcStatusFilter.ts index 8e8b0981e..f7ccc8052 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/GrpcStatusFilter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/GrpcStatusFilter.ts @@ -1,9 +1,9 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto -export enum _envoy_config_filter_accesslog_v2_GrpcStatusFilter_Status { +export enum _envoy_config_accesslog_v3_GrpcStatusFilter_Status { OK = 0, CANCELED = 1, UNKNOWN = 2, @@ -24,33 +24,35 @@ export enum _envoy_config_filter_accesslog_v2_GrpcStatusFilter_Status { } /** - * Filters gRPC requests based on their response status. If a gRPC status is not provided, the - * filter will infer the status from the HTTP status code. + * Filters gRPC requests based on their response status. If a gRPC status is not + * provided, the filter will infer the status from the HTTP status code. */ export interface GrpcStatusFilter { /** * Logs only responses that have any one of the gRPC statuses in this field. */ - 'statuses'?: (_envoy_config_filter_accesslog_v2_GrpcStatusFilter_Status | keyof typeof _envoy_config_filter_accesslog_v2_GrpcStatusFilter_Status)[]; + 'statuses'?: (_envoy_config_accesslog_v3_GrpcStatusFilter_Status | keyof typeof _envoy_config_accesslog_v3_GrpcStatusFilter_Status)[]; /** - * If included and set to true, the filter will instead block all responses with a gRPC status or - * inferred gRPC status enumerated in statuses, and allow all other responses. + * If included and set to true, the filter will instead block all responses + * with a gRPC status or inferred gRPC status enumerated in statuses, and + * allow all other responses. */ 'exclude'?: (boolean); } /** - * Filters gRPC requests based on their response status. If a gRPC status is not provided, the - * filter will infer the status from the HTTP status code. + * Filters gRPC requests based on their response status. If a gRPC status is not + * provided, the filter will infer the status from the HTTP status code. */ export interface GrpcStatusFilter__Output { /** * Logs only responses that have any one of the gRPC statuses in this field. */ - 'statuses': (keyof typeof _envoy_config_filter_accesslog_v2_GrpcStatusFilter_Status)[]; + 'statuses': (keyof typeof _envoy_config_accesslog_v3_GrpcStatusFilter_Status)[]; /** - * If included and set to true, the filter will instead block all responses with a gRPC status or - * inferred gRPC status enumerated in statuses, and allow all other responses. + * If included and set to true, the filter will instead block all responses + * with a gRPC status or inferred gRPC status enumerated in statuses, and + * allow all other responses. */ 'exclude': (boolean); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/HeaderFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/HeaderFilter.ts new file mode 100644 index 000000000..294084d1c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/HeaderFilter.ts @@ -0,0 +1,25 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { HeaderMatcher as _envoy_config_route_v3_HeaderMatcher, HeaderMatcher__Output as _envoy_config_route_v3_HeaderMatcher__Output } from '../../../../envoy/config/route/v3/HeaderMatcher'; + +/** + * Filters requests based on the presence or value of a request header. + */ +export interface HeaderFilter { + /** + * Only requests with a header which matches the specified HeaderMatcher will + * pass the filter check. + */ + 'header'?: (_envoy_config_route_v3_HeaderMatcher | null); +} + +/** + * Filters requests based on the presence or value of a request header. + */ +export interface HeaderFilter__Output { + /** + * Only requests with a header which matches the specified HeaderMatcher will + * pass the filter check. + */ + 'header': (_envoy_config_route_v3_HeaderMatcher__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/MetadataFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/MetadataFilter.ts new file mode 100644 index 000000000..cd821fef6 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/MetadataFilter.ts @@ -0,0 +1,48 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { MetadataMatcher as _envoy_type_matcher_v3_MetadataMatcher, MetadataMatcher__Output as _envoy_type_matcher_v3_MetadataMatcher__Output } from '../../../../envoy/type/matcher/v3/MetadataMatcher'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; + +/** + * Filters based on matching dynamic metadata. + * If the matcher path and key correspond to an existing key in dynamic + * metadata, the request is logged only if the matcher value is equal to the + * metadata value. If the matcher path and key *do not* correspond to an + * existing key in dynamic metadata, the request is logged only if + * match_if_key_not_found is "true" or unset. + */ +export interface MetadataFilter { + /** + * Matcher to check metadata for specified value. For example, to match on the + * access_log_hint metadata, set the filter to "envoy.common" and the path to + * "access_log_hint", and the value to "true". + */ + 'matcher'?: (_envoy_type_matcher_v3_MetadataMatcher | null); + /** + * Default result if the key does not exist in dynamic metadata: if unset or + * true, then log; if false, then don't log. + */ + 'match_if_key_not_found'?: (_google_protobuf_BoolValue | null); +} + +/** + * Filters based on matching dynamic metadata. + * If the matcher path and key correspond to an existing key in dynamic + * metadata, the request is logged only if the matcher value is equal to the + * metadata value. If the matcher path and key *do not* correspond to an + * existing key in dynamic metadata, the request is logged only if + * match_if_key_not_found is "true" or unset. + */ +export interface MetadataFilter__Output { + /** + * Matcher to check metadata for specified value. For example, to match on the + * access_log_hint metadata, set the filter to "envoy.common" and the path to + * "access_log_hint", and the value to "true". + */ + 'matcher': (_envoy_type_matcher_v3_MetadataMatcher__Output | null); + /** + * Default result if the key does not exist in dynamic metadata: if unset or + * true, then log; if false, then don't log. + */ + 'match_if_key_not_found': (_google_protobuf_BoolValue__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/NotHealthCheckFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/NotHealthCheckFilter.ts similarity index 81% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/NotHealthCheckFilter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/NotHealthCheckFilter.ts index 3de68f081..40728fc34 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/NotHealthCheckFilter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/NotHealthCheckFilter.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/OrFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/OrFilter.ts similarity index 50% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/OrFilter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/OrFilter.ts index 859c1218c..1756d3ad5 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/OrFilter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/OrFilter.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto -import type { AccessLogFilter as _envoy_config_filter_accesslog_v2_AccessLogFilter, AccessLogFilter__Output as _envoy_config_filter_accesslog_v2_AccessLogFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/AccessLogFilter'; +import type { AccessLogFilter as _envoy_config_accesslog_v3_AccessLogFilter, AccessLogFilter__Output as _envoy_config_accesslog_v3_AccessLogFilter__Output } from '../../../../envoy/config/accesslog/v3/AccessLogFilter'; /** * Performs a logical “or” operation on the result of each individual filter. @@ -8,7 +8,7 @@ import type { AccessLogFilter as _envoy_config_filter_accesslog_v2_AccessLogFilt * filter returns true immediately. */ export interface OrFilter { - 'filters'?: (_envoy_config_filter_accesslog_v2_AccessLogFilter)[]; + 'filters'?: (_envoy_config_accesslog_v3_AccessLogFilter)[]; } /** @@ -17,5 +17,5 @@ export interface OrFilter { * filter returns true immediately. */ export interface OrFilter__Output { - 'filters': (_envoy_config_filter_accesslog_v2_AccessLogFilter__Output)[]; + 'filters': (_envoy_config_accesslog_v3_AccessLogFilter__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ResponseFlagFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ResponseFlagFilter.ts similarity index 51% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ResponseFlagFilter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ResponseFlagFilter.ts index 280fbb26a..c45a63054 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ResponseFlagFilter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/ResponseFlagFilter.ts @@ -1,16 +1,17 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto /** * Filters requests that received responses with an Envoy response flag set. * A list of the response flags can be found - * in the access log formatter :ref:`documentation`. + * in the access log formatter + * :ref:`documentation`. */ export interface ResponseFlagFilter { /** - * Only responses with the any of the flags listed in this field will be logged. - * This field is optional. If it is not specified, then any response flag will pass - * the filter check. + * Only responses with the any of the flags listed in this field will be + * logged. This field is optional. If it is not specified, then any response + * flag will pass the filter check. */ 'flags'?: (string)[]; } @@ -18,13 +19,14 @@ export interface ResponseFlagFilter { /** * Filters requests that received responses with an Envoy response flag set. * A list of the response flags can be found - * in the access log formatter :ref:`documentation`. + * in the access log formatter + * :ref:`documentation`. */ export interface ResponseFlagFilter__Output { /** - * Only responses with the any of the flags listed in this field will be logged. - * This field is optional. If it is not specified, then any response flag will pass - * the filter check. + * Only responses with the any of the flags listed in this field will be + * logged. This field is optional. If it is not specified, then any response + * flag will pass the filter check. */ 'flags': (string)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/RuntimeFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/RuntimeFilter.ts new file mode 100644 index 000000000..83b075388 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/RuntimeFilter.ts @@ -0,0 +1,73 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../envoy/type/v3/FractionalPercent'; + +/** + * Filters for random sampling of requests. + */ +export interface RuntimeFilter { + /** + * Runtime key to get an optional overridden numerator for use in the + * *percent_sampled* field. If found in runtime, this value will replace the + * default numerator. + */ + 'runtime_key'?: (string); + /** + * The default sampling percentage. If not specified, defaults to 0% with + * denominator of 100. + */ + 'percent_sampled'?: (_envoy_type_v3_FractionalPercent | null); + /** + * By default, sampling pivots on the header + * :ref:`x-request-id` being + * present. If :ref:`x-request-id` + * is present, the filter will consistently sample across multiple hosts based + * on the runtime key value and the value extracted from + * :ref:`x-request-id`. If it is + * missing, or *use_independent_randomness* is set to true, the filter will + * randomly sample based on the runtime key value alone. + * *use_independent_randomness* can be used for logging kill switches within + * complex nested :ref:`AndFilter + * ` and :ref:`OrFilter + * ` blocks that are easier to + * reason about from a probability perspective (i.e., setting to true will + * cause the filter to behave like an independent random variable when + * composed within logical operator filters). + */ + 'use_independent_randomness'?: (boolean); +} + +/** + * Filters for random sampling of requests. + */ +export interface RuntimeFilter__Output { + /** + * Runtime key to get an optional overridden numerator for use in the + * *percent_sampled* field. If found in runtime, this value will replace the + * default numerator. + */ + 'runtime_key': (string); + /** + * The default sampling percentage. If not specified, defaults to 0% with + * denominator of 100. + */ + 'percent_sampled': (_envoy_type_v3_FractionalPercent__Output | null); + /** + * By default, sampling pivots on the header + * :ref:`x-request-id` being + * present. If :ref:`x-request-id` + * is present, the filter will consistently sample across multiple hosts based + * on the runtime key value and the value extracted from + * :ref:`x-request-id`. If it is + * missing, or *use_independent_randomness* is set to true, the filter will + * randomly sample based on the runtime key value alone. + * *use_independent_randomness* can be used for logging kill switches within + * complex nested :ref:`AndFilter + * ` and :ref:`OrFilter + * ` blocks that are easier to + * reason about from a probability perspective (i.e., setting to true will + * cause the filter to behave like an independent random variable when + * composed within logical operator filters). + */ + 'use_independent_randomness': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/StatusCodeFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/StatusCodeFilter.ts new file mode 100644 index 000000000..a071b5cbb --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/StatusCodeFilter.ts @@ -0,0 +1,23 @@ +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto + +import type { ComparisonFilter as _envoy_config_accesslog_v3_ComparisonFilter, ComparisonFilter__Output as _envoy_config_accesslog_v3_ComparisonFilter__Output } from '../../../../envoy/config/accesslog/v3/ComparisonFilter'; + +/** + * Filters on HTTP response/status code. + */ +export interface StatusCodeFilter { + /** + * Comparison. + */ + 'comparison'?: (_envoy_config_accesslog_v3_ComparisonFilter | null); +} + +/** + * Filters on HTTP response/status code. + */ +export interface StatusCodeFilter__Output { + /** + * Comparison. + */ + 'comparison': (_envoy_config_accesslog_v3_ComparisonFilter__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/TraceableFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/TraceableFilter.ts similarity index 81% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/TraceableFilter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/TraceableFilter.ts index 8de24656a..c2b3a646b 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/TraceableFilter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/accesslog/v3/TraceableFilter.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto +// Original file: deps/envoy-api/envoy/config/accesslog/v3/accesslog.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Admin.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Admin.ts new file mode 100644 index 000000000..a7f3826a1 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Admin.ts @@ -0,0 +1,75 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; +import type { SocketOption as _envoy_config_core_v3_SocketOption, SocketOption__Output as _envoy_config_core_v3_SocketOption__Output } from '../../../../envoy/config/core/v3/SocketOption'; +import type { AccessLog as _envoy_config_accesslog_v3_AccessLog, AccessLog__Output as _envoy_config_accesslog_v3_AccessLog__Output } from '../../../../envoy/config/accesslog/v3/AccessLog'; + +/** + * Administration interface :ref:`operations documentation + * `. + * [#next-free-field: 6] + */ +export interface Admin { + /** + * The path to write the access log for the administration server. If no + * access log is desired specify ‘/dev/null’. This is only required if + * :ref:`address ` is set. + * Deprecated in favor of *access_log* which offers more options. + */ + 'access_log_path'?: (string); + /** + * The cpu profiler output path for the administration server. If no profile + * path is specified, the default is ‘/var/log/envoy/envoy.prof’. + */ + 'profile_path'?: (string); + /** + * The TCP address that the administration server will listen on. + * If not specified, Envoy will not start an administration server. + */ + 'address'?: (_envoy_config_core_v3_Address | null); + /** + * Additional socket options that may not be present in Envoy source code or + * precompiled binaries. + */ + 'socket_options'?: (_envoy_config_core_v3_SocketOption)[]; + /** + * Configuration for :ref:`access logs ` + * emitted by the administration server. + */ + 'access_log'?: (_envoy_config_accesslog_v3_AccessLog)[]; +} + +/** + * Administration interface :ref:`operations documentation + * `. + * [#next-free-field: 6] + */ +export interface Admin__Output { + /** + * The path to write the access log for the administration server. If no + * access log is desired specify ‘/dev/null’. This is only required if + * :ref:`address ` is set. + * Deprecated in favor of *access_log* which offers more options. + */ + 'access_log_path': (string); + /** + * The cpu profiler output path for the administration server. If no profile + * path is specified, the default is ‘/var/log/envoy/envoy.prof’. + */ + 'profile_path': (string); + /** + * The TCP address that the administration server will listen on. + * If not specified, Envoy will not start an administration server. + */ + 'address': (_envoy_config_core_v3_Address__Output | null); + /** + * Additional socket options that may not be present in Envoy source code or + * precompiled binaries. + */ + 'socket_options': (_envoy_config_core_v3_SocketOption__Output)[]; + /** + * Configuration for :ref:`access logs ` + * emitted by the administration server. + */ + 'access_log': (_envoy_config_accesslog_v3_AccessLog__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Bootstrap.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Bootstrap.ts new file mode 100644 index 000000000..797148675 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Bootstrap.ts @@ -0,0 +1,642 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { Node as _envoy_config_core_v3_Node, Node__Output as _envoy_config_core_v3_Node__Output } from '../../../../envoy/config/core/v3/Node'; +import type { ClusterManager as _envoy_config_bootstrap_v3_ClusterManager, ClusterManager__Output as _envoy_config_bootstrap_v3_ClusterManager__Output } from '../../../../envoy/config/bootstrap/v3/ClusterManager'; +import type { StatsSink as _envoy_config_metrics_v3_StatsSink, StatsSink__Output as _envoy_config_metrics_v3_StatsSink__Output } from '../../../../envoy/config/metrics/v3/StatsSink'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { Watchdog as _envoy_config_bootstrap_v3_Watchdog, Watchdog__Output as _envoy_config_bootstrap_v3_Watchdog__Output } from '../../../../envoy/config/bootstrap/v3/Watchdog'; +import type { Tracing as _envoy_config_trace_v3_Tracing, Tracing__Output as _envoy_config_trace_v3_Tracing__Output } from '../../../../envoy/config/trace/v3/Tracing'; +import type { Admin as _envoy_config_bootstrap_v3_Admin, Admin__Output as _envoy_config_bootstrap_v3_Admin__Output } from '../../../../envoy/config/bootstrap/v3/Admin'; +import type { StatsConfig as _envoy_config_metrics_v3_StatsConfig, StatsConfig__Output as _envoy_config_metrics_v3_StatsConfig__Output } from '../../../../envoy/config/metrics/v3/StatsConfig'; +import type { ApiConfigSource as _envoy_config_core_v3_ApiConfigSource, ApiConfigSource__Output as _envoy_config_core_v3_ApiConfigSource__Output } from '../../../../envoy/config/core/v3/ApiConfigSource'; +import type { OverloadManager as _envoy_config_overload_v3_OverloadManager, OverloadManager__Output as _envoy_config_overload_v3_OverloadManager__Output } from '../../../../envoy/config/overload/v3/OverloadManager'; +import type { LayeredRuntime as _envoy_config_bootstrap_v3_LayeredRuntime, LayeredRuntime__Output as _envoy_config_bootstrap_v3_LayeredRuntime__Output } from '../../../../envoy/config/bootstrap/v3/LayeredRuntime'; +import type { UInt64Value as _google_protobuf_UInt64Value, UInt64Value__Output as _google_protobuf_UInt64Value__Output } from '../../../../google/protobuf/UInt64Value'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../envoy/config/core/v3/ConfigSource'; +import type { Watchdogs as _envoy_config_bootstrap_v3_Watchdogs, Watchdogs__Output as _envoy_config_bootstrap_v3_Watchdogs__Output } from '../../../../envoy/config/bootstrap/v3/Watchdogs'; +import type { FatalAction as _envoy_config_bootstrap_v3_FatalAction, FatalAction__Output as _envoy_config_bootstrap_v3_FatalAction__Output } from '../../../../envoy/config/bootstrap/v3/FatalAction'; +import type { DnsResolutionConfig as _envoy_config_core_v3_DnsResolutionConfig, DnsResolutionConfig__Output as _envoy_config_core_v3_DnsResolutionConfig__Output } from '../../../../envoy/config/core/v3/DnsResolutionConfig'; +import type { CustomInlineHeader as _envoy_config_bootstrap_v3_CustomInlineHeader, CustomInlineHeader__Output as _envoy_config_bootstrap_v3_CustomInlineHeader__Output } from '../../../../envoy/config/bootstrap/v3/CustomInlineHeader'; +import type { Listener as _envoy_config_listener_v3_Listener, Listener__Output as _envoy_config_listener_v3_Listener__Output } from '../../../../envoy/config/listener/v3/Listener'; +import type { Cluster as _envoy_config_cluster_v3_Cluster, Cluster__Output as _envoy_config_cluster_v3_Cluster__Output } from '../../../../envoy/config/cluster/v3/Cluster'; +import type { Secret as _envoy_extensions_transport_sockets_tls_v3_Secret, Secret__Output as _envoy_extensions_transport_sockets_tls_v3_Secret__Output } from '../../../../envoy/extensions/transport_sockets/tls/v3/Secret'; +import type { Long } from '@grpc/proto-loader'; + +/** + * [#next-free-field: 7] + */ +export interface _envoy_config_bootstrap_v3_Bootstrap_DynamicResources { + /** + * All :ref:`Listeners ` are provided by a single + * :ref:`LDS ` configuration source. + */ + 'lds_config'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * xdstp:// resource locator for listener collection. + * [#not-implemented-hide:] + */ + 'lds_resources_locator'?: (string); + /** + * All post-bootstrap :ref:`Cluster ` definitions are + * provided by a single :ref:`CDS ` + * configuration source. + */ + 'cds_config'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * xdstp:// resource locator for cluster collection. + * [#not-implemented-hide:] + */ + 'cds_resources_locator'?: (string); + /** + * A single :ref:`ADS ` source may be optionally + * specified. This must have :ref:`api_type + * ` :ref:`GRPC + * `. Only + * :ref:`ConfigSources ` that have + * the :ref:`ads ` field set will be + * streamed on the ADS channel. + */ + 'ads_config'?: (_envoy_config_core_v3_ApiConfigSource | null); +} + +/** + * [#next-free-field: 7] + */ +export interface _envoy_config_bootstrap_v3_Bootstrap_DynamicResources__Output { + /** + * All :ref:`Listeners ` are provided by a single + * :ref:`LDS ` configuration source. + */ + 'lds_config': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * xdstp:// resource locator for listener collection. + * [#not-implemented-hide:] + */ + 'lds_resources_locator': (string); + /** + * All post-bootstrap :ref:`Cluster ` definitions are + * provided by a single :ref:`CDS ` + * configuration source. + */ + 'cds_config': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * xdstp:// resource locator for cluster collection. + * [#not-implemented-hide:] + */ + 'cds_resources_locator': (string); + /** + * A single :ref:`ADS ` source may be optionally + * specified. This must have :ref:`api_type + * ` :ref:`GRPC + * `. Only + * :ref:`ConfigSources ` that have + * the :ref:`ads ` field set will be + * streamed on the ADS channel. + */ + 'ads_config': (_envoy_config_core_v3_ApiConfigSource__Output | null); +} + +export interface _envoy_config_bootstrap_v3_Bootstrap_StaticResources { + /** + * Static :ref:`Listeners `. These listeners are + * available regardless of LDS configuration. + */ + 'listeners'?: (_envoy_config_listener_v3_Listener)[]; + /** + * If a network based configuration source is specified for :ref:`cds_config + * `, it's necessary + * to have some initial cluster definitions available to allow Envoy to know + * how to speak to the management server. These cluster definitions may not + * use :ref:`EDS ` (i.e. they should be static + * IP or DNS-based). + */ + 'clusters'?: (_envoy_config_cluster_v3_Cluster)[]; + /** + * These static secrets can be used by :ref:`SdsSecretConfig + * ` + */ + 'secrets'?: (_envoy_extensions_transport_sockets_tls_v3_Secret)[]; +} + +export interface _envoy_config_bootstrap_v3_Bootstrap_StaticResources__Output { + /** + * Static :ref:`Listeners `. These listeners are + * available regardless of LDS configuration. + */ + 'listeners': (_envoy_config_listener_v3_Listener__Output)[]; + /** + * If a network based configuration source is specified for :ref:`cds_config + * `, it's necessary + * to have some initial cluster definitions available to allow Envoy to know + * how to speak to the management server. These cluster definitions may not + * use :ref:`EDS ` (i.e. they should be static + * IP or DNS-based). + */ + 'clusters': (_envoy_config_cluster_v3_Cluster__Output)[]; + /** + * These static secrets can be used by :ref:`SdsSecretConfig + * ` + */ + 'secrets': (_envoy_extensions_transport_sockets_tls_v3_Secret__Output)[]; +} + +/** + * Bootstrap :ref:`configuration overview `. + * [#next-free-field: 33] + */ +export interface Bootstrap { + /** + * Node identity to present to the management server and for instance + * identification purposes (e.g. in generated headers). + */ + 'node'?: (_envoy_config_core_v3_Node | null); + /** + * Statically specified resources. + */ + 'static_resources'?: (_envoy_config_bootstrap_v3_Bootstrap_StaticResources | null); + /** + * xDS configuration sources. + */ + 'dynamic_resources'?: (_envoy_config_bootstrap_v3_Bootstrap_DynamicResources | null); + /** + * Configuration for the cluster manager which owns all upstream clusters + * within the server. + */ + 'cluster_manager'?: (_envoy_config_bootstrap_v3_ClusterManager | null); + /** + * Optional file system path to search for startup flag files. + */ + 'flags_path'?: (string); + /** + * Optional set of stats sinks. + */ + 'stats_sinks'?: (_envoy_config_metrics_v3_StatsSink)[]; + /** + * Optional duration between flushes to configured stats sinks. For + * performance reasons Envoy latches counters and only flushes counters and + * gauges at a periodic interval. If not specified the default is 5000ms (5 + * seconds). Only one of `stats_flush_interval` or `stats_flush_on_admin` + * can be set. + * Duration must be at least 1ms and at most 5 min. + */ + 'stats_flush_interval'?: (_google_protobuf_Duration | null); + /** + * Optional watchdog configuration. + * This is for a single watchdog configuration for the entire system. + * Deprecated in favor of *watchdogs* which has finer granularity. + */ + 'watchdog'?: (_envoy_config_bootstrap_v3_Watchdog | null); + /** + * Configuration for an external tracing provider. + * + * .. attention:: + * This field has been deprecated in favor of :ref:`HttpConnectionManager.Tracing.provider + * `. + */ + 'tracing'?: (_envoy_config_trace_v3_Tracing | null); + /** + * Configuration for the local administration HTTP server. + */ + 'admin'?: (_envoy_config_bootstrap_v3_Admin | null); + /** + * Configuration for internal processing of stats. + */ + 'stats_config'?: (_envoy_config_metrics_v3_StatsConfig | null); + /** + * Health discovery service config option. + * (:ref:`core.ApiConfigSource `) + */ + 'hds_config'?: (_envoy_config_core_v3_ApiConfigSource | null); + /** + * Optional overload manager configuration. + */ + 'overload_manager'?: (_envoy_config_overload_v3_OverloadManager | null); + /** + * Enable :ref:`stats for event dispatcher `, defaults to false. + * Note that this records a value for each iteration of the event loop on every thread. This + * should normally be minimal overhead, but when using + * :ref:`statsd `, it will send each observed value + * over the wire individually because the statsd protocol doesn't have any way to represent a + * histogram summary. Be aware that this can be a very large volume of data. + */ + 'enable_dispatcher_stats'?: (boolean); + /** + * Configuration for the runtime configuration provider. If not + * specified, a “null” provider will be used which will result in all defaults + * being used. + */ + 'layered_runtime'?: (_envoy_config_bootstrap_v3_LayeredRuntime | null); + /** + * Optional string which will be used in lieu of x-envoy in prefixing headers. + * + * For example, if this string is present and set to X-Foo, then x-envoy-retry-on will be + * transformed into x-foo-retry-on etc. + * + * Note this applies to the headers Envoy will generate, the headers Envoy will sanitize, and the + * headers Envoy will trust for core code and core extensions only. Be VERY careful making + * changes to this string, especially in multi-layer Envoy deployments or deployments using + * extensions which are not upstream. + */ + 'header_prefix'?: (string); + /** + * Optional proxy version which will be used to set the value of :ref:`server.version statistic + * ` if specified. Envoy will not process this value, it will be sent as is to + * :ref:`stats sinks `. + */ + 'stats_server_version_override'?: (_google_protobuf_UInt64Value | null); + /** + * Always use TCP queries instead of UDP queries for DNS lookups. + * This may be overridden on a per-cluster basis in cds_config, + * when :ref:`dns_resolvers ` and + * :ref:`use_tcp_for_dns_lookups ` are + * specified. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple' API only uses UDP for DNS resolution. + * This field is deprecated in favor of *dns_resolution_config* + * which aggregates all of the DNS resolver configuration in a single message. + */ + 'use_tcp_for_dns_lookups'?: (boolean); + /** + * Specifies optional bootstrap extensions to be instantiated at startup time. + * Each item contains extension specific configuration. + * [#extension-category: envoy.bootstrap] + */ + 'bootstrap_extensions'?: (_envoy_config_core_v3_TypedExtensionConfig)[]; + /** + * Configuration sources that will participate in + * xdstp:// URL authority resolution. The algorithm is as + * follows: + * 1. The authority field is taken from the xdstp:// URL, call + * this *resource_authority*. + * 2. *resource_authority* is compared against the authorities in any peer + * *ConfigSource*. The peer *ConfigSource* is the configuration source + * message which would have been used unconditionally for resolution + * with opaque resource names. If there is a match with an authority, the + * peer *ConfigSource* message is used. + * 3. *resource_authority* is compared sequentially with the authorities in + * each configuration source in *config_sources*. The first *ConfigSource* + * to match wins. + * 4. As a fallback, if no configuration source matches, then + * *default_config_source* is used. + * 5. If *default_config_source* is not specified, resolution fails. + * [#not-implemented-hide:] + */ + 'config_sources'?: (_envoy_config_core_v3_ConfigSource)[]; + /** + * Default configuration source for xdstp:// URLs if all + * other resolution fails. + * [#not-implemented-hide:] + */ + 'default_config_source'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * Optional overriding of default socket interface. The value must be the name of one of the + * socket interface factories initialized through a bootstrap extension + */ + 'default_socket_interface'?: (string); + /** + * Global map of CertificateProvider instances. These instances are referred to by name in the + * :ref:`CommonTlsContext.CertificateProviderInstance.instance_name + * ` + * field. + * [#not-implemented-hide:] + */ + 'certificate_provider_instances'?: ({[key: string]: _envoy_config_core_v3_TypedExtensionConfig}); + /** + * A list of :ref:`Node ` field names + * that will be included in the context parameters of the effective + * xdstp:// URL that is sent in a discovery request when resource + * locators are used for LDS/CDS. Any non-string field will have its JSON + * encoding set as the context parameter value, with the exception of + * metadata, which will be flattened (see example below). The supported field + * names are: + * - "cluster" + * - "id" + * - "locality.region" + * - "locality.sub_zone" + * - "locality.zone" + * - "metadata" + * - "user_agent_build_version.metadata" + * - "user_agent_build_version.version" + * - "user_agent_name" + * - "user_agent_version" + * + * The node context parameters act as a base layer dictionary for the context + * parameters (i.e. more specific resource specific context parameters will + * override). Field names will be prefixed with “udpa.node.” when included in + * context parameters. + * + * For example, if node_context_params is ``["user_agent_name", "metadata"]``, + * the implied context parameters might be:: + * + * node.user_agent_name: "envoy" + * node.metadata.foo: "{\"bar\": \"baz\"}" + * node.metadata.some: "42" + * node.metadata.thing: "\"thing\"" + * + * [#not-implemented-hide:] + */ + 'node_context_params'?: (string)[]; + /** + * Optional watchdogs configuration. + * This is used for specifying different watchdogs for the different subsystems. + * [#extension-category: envoy.guarddog_actions] + */ + 'watchdogs'?: (_envoy_config_bootstrap_v3_Watchdogs | null); + /** + * Specifies optional extensions instantiated at startup time and + * invoked during crash time on the request that caused the crash. + */ + 'fatal_actions'?: (_envoy_config_bootstrap_v3_FatalAction)[]; + /** + * Flush stats to sinks only when queried for on the admin interface. If set, + * a flush timer is not created. Only one of `stats_flush_on_admin` or + * `stats_flush_interval` can be set. + */ + 'stats_flush_on_admin'?: (boolean); + /** + * DNS resolution configuration which includes the underlying dns resolver addresses and options. + * This may be overridden on a per-cluster basis in cds_config, when + * :ref:`dns_resolution_config ` + * is specified. + * *dns_resolution_config* will be deprecated once + * :ref:'typed_dns_resolver_config ' + * is fully supported. + */ + 'dns_resolution_config'?: (_envoy_config_core_v3_DnsResolutionConfig | null); + /** + * DNS resolver type configuration extension. This extension can be used to configure c-ares, apple, + * or any other DNS resolver types and the related parameters. + * For example, an object of :ref:`DnsResolutionConfig ` + * can be packed into this *typed_dns_resolver_config*. This configuration will replace the + * :ref:'dns_resolution_config ' + * configuration eventually. + * TODO(yanjunxiang): Investigate the deprecation plan for *dns_resolution_config*. + * During the transition period when both *dns_resolution_config* and *typed_dns_resolver_config* exists, + * this configuration is optional. + * When *typed_dns_resolver_config* is in place, Envoy will use it and ignore *dns_resolution_config*. + * When *typed_dns_resolver_config* is missing, the default behavior is in place. + * [#not-implemented-hide:] + */ + 'typed_dns_resolver_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + /** + * Specifies a set of headers that need to be registered as inline header. This configuration + * allows users to customize the inline headers on-demand at Envoy startup without modifying + * Envoy's source code. + * + * Note that the 'set-cookie' header cannot be registered as inline header. + */ + 'inline_headers'?: (_envoy_config_bootstrap_v3_CustomInlineHeader)[]; + 'stats_flush'?: "stats_flush_on_admin"; +} + +/** + * Bootstrap :ref:`configuration overview `. + * [#next-free-field: 33] + */ +export interface Bootstrap__Output { + /** + * Node identity to present to the management server and for instance + * identification purposes (e.g. in generated headers). + */ + 'node': (_envoy_config_core_v3_Node__Output | null); + /** + * Statically specified resources. + */ + 'static_resources': (_envoy_config_bootstrap_v3_Bootstrap_StaticResources__Output | null); + /** + * xDS configuration sources. + */ + 'dynamic_resources': (_envoy_config_bootstrap_v3_Bootstrap_DynamicResources__Output | null); + /** + * Configuration for the cluster manager which owns all upstream clusters + * within the server. + */ + 'cluster_manager': (_envoy_config_bootstrap_v3_ClusterManager__Output | null); + /** + * Optional file system path to search for startup flag files. + */ + 'flags_path': (string); + /** + * Optional set of stats sinks. + */ + 'stats_sinks': (_envoy_config_metrics_v3_StatsSink__Output)[]; + /** + * Optional duration between flushes to configured stats sinks. For + * performance reasons Envoy latches counters and only flushes counters and + * gauges at a periodic interval. If not specified the default is 5000ms (5 + * seconds). Only one of `stats_flush_interval` or `stats_flush_on_admin` + * can be set. + * Duration must be at least 1ms and at most 5 min. + */ + 'stats_flush_interval': (_google_protobuf_Duration__Output | null); + /** + * Optional watchdog configuration. + * This is for a single watchdog configuration for the entire system. + * Deprecated in favor of *watchdogs* which has finer granularity. + */ + 'watchdog': (_envoy_config_bootstrap_v3_Watchdog__Output | null); + /** + * Configuration for an external tracing provider. + * + * .. attention:: + * This field has been deprecated in favor of :ref:`HttpConnectionManager.Tracing.provider + * `. + */ + 'tracing': (_envoy_config_trace_v3_Tracing__Output | null); + /** + * Configuration for the local administration HTTP server. + */ + 'admin': (_envoy_config_bootstrap_v3_Admin__Output | null); + /** + * Configuration for internal processing of stats. + */ + 'stats_config': (_envoy_config_metrics_v3_StatsConfig__Output | null); + /** + * Health discovery service config option. + * (:ref:`core.ApiConfigSource `) + */ + 'hds_config': (_envoy_config_core_v3_ApiConfigSource__Output | null); + /** + * Optional overload manager configuration. + */ + 'overload_manager': (_envoy_config_overload_v3_OverloadManager__Output | null); + /** + * Enable :ref:`stats for event dispatcher `, defaults to false. + * Note that this records a value for each iteration of the event loop on every thread. This + * should normally be minimal overhead, but when using + * :ref:`statsd `, it will send each observed value + * over the wire individually because the statsd protocol doesn't have any way to represent a + * histogram summary. Be aware that this can be a very large volume of data. + */ + 'enable_dispatcher_stats': (boolean); + /** + * Configuration for the runtime configuration provider. If not + * specified, a “null” provider will be used which will result in all defaults + * being used. + */ + 'layered_runtime': (_envoy_config_bootstrap_v3_LayeredRuntime__Output | null); + /** + * Optional string which will be used in lieu of x-envoy in prefixing headers. + * + * For example, if this string is present and set to X-Foo, then x-envoy-retry-on will be + * transformed into x-foo-retry-on etc. + * + * Note this applies to the headers Envoy will generate, the headers Envoy will sanitize, and the + * headers Envoy will trust for core code and core extensions only. Be VERY careful making + * changes to this string, especially in multi-layer Envoy deployments or deployments using + * extensions which are not upstream. + */ + 'header_prefix': (string); + /** + * Optional proxy version which will be used to set the value of :ref:`server.version statistic + * ` if specified. Envoy will not process this value, it will be sent as is to + * :ref:`stats sinks `. + */ + 'stats_server_version_override': (_google_protobuf_UInt64Value__Output | null); + /** + * Always use TCP queries instead of UDP queries for DNS lookups. + * This may be overridden on a per-cluster basis in cds_config, + * when :ref:`dns_resolvers ` and + * :ref:`use_tcp_for_dns_lookups ` are + * specified. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple' API only uses UDP for DNS resolution. + * This field is deprecated in favor of *dns_resolution_config* + * which aggregates all of the DNS resolver configuration in a single message. + */ + 'use_tcp_for_dns_lookups': (boolean); + /** + * Specifies optional bootstrap extensions to be instantiated at startup time. + * Each item contains extension specific configuration. + * [#extension-category: envoy.bootstrap] + */ + 'bootstrap_extensions': (_envoy_config_core_v3_TypedExtensionConfig__Output)[]; + /** + * Configuration sources that will participate in + * xdstp:// URL authority resolution. The algorithm is as + * follows: + * 1. The authority field is taken from the xdstp:// URL, call + * this *resource_authority*. + * 2. *resource_authority* is compared against the authorities in any peer + * *ConfigSource*. The peer *ConfigSource* is the configuration source + * message which would have been used unconditionally for resolution + * with opaque resource names. If there is a match with an authority, the + * peer *ConfigSource* message is used. + * 3. *resource_authority* is compared sequentially with the authorities in + * each configuration source in *config_sources*. The first *ConfigSource* + * to match wins. + * 4. As a fallback, if no configuration source matches, then + * *default_config_source* is used. + * 5. If *default_config_source* is not specified, resolution fails. + * [#not-implemented-hide:] + */ + 'config_sources': (_envoy_config_core_v3_ConfigSource__Output)[]; + /** + * Default configuration source for xdstp:// URLs if all + * other resolution fails. + * [#not-implemented-hide:] + */ + 'default_config_source': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * Optional overriding of default socket interface. The value must be the name of one of the + * socket interface factories initialized through a bootstrap extension + */ + 'default_socket_interface': (string); + /** + * Global map of CertificateProvider instances. These instances are referred to by name in the + * :ref:`CommonTlsContext.CertificateProviderInstance.instance_name + * ` + * field. + * [#not-implemented-hide:] + */ + 'certificate_provider_instances': ({[key: string]: _envoy_config_core_v3_TypedExtensionConfig__Output}); + /** + * A list of :ref:`Node ` field names + * that will be included in the context parameters of the effective + * xdstp:// URL that is sent in a discovery request when resource + * locators are used for LDS/CDS. Any non-string field will have its JSON + * encoding set as the context parameter value, with the exception of + * metadata, which will be flattened (see example below). The supported field + * names are: + * - "cluster" + * - "id" + * - "locality.region" + * - "locality.sub_zone" + * - "locality.zone" + * - "metadata" + * - "user_agent_build_version.metadata" + * - "user_agent_build_version.version" + * - "user_agent_name" + * - "user_agent_version" + * + * The node context parameters act as a base layer dictionary for the context + * parameters (i.e. more specific resource specific context parameters will + * override). Field names will be prefixed with “udpa.node.” when included in + * context parameters. + * + * For example, if node_context_params is ``["user_agent_name", "metadata"]``, + * the implied context parameters might be:: + * + * node.user_agent_name: "envoy" + * node.metadata.foo: "{\"bar\": \"baz\"}" + * node.metadata.some: "42" + * node.metadata.thing: "\"thing\"" + * + * [#not-implemented-hide:] + */ + 'node_context_params': (string)[]; + /** + * Optional watchdogs configuration. + * This is used for specifying different watchdogs for the different subsystems. + * [#extension-category: envoy.guarddog_actions] + */ + 'watchdogs': (_envoy_config_bootstrap_v3_Watchdogs__Output | null); + /** + * Specifies optional extensions instantiated at startup time and + * invoked during crash time on the request that caused the crash. + */ + 'fatal_actions': (_envoy_config_bootstrap_v3_FatalAction__Output)[]; + /** + * Flush stats to sinks only when queried for on the admin interface. If set, + * a flush timer is not created. Only one of `stats_flush_on_admin` or + * `stats_flush_interval` can be set. + */ + 'stats_flush_on_admin'?: (boolean); + /** + * DNS resolution configuration which includes the underlying dns resolver addresses and options. + * This may be overridden on a per-cluster basis in cds_config, when + * :ref:`dns_resolution_config ` + * is specified. + * *dns_resolution_config* will be deprecated once + * :ref:'typed_dns_resolver_config ' + * is fully supported. + */ + 'dns_resolution_config': (_envoy_config_core_v3_DnsResolutionConfig__Output | null); + /** + * DNS resolver type configuration extension. This extension can be used to configure c-ares, apple, + * or any other DNS resolver types and the related parameters. + * For example, an object of :ref:`DnsResolutionConfig ` + * can be packed into this *typed_dns_resolver_config*. This configuration will replace the + * :ref:'dns_resolution_config ' + * configuration eventually. + * TODO(yanjunxiang): Investigate the deprecation plan for *dns_resolution_config*. + * During the transition period when both *dns_resolution_config* and *typed_dns_resolver_config* exists, + * this configuration is optional. + * When *typed_dns_resolver_config* is in place, Envoy will use it and ignore *dns_resolution_config*. + * When *typed_dns_resolver_config* is missing, the default behavior is in place. + * [#not-implemented-hide:] + */ + 'typed_dns_resolver_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + /** + * Specifies a set of headers that need to be registered as inline header. This configuration + * allows users to customize the inline headers on-demand at Envoy startup without modifying + * Envoy's source code. + * + * Note that the 'set-cookie' header cannot be registered as inline header. + */ + 'inline_headers': (_envoy_config_bootstrap_v3_CustomInlineHeader__Output)[]; + 'stats_flush': "stats_flush_on_admin"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/ClusterManager.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/ClusterManager.ts new file mode 100644 index 000000000..571b96fb7 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/ClusterManager.ts @@ -0,0 +1,99 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { BindConfig as _envoy_config_core_v3_BindConfig, BindConfig__Output as _envoy_config_core_v3_BindConfig__Output } from '../../../../envoy/config/core/v3/BindConfig'; +import type { ApiConfigSource as _envoy_config_core_v3_ApiConfigSource, ApiConfigSource__Output as _envoy_config_core_v3_ApiConfigSource__Output } from '../../../../envoy/config/core/v3/ApiConfigSource'; +import type { EventServiceConfig as _envoy_config_core_v3_EventServiceConfig, EventServiceConfig__Output as _envoy_config_core_v3_EventServiceConfig__Output } from '../../../../envoy/config/core/v3/EventServiceConfig'; + +export interface _envoy_config_bootstrap_v3_ClusterManager_OutlierDetection { + /** + * Specifies the path to the outlier event log. + */ + 'event_log_path'?: (string); + /** + * [#not-implemented-hide:] + * The gRPC service for the outlier detection event service. + * If empty, outlier detection events won't be sent to a remote endpoint. + */ + 'event_service'?: (_envoy_config_core_v3_EventServiceConfig | null); +} + +export interface _envoy_config_bootstrap_v3_ClusterManager_OutlierDetection__Output { + /** + * Specifies the path to the outlier event log. + */ + 'event_log_path': (string); + /** + * [#not-implemented-hide:] + * The gRPC service for the outlier detection event service. + * If empty, outlier detection events won't be sent to a remote endpoint. + */ + 'event_service': (_envoy_config_core_v3_EventServiceConfig__Output | null); +} + +/** + * Cluster manager :ref:`architecture overview `. + */ +export interface ClusterManager { + /** + * Name of the local cluster (i.e., the cluster that owns the Envoy running + * this configuration). In order to enable :ref:`zone aware routing + * ` this option must be set. + * If *local_cluster_name* is defined then :ref:`clusters + * ` must be defined in the :ref:`Bootstrap + * static cluster resources + * `. This is unrelated to + * the :option:`--service-cluster` option which does not `affect zone aware + * routing `_. + */ + 'local_cluster_name'?: (string); + /** + * Optional global configuration for outlier detection. + */ + 'outlier_detection'?: (_envoy_config_bootstrap_v3_ClusterManager_OutlierDetection | null); + /** + * Optional configuration used to bind newly established upstream connections. + * This may be overridden on a per-cluster basis by upstream_bind_config in the cds_config. + */ + 'upstream_bind_config'?: (_envoy_config_core_v3_BindConfig | null); + /** + * A management server endpoint to stream load stats to via + * *StreamLoadStats*. This must have :ref:`api_type + * ` :ref:`GRPC + * `. + */ + 'load_stats_config'?: (_envoy_config_core_v3_ApiConfigSource | null); +} + +/** + * Cluster manager :ref:`architecture overview `. + */ +export interface ClusterManager__Output { + /** + * Name of the local cluster (i.e., the cluster that owns the Envoy running + * this configuration). In order to enable :ref:`zone aware routing + * ` this option must be set. + * If *local_cluster_name* is defined then :ref:`clusters + * ` must be defined in the :ref:`Bootstrap + * static cluster resources + * `. This is unrelated to + * the :option:`--service-cluster` option which does not `affect zone aware + * routing `_. + */ + 'local_cluster_name': (string); + /** + * Optional global configuration for outlier detection. + */ + 'outlier_detection': (_envoy_config_bootstrap_v3_ClusterManager_OutlierDetection__Output | null); + /** + * Optional configuration used to bind newly established upstream connections. + * This may be overridden on a per-cluster basis by upstream_bind_config in the cds_config. + */ + 'upstream_bind_config': (_envoy_config_core_v3_BindConfig__Output | null); + /** + * A management server endpoint to stream load stats to via + * *StreamLoadStats*. This must have :ref:`api_type + * ` :ref:`GRPC + * `. + */ + 'load_stats_config': (_envoy_config_core_v3_ApiConfigSource__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/CustomInlineHeader.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/CustomInlineHeader.ts new file mode 100644 index 000000000..f0e2d29aa --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/CustomInlineHeader.ts @@ -0,0 +1,85 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + + +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +export enum _envoy_config_bootstrap_v3_CustomInlineHeader_InlineHeaderType { + REQUEST_HEADER = 0, + REQUEST_TRAILER = 1, + RESPONSE_HEADER = 2, + RESPONSE_TRAILER = 3, +} + +/** + * Used to specify the header that needs to be registered as an inline header. + * + * If request or response contain multiple headers with the same name and the header + * name is registered as an inline header. Then multiple headers will be folded + * into one, and multiple header values will be concatenated by a suitable delimiter. + * The delimiter is generally a comma. + * + * For example, if 'foo' is registered as an inline header, and the headers contains + * the following two headers: + * + * .. code-block:: text + * + * foo: bar + * foo: eep + * + * Then they will eventually be folded into: + * + * .. code-block:: text + * + * foo: bar, eep + * + * Inline headers provide O(1) search performance, but each inline header imposes + * an additional memory overhead on all instances of the corresponding type of + * HeaderMap or TrailerMap. + */ +export interface CustomInlineHeader { + /** + * The name of the header that is expected to be set as the inline header. + */ + 'inline_header_name'?: (string); + /** + * The type of the header that is expected to be set as the inline header. + */ + 'inline_header_type'?: (_envoy_config_bootstrap_v3_CustomInlineHeader_InlineHeaderType | keyof typeof _envoy_config_bootstrap_v3_CustomInlineHeader_InlineHeaderType); +} + +/** + * Used to specify the header that needs to be registered as an inline header. + * + * If request or response contain multiple headers with the same name and the header + * name is registered as an inline header. Then multiple headers will be folded + * into one, and multiple header values will be concatenated by a suitable delimiter. + * The delimiter is generally a comma. + * + * For example, if 'foo' is registered as an inline header, and the headers contains + * the following two headers: + * + * .. code-block:: text + * + * foo: bar + * foo: eep + * + * Then they will eventually be folded into: + * + * .. code-block:: text + * + * foo: bar, eep + * + * Inline headers provide O(1) search performance, but each inline header imposes + * an additional memory overhead on all instances of the corresponding type of + * HeaderMap or TrailerMap. + */ +export interface CustomInlineHeader__Output { + /** + * The name of the header that is expected to be set as the inline header. + */ + 'inline_header_name': (string); + /** + * The type of the header that is expected to be set as the inline header. + */ + 'inline_header_type': (keyof typeof _envoy_config_bootstrap_v3_CustomInlineHeader_InlineHeaderType); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/FatalAction.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/FatalAction.ts new file mode 100644 index 000000000..236afded5 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/FatalAction.ts @@ -0,0 +1,39 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +/** + * Fatal actions to run while crashing. Actions can be safe (meaning they are + * async-signal safe) or unsafe. We run all safe actions before we run unsafe actions. + * If using an unsafe action that could get stuck or deadlock, it important to + * have an out of band system to terminate the process. + * + * The interface for the extension is ``Envoy::Server::Configuration::FatalAction``. + * *FatalAction* extensions live in the ``envoy.extensions.fatal_actions`` API + * namespace. + */ +export interface FatalAction { + /** + * Extension specific configuration for the action. It's expected to conform + * to the ``Envoy::Server::Configuration::FatalAction`` interface. + */ + 'config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); +} + +/** + * Fatal actions to run while crashing. Actions can be safe (meaning they are + * async-signal safe) or unsafe. We run all safe actions before we run unsafe actions. + * If using an unsafe action that could get stuck or deadlock, it important to + * have an out of band system to terminate the process. + * + * The interface for the extension is ``Envoy::Server::Configuration::FatalAction``. + * *FatalAction* extensions live in the ``envoy.extensions.fatal_actions`` API + * namespace. + */ +export interface FatalAction__Output { + /** + * Extension specific configuration for the action. It's expected to conform + * to the ``Envoy::Server::Configuration::FatalAction`` interface. + */ + 'config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/LayeredRuntime.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/LayeredRuntime.ts new file mode 100644 index 000000000..3514d3140 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/LayeredRuntime.ts @@ -0,0 +1,25 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { RuntimeLayer as _envoy_config_bootstrap_v3_RuntimeLayer, RuntimeLayer__Output as _envoy_config_bootstrap_v3_RuntimeLayer__Output } from '../../../../envoy/config/bootstrap/v3/RuntimeLayer'; + +/** + * Runtime :ref:`configuration overview `. + */ +export interface LayeredRuntime { + /** + * The :ref:`layers ` of the runtime. This is ordered + * such that later layers in the list overlay earlier entries. + */ + 'layers'?: (_envoy_config_bootstrap_v3_RuntimeLayer)[]; +} + +/** + * Runtime :ref:`configuration overview `. + */ +export interface LayeredRuntime__Output { + /** + * The :ref:`layers ` of the runtime. This is ordered + * such that later layers in the list overlay earlier entries. + */ + 'layers': (_envoy_config_bootstrap_v3_RuntimeLayer__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Runtime.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Runtime.ts new file mode 100644 index 000000000..4f7713bcf --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Runtime.ts @@ -0,0 +1,77 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; + +/** + * Runtime :ref:`configuration overview ` (deprecated). + */ +export interface Runtime { + /** + * The implementation assumes that the file system tree is accessed via a + * symbolic link. An atomic link swap is used when a new tree should be + * switched to. This parameter specifies the path to the symbolic link. Envoy + * will watch the location for changes and reload the file system tree when + * they happen. If this parameter is not set, there will be no disk based + * runtime. + */ + 'symlink_root'?: (string); + /** + * Specifies the subdirectory to load within the root directory. This is + * useful if multiple systems share the same delivery mechanism. Envoy + * configuration elements can be contained in a dedicated subdirectory. + */ + 'subdirectory'?: (string); + /** + * Specifies an optional subdirectory to load within the root directory. If + * specified and the directory exists, configuration values within this + * directory will override those found in the primary subdirectory. This is + * useful when Envoy is deployed across many different types of servers. + * Sometimes it is useful to have a per service cluster directory for runtime + * configuration. See below for exactly how the override directory is used. + */ + 'override_subdirectory'?: (string); + /** + * Static base runtime. This will be :ref:`overridden + * ` by other runtime layers, e.g. + * disk or admin. This follows the :ref:`runtime protobuf JSON representation + * encoding `. + */ + 'base'?: (_google_protobuf_Struct | null); +} + +/** + * Runtime :ref:`configuration overview ` (deprecated). + */ +export interface Runtime__Output { + /** + * The implementation assumes that the file system tree is accessed via a + * symbolic link. An atomic link swap is used when a new tree should be + * switched to. This parameter specifies the path to the symbolic link. Envoy + * will watch the location for changes and reload the file system tree when + * they happen. If this parameter is not set, there will be no disk based + * runtime. + */ + 'symlink_root': (string); + /** + * Specifies the subdirectory to load within the root directory. This is + * useful if multiple systems share the same delivery mechanism. Envoy + * configuration elements can be contained in a dedicated subdirectory. + */ + 'subdirectory': (string); + /** + * Specifies an optional subdirectory to load within the root directory. If + * specified and the directory exists, configuration values within this + * directory will override those found in the primary subdirectory. This is + * useful when Envoy is deployed across many different types of servers. + * Sometimes it is useful to have a per service cluster directory for runtime + * configuration. See below for exactly how the override directory is used. + */ + 'override_subdirectory': (string); + /** + * Static base runtime. This will be :ref:`overridden + * ` by other runtime layers, e.g. + * disk or admin. This follows the :ref:`runtime protobuf JSON representation + * encoding `. + */ + 'base': (_google_protobuf_Struct__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/RuntimeLayer.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/RuntimeLayer.ts new file mode 100644 index 000000000..b072bfa7d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/RuntimeLayer.ts @@ -0,0 +1,142 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../envoy/config/core/v3/ConfigSource'; + +/** + * :ref:`Admin console runtime ` layer. + */ +export interface _envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer { +} + +/** + * :ref:`Admin console runtime ` layer. + */ +export interface _envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer__Output { +} + +/** + * :ref:`Disk runtime ` layer. + */ +export interface _envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer { + /** + * The implementation assumes that the file system tree is accessed via a + * symbolic link. An atomic link swap is used when a new tree should be + * switched to. This parameter specifies the path to the symbolic link. + * Envoy will watch the location for changes and reload the file system tree + * when they happen. See documentation on runtime :ref:`atomicity + * ` for further details on how reloads are + * treated. + */ + 'symlink_root'?: (string); + /** + * Specifies the subdirectory to load within the root directory. This is + * useful if multiple systems share the same delivery mechanism. Envoy + * configuration elements can be contained in a dedicated subdirectory. + */ + 'subdirectory'?: (string); + /** + * :ref:`Append ` the + * service cluster to the path under symlink root. + */ + 'append_service_cluster'?: (boolean); +} + +/** + * :ref:`Disk runtime ` layer. + */ +export interface _envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer__Output { + /** + * The implementation assumes that the file system tree is accessed via a + * symbolic link. An atomic link swap is used when a new tree should be + * switched to. This parameter specifies the path to the symbolic link. + * Envoy will watch the location for changes and reload the file system tree + * when they happen. See documentation on runtime :ref:`atomicity + * ` for further details on how reloads are + * treated. + */ + 'symlink_root': (string); + /** + * Specifies the subdirectory to load within the root directory. This is + * useful if multiple systems share the same delivery mechanism. Envoy + * configuration elements can be contained in a dedicated subdirectory. + */ + 'subdirectory': (string); + /** + * :ref:`Append ` the + * service cluster to the path under symlink root. + */ + 'append_service_cluster': (boolean); +} + +/** + * :ref:`Runtime Discovery Service (RTDS) ` layer. + */ +export interface _envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer { + /** + * Resource to subscribe to at *rtds_config* for the RTDS layer. + */ + 'name'?: (string); + /** + * RTDS configuration source. + */ + 'rtds_config'?: (_envoy_config_core_v3_ConfigSource | null); +} + +/** + * :ref:`Runtime Discovery Service (RTDS) ` layer. + */ +export interface _envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer__Output { + /** + * Resource to subscribe to at *rtds_config* for the RTDS layer. + */ + 'name': (string); + /** + * RTDS configuration source. + */ + 'rtds_config': (_envoy_config_core_v3_ConfigSource__Output | null); +} + +/** + * [#next-free-field: 6] + */ +export interface RuntimeLayer { + /** + * Descriptive name for the runtime layer. This is only used for the runtime + * :http:get:`/runtime` output. + */ + 'name'?: (string); + /** + * :ref:`Static runtime ` layer. + * This follows the :ref:`runtime protobuf JSON representation encoding + * `. Unlike static xDS resources, this static + * layer is overridable by later layers in the runtime virtual filesystem. + */ + 'static_layer'?: (_google_protobuf_Struct | null); + 'disk_layer'?: (_envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer | null); + 'admin_layer'?: (_envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer | null); + 'rtds_layer'?: (_envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer | null); + 'layer_specifier'?: "static_layer"|"disk_layer"|"admin_layer"|"rtds_layer"; +} + +/** + * [#next-free-field: 6] + */ +export interface RuntimeLayer__Output { + /** + * Descriptive name for the runtime layer. This is only used for the runtime + * :http:get:`/runtime` output. + */ + 'name': (string); + /** + * :ref:`Static runtime ` layer. + * This follows the :ref:`runtime protobuf JSON representation encoding + * `. Unlike static xDS resources, this static + * layer is overridable by later layers in the runtime virtual filesystem. + */ + 'static_layer'?: (_google_protobuf_Struct__Output | null); + 'disk_layer'?: (_envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer__Output | null); + 'admin_layer'?: (_envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer__Output | null); + 'rtds_layer'?: (_envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer__Output | null); + 'layer_specifier': "static_layer"|"disk_layer"|"admin_layer"|"rtds_layer"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Watchdog.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Watchdog.ts new file mode 100644 index 000000000..8cd743b56 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Watchdog.ts @@ -0,0 +1,141 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { Percent as _envoy_type_v3_Percent, Percent__Output as _envoy_type_v3_Percent__Output } from '../../../../envoy/type/v3/Percent'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +export interface _envoy_config_bootstrap_v3_Watchdog_WatchdogAction { + /** + * Extension specific configuration for the action. + */ + 'config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + 'event'?: (_envoy_config_bootstrap_v3_Watchdog_WatchdogAction_WatchdogEvent | keyof typeof _envoy_config_bootstrap_v3_Watchdog_WatchdogAction_WatchdogEvent); +} + +export interface _envoy_config_bootstrap_v3_Watchdog_WatchdogAction__Output { + /** + * Extension specific configuration for the action. + */ + 'config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + 'event': (keyof typeof _envoy_config_bootstrap_v3_Watchdog_WatchdogAction_WatchdogEvent); +} + +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +/** + * The events are fired in this order: KILL, MULTIKILL, MEGAMISS, MISS. + * Within an event type, actions execute in the order they are configured. + * For KILL/MULTIKILL there is a default PANIC that will run after the + * registered actions and kills the process if it wasn't already killed. + * It might be useful to specify several debug actions, and possibly an + * alternate FATAL action. + */ +export enum _envoy_config_bootstrap_v3_Watchdog_WatchdogAction_WatchdogEvent { + UNKNOWN = 0, + KILL = 1, + MULTIKILL = 2, + MEGAMISS = 3, + MISS = 4, +} + +/** + * Envoy process watchdog configuration. When configured, this monitors for + * nonresponsive threads and kills the process after the configured thresholds. + * See the :ref:`watchdog documentation ` for more information. + * [#next-free-field: 8] + */ +export interface Watchdog { + /** + * The duration after which Envoy counts a nonresponsive thread in the + * *watchdog_miss* statistic. If not specified the default is 200ms. + */ + 'miss_timeout'?: (_google_protobuf_Duration | null); + /** + * The duration after which Envoy counts a nonresponsive thread in the + * *watchdog_mega_miss* statistic. If not specified the default is + * 1000ms. + */ + 'megamiss_timeout'?: (_google_protobuf_Duration | null); + /** + * If a watched thread has been nonresponsive for this duration, assume a + * programming error and kill the entire Envoy process. Set to 0 to disable + * kill behavior. If not specified the default is 0 (disabled). + */ + 'kill_timeout'?: (_google_protobuf_Duration | null); + /** + * If max(2, ceil(registered_threads * Fraction(*multikill_threshold*))) + * threads have been nonresponsive for at least this duration kill the entire + * Envoy process. Set to 0 to disable this behavior. If not specified the + * default is 0 (disabled). + */ + 'multikill_timeout'?: (_google_protobuf_Duration | null); + /** + * Sets the threshold for *multikill_timeout* in terms of the percentage of + * nonresponsive threads required for the *multikill_timeout*. + * If not specified the default is 0. + */ + 'multikill_threshold'?: (_envoy_type_v3_Percent | null); + /** + * Defines the maximum jitter used to adjust the *kill_timeout* if *kill_timeout* is + * enabled. Enabling this feature would help to reduce risk of synchronized + * watchdog kill events across proxies due to external triggers. Set to 0 to + * disable. If not specified the default is 0 (disabled). + */ + 'max_kill_timeout_jitter'?: (_google_protobuf_Duration | null); + /** + * Register actions that will fire on given WatchDog events. + * See *WatchDogAction* for priority of events. + */ + 'actions'?: (_envoy_config_bootstrap_v3_Watchdog_WatchdogAction)[]; +} + +/** + * Envoy process watchdog configuration. When configured, this monitors for + * nonresponsive threads and kills the process after the configured thresholds. + * See the :ref:`watchdog documentation ` for more information. + * [#next-free-field: 8] + */ +export interface Watchdog__Output { + /** + * The duration after which Envoy counts a nonresponsive thread in the + * *watchdog_miss* statistic. If not specified the default is 200ms. + */ + 'miss_timeout': (_google_protobuf_Duration__Output | null); + /** + * The duration after which Envoy counts a nonresponsive thread in the + * *watchdog_mega_miss* statistic. If not specified the default is + * 1000ms. + */ + 'megamiss_timeout': (_google_protobuf_Duration__Output | null); + /** + * If a watched thread has been nonresponsive for this duration, assume a + * programming error and kill the entire Envoy process. Set to 0 to disable + * kill behavior. If not specified the default is 0 (disabled). + */ + 'kill_timeout': (_google_protobuf_Duration__Output | null); + /** + * If max(2, ceil(registered_threads * Fraction(*multikill_threshold*))) + * threads have been nonresponsive for at least this duration kill the entire + * Envoy process. Set to 0 to disable this behavior. If not specified the + * default is 0 (disabled). + */ + 'multikill_timeout': (_google_protobuf_Duration__Output | null); + /** + * Sets the threshold for *multikill_timeout* in terms of the percentage of + * nonresponsive threads required for the *multikill_timeout*. + * If not specified the default is 0. + */ + 'multikill_threshold': (_envoy_type_v3_Percent__Output | null); + /** + * Defines the maximum jitter used to adjust the *kill_timeout* if *kill_timeout* is + * enabled. Enabling this feature would help to reduce risk of synchronized + * watchdog kill events across proxies due to external triggers. Set to 0 to + * disable. If not specified the default is 0 (disabled). + */ + 'max_kill_timeout_jitter': (_google_protobuf_Duration__Output | null); + /** + * Register actions that will fire on given WatchDog events. + * See *WatchDogAction* for priority of events. + */ + 'actions': (_envoy_config_bootstrap_v3_Watchdog_WatchdogAction__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Watchdogs.ts b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Watchdogs.ts new file mode 100644 index 000000000..b478615ea --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/bootstrap/v3/Watchdogs.ts @@ -0,0 +1,35 @@ +// Original file: deps/envoy-api/envoy/config/bootstrap/v3/bootstrap.proto + +import type { Watchdog as _envoy_config_bootstrap_v3_Watchdog, Watchdog__Output as _envoy_config_bootstrap_v3_Watchdog__Output } from '../../../../envoy/config/bootstrap/v3/Watchdog'; + +/** + * Allows you to specify different watchdog configs for different subsystems. + * This allows finer tuned policies for the watchdog. If a subsystem is omitted + * the default values for that system will be used. + */ +export interface Watchdogs { + /** + * Watchdog for the main thread. + */ + 'main_thread_watchdog'?: (_envoy_config_bootstrap_v3_Watchdog | null); + /** + * Watchdog for the worker threads. + */ + 'worker_watchdog'?: (_envoy_config_bootstrap_v3_Watchdog | null); +} + +/** + * Allows you to specify different watchdog configs for different subsystems. + * This allows finer tuned policies for the watchdog. If a subsystem is omitted + * the default values for that system will be used. + */ +export interface Watchdogs__Output { + /** + * Watchdog for the main thread. + */ + 'main_thread_watchdog': (_envoy_config_bootstrap_v3_Watchdog__Output | null); + /** + * Watchdog for the worker threads. + */ + 'worker_watchdog': (_envoy_config_bootstrap_v3_Watchdog__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/CircuitBreakers.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/CircuitBreakers.ts similarity index 63% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/CircuitBreakers.ts rename to packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/CircuitBreakers.ts index edf946590..12731b056 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/CircuitBreakers.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/CircuitBreakers.ts @@ -1,10 +1,10 @@ -// Original file: deps/envoy-api/envoy/api/v2/cluster/circuit_breaker.proto +// Original file: deps/envoy-api/envoy/config/cluster/v3/circuit_breaker.proto -import type { RoutingPriority as _envoy_api_v2_core_RoutingPriority } from '../../../../envoy/api/v2/core/RoutingPriority'; +import type { RoutingPriority as _envoy_config_core_v3_RoutingPriority } from '../../../../envoy/config/core/v3/RoutingPriority'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -import type { Percent as _envoy_type_Percent, Percent__Output as _envoy_type_Percent__Output } from '../../../../envoy/type/Percent'; +import type { Percent as _envoy_type_v3_Percent, Percent__Output as _envoy_type_v3_Percent__Output } from '../../../../envoy/type/v3/Percent'; -export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds_RetryBudget { +export interface _envoy_config_cluster_v3_CircuitBreakers_Thresholds_RetryBudget { /** * Specifies the limit on concurrent retries as a percentage of the sum of active requests and * active pending requests. For example, if there are 100 active requests and the @@ -12,17 +12,17 @@ export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds_RetryBudget { * * This parameter is optional. Defaults to 20%. */ - 'budget_percent'?: (_envoy_type_Percent); + 'budget_percent'?: (_envoy_type_v3_Percent | null); /** * Specifies the minimum retry concurrency allowed for the retry budget. The limit on the * number of active retries may never go below this number. * * This parameter is optional. Defaults to 3. */ - 'min_retry_concurrency'?: (_google_protobuf_UInt32Value); + 'min_retry_concurrency'?: (_google_protobuf_UInt32Value | null); } -export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds_RetryBudget__Output { +export interface _envoy_config_cluster_v3_CircuitBreakers_Thresholds_RetryBudget__Output { /** * Specifies the limit on concurrent retries as a percentage of the sum of active requests and * active pending requests. For example, if there are 100 active requests and the @@ -30,47 +30,47 @@ export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds_RetryBudget__O * * This parameter is optional. Defaults to 20%. */ - 'budget_percent'?: (_envoy_type_Percent__Output); + 'budget_percent': (_envoy_type_v3_Percent__Output | null); /** * Specifies the minimum retry concurrency allowed for the retry budget. The limit on the * number of active retries may never go below this number. * * This parameter is optional. Defaults to 3. */ - 'min_retry_concurrency'?: (_google_protobuf_UInt32Value__Output); + 'min_retry_concurrency': (_google_protobuf_UInt32Value__Output | null); } /** * A Thresholds defines CircuitBreaker settings for a - * :ref:`RoutingPriority`. + * :ref:`RoutingPriority`. * [#next-free-field: 9] */ -export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds { +export interface _envoy_config_cluster_v3_CircuitBreakers_Thresholds { /** - * The :ref:`RoutingPriority` + * The :ref:`RoutingPriority` * the specified CircuitBreaker settings apply to. */ - 'priority'?: (_envoy_api_v2_core_RoutingPriority | keyof typeof _envoy_api_v2_core_RoutingPriority); + 'priority'?: (_envoy_config_core_v3_RoutingPriority | keyof typeof _envoy_config_core_v3_RoutingPriority); /** * The maximum number of connections that Envoy will make to the upstream * cluster. If not specified, the default is 1024. */ - 'max_connections'?: (_google_protobuf_UInt32Value); + 'max_connections'?: (_google_protobuf_UInt32Value | null); /** * The maximum number of pending requests that Envoy will allow to the * upstream cluster. If not specified, the default is 1024. */ - 'max_pending_requests'?: (_google_protobuf_UInt32Value); + 'max_pending_requests'?: (_google_protobuf_UInt32Value | null); /** * The maximum number of parallel requests that Envoy will make to the * upstream cluster. If not specified, the default is 1024. */ - 'max_requests'?: (_google_protobuf_UInt32Value); + 'max_requests'?: (_google_protobuf_UInt32Value | null); /** * The maximum number of parallel retries that Envoy will allow to the * upstream cluster. If not specified, the default is 3. */ - 'max_retries'?: (_google_protobuf_UInt32Value); + 'max_retries'?: (_google_protobuf_UInt32Value | null); /** * Specifies a limit on concurrent retries in relation to the number of active requests. This * parameter is optional. @@ -80,7 +80,7 @@ export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds { * If this field is set, the retry budget will override any configured retry circuit * breaker. */ - 'retry_budget'?: (_envoy_api_v2_cluster_CircuitBreakers_Thresholds_RetryBudget); + 'retry_budget'?: (_envoy_config_cluster_v3_CircuitBreakers_Thresholds_RetryBudget | null); /** * If track_remaining is true, then stats will be published that expose * the number of resources remaining until the circuit breakers open. If @@ -99,40 +99,40 @@ export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds { * :ref:`Circuit Breaking ` for * more details. */ - 'max_connection_pools'?: (_google_protobuf_UInt32Value); + 'max_connection_pools'?: (_google_protobuf_UInt32Value | null); } /** * A Thresholds defines CircuitBreaker settings for a - * :ref:`RoutingPriority`. + * :ref:`RoutingPriority`. * [#next-free-field: 9] */ -export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds__Output { +export interface _envoy_config_cluster_v3_CircuitBreakers_Thresholds__Output { /** - * The :ref:`RoutingPriority` + * The :ref:`RoutingPriority` * the specified CircuitBreaker settings apply to. */ - 'priority': (keyof typeof _envoy_api_v2_core_RoutingPriority); + 'priority': (keyof typeof _envoy_config_core_v3_RoutingPriority); /** * The maximum number of connections that Envoy will make to the upstream * cluster. If not specified, the default is 1024. */ - 'max_connections'?: (_google_protobuf_UInt32Value__Output); + 'max_connections': (_google_protobuf_UInt32Value__Output | null); /** * The maximum number of pending requests that Envoy will allow to the * upstream cluster. If not specified, the default is 1024. */ - 'max_pending_requests'?: (_google_protobuf_UInt32Value__Output); + 'max_pending_requests': (_google_protobuf_UInt32Value__Output | null); /** * The maximum number of parallel requests that Envoy will make to the * upstream cluster. If not specified, the default is 1024. */ - 'max_requests'?: (_google_protobuf_UInt32Value__Output); + 'max_requests': (_google_protobuf_UInt32Value__Output | null); /** * The maximum number of parallel retries that Envoy will allow to the * upstream cluster. If not specified, the default is 3. */ - 'max_retries'?: (_google_protobuf_UInt32Value__Output); + 'max_retries': (_google_protobuf_UInt32Value__Output | null); /** * Specifies a limit on concurrent retries in relation to the number of active requests. This * parameter is optional. @@ -142,7 +142,7 @@ export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds__Output { * If this field is set, the retry budget will override any configured retry circuit * breaker. */ - 'retry_budget'?: (_envoy_api_v2_cluster_CircuitBreakers_Thresholds_RetryBudget__Output); + 'retry_budget': (_envoy_config_cluster_v3_CircuitBreakers_Thresholds_RetryBudget__Output | null); /** * If track_remaining is true, then stats will be published that expose * the number of resources remaining until the circuit breakers open. If @@ -161,7 +161,7 @@ export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds__Output { * :ref:`Circuit Breaking ` for * more details. */ - 'max_connection_pools'?: (_google_protobuf_UInt32Value__Output); + 'max_connection_pools': (_google_protobuf_UInt32Value__Output | null); } /** @@ -170,13 +170,13 @@ export interface _envoy_api_v2_cluster_CircuitBreakers_Thresholds__Output { */ export interface CircuitBreakers { /** - * If multiple :ref:`Thresholds` - * are defined with the same :ref:`RoutingPriority`, + * If multiple :ref:`Thresholds` + * are defined with the same :ref:`RoutingPriority`, * the first one in the list is used. If no Thresholds is defined for a given - * :ref:`RoutingPriority`, the default values + * :ref:`RoutingPriority`, the default values * are used. */ - 'thresholds'?: (_envoy_api_v2_cluster_CircuitBreakers_Thresholds)[]; + 'thresholds'?: (_envoy_config_cluster_v3_CircuitBreakers_Thresholds)[]; } /** @@ -185,11 +185,11 @@ export interface CircuitBreakers { */ export interface CircuitBreakers__Output { /** - * If multiple :ref:`Thresholds` - * are defined with the same :ref:`RoutingPriority`, + * If multiple :ref:`Thresholds` + * are defined with the same :ref:`RoutingPriority`, * the first one in the list is used. If no Thresholds is defined for a given - * :ref:`RoutingPriority`, the default values + * :ref:`RoutingPriority`, the default values * are used. */ - 'thresholds': (_envoy_api_v2_cluster_CircuitBreakers_Thresholds__Output)[]; + 'thresholds': (_envoy_config_cluster_v3_CircuitBreakers_Thresholds__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/Cluster.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/Cluster.ts new file mode 100644 index 000000000..12ec7b633 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/Cluster.ts @@ -0,0 +1,2224 @@ +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { HealthCheck as _envoy_config_core_v3_HealthCheck, HealthCheck__Output as _envoy_config_core_v3_HealthCheck__Output } from '../../../../envoy/config/core/v3/HealthCheck'; +import type { CircuitBreakers as _envoy_config_cluster_v3_CircuitBreakers, CircuitBreakers__Output as _envoy_config_cluster_v3_CircuitBreakers__Output } from '../../../../envoy/config/cluster/v3/CircuitBreakers'; +import type { Http1ProtocolOptions as _envoy_config_core_v3_Http1ProtocolOptions, Http1ProtocolOptions__Output as _envoy_config_core_v3_Http1ProtocolOptions__Output } from '../../../../envoy/config/core/v3/Http1ProtocolOptions'; +import type { Http2ProtocolOptions as _envoy_config_core_v3_Http2ProtocolOptions, Http2ProtocolOptions__Output as _envoy_config_core_v3_Http2ProtocolOptions__Output } from '../../../../envoy/config/core/v3/Http2ProtocolOptions'; +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; +import type { OutlierDetection as _envoy_config_cluster_v3_OutlierDetection, OutlierDetection__Output as _envoy_config_cluster_v3_OutlierDetection__Output } from '../../../../envoy/config/cluster/v3/OutlierDetection'; +import type { BindConfig as _envoy_config_core_v3_BindConfig, BindConfig__Output as _envoy_config_core_v3_BindConfig__Output } from '../../../../envoy/config/core/v3/BindConfig'; +import type { TransportSocket as _envoy_config_core_v3_TransportSocket, TransportSocket__Output as _envoy_config_core_v3_TransportSocket__Output } from '../../../../envoy/config/core/v3/TransportSocket'; +import type { Metadata as _envoy_config_core_v3_Metadata, Metadata__Output as _envoy_config_core_v3_Metadata__Output } from '../../../../envoy/config/core/v3/Metadata'; +import type { HttpProtocolOptions as _envoy_config_core_v3_HttpProtocolOptions, HttpProtocolOptions__Output as _envoy_config_core_v3_HttpProtocolOptions__Output } from '../../../../envoy/config/core/v3/HttpProtocolOptions'; +import type { UpstreamConnectionOptions as _envoy_config_cluster_v3_UpstreamConnectionOptions, UpstreamConnectionOptions__Output as _envoy_config_cluster_v3_UpstreamConnectionOptions__Output } from '../../../../envoy/config/cluster/v3/UpstreamConnectionOptions'; +import type { ClusterLoadAssignment as _envoy_config_endpoint_v3_ClusterLoadAssignment, ClusterLoadAssignment__Output as _envoy_config_endpoint_v3_ClusterLoadAssignment__Output } from '../../../../envoy/config/endpoint/v3/ClusterLoadAssignment'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { Filter as _envoy_config_cluster_v3_Filter, Filter__Output as _envoy_config_cluster_v3_Filter__Output } from '../../../../envoy/config/cluster/v3/Filter'; +import type { LoadBalancingPolicy as _envoy_config_cluster_v3_LoadBalancingPolicy, LoadBalancingPolicy__Output as _envoy_config_cluster_v3_LoadBalancingPolicy__Output } from '../../../../envoy/config/cluster/v3/LoadBalancingPolicy'; +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../envoy/config/core/v3/ConfigSource'; +import type { UpstreamHttpProtocolOptions as _envoy_config_core_v3_UpstreamHttpProtocolOptions, UpstreamHttpProtocolOptions__Output as _envoy_config_core_v3_UpstreamHttpProtocolOptions__Output } from '../../../../envoy/config/core/v3/UpstreamHttpProtocolOptions'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; +import type { TrackClusterStats as _envoy_config_cluster_v3_TrackClusterStats, TrackClusterStats__Output as _envoy_config_cluster_v3_TrackClusterStats__Output } from '../../../../envoy/config/cluster/v3/TrackClusterStats'; +import type { DnsResolutionConfig as _envoy_config_core_v3_DnsResolutionConfig, DnsResolutionConfig__Output as _envoy_config_core_v3_DnsResolutionConfig__Output } from '../../../../envoy/config/core/v3/DnsResolutionConfig'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import type { RuntimeDouble as _envoy_config_core_v3_RuntimeDouble, RuntimeDouble__Output as _envoy_config_core_v3_RuntimeDouble__Output } from '../../../../envoy/config/core/v3/RuntimeDouble'; +import type { UInt64Value as _google_protobuf_UInt64Value, UInt64Value__Output as _google_protobuf_UInt64Value__Output } from '../../../../google/protobuf/UInt64Value'; +import type { Percent as _envoy_type_v3_Percent, Percent__Output as _envoy_type_v3_Percent__Output } from '../../../../envoy/type/v3/Percent'; +import type { DoubleValue as _google_protobuf_DoubleValue, DoubleValue__Output as _google_protobuf_DoubleValue__Output } from '../../../../google/protobuf/DoubleValue'; +import type { Long } from '@grpc/proto-loader'; + +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +export enum _envoy_config_cluster_v3_Cluster_ClusterProtocolSelection { + /** + * Cluster can only operate on one of the possible upstream protocols (HTTP1.1, HTTP2). + * If :ref:`http2_protocol_options ` are + * present, HTTP2 will be used, otherwise HTTP1.1 will be used. + */ + USE_CONFIGURED_PROTOCOL = 0, + /** + * Use HTTP1.1 or HTTP2, depending on which one is used on the downstream connection. + */ + USE_DOWNSTREAM_PROTOCOL = 1, +} + +/** + * Common configuration for all load balancer implementations. + * [#next-free-field: 8] + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig { + /** + * Configures the :ref:`healthy panic threshold `. + * If not specified, the default is 50%. + * To disable panic mode, set to 0%. + * + * .. note:: + * The specified percent will be truncated to the nearest 1%. + */ + 'healthy_panic_threshold'?: (_envoy_type_v3_Percent | null); + 'zone_aware_lb_config'?: (_envoy_config_cluster_v3_Cluster_CommonLbConfig_ZoneAwareLbConfig | null); + 'locality_weighted_lb_config'?: (_envoy_config_cluster_v3_Cluster_CommonLbConfig_LocalityWeightedLbConfig | null); + /** + * If set, all health check/weight/metadata updates that happen within this duration will be + * merged and delivered in one shot when the duration expires. The start of the duration is when + * the first update happens. This is useful for big clusters, with potentially noisy deploys + * that might trigger excessive CPU usage due to a constant stream of healthcheck state changes + * or metadata updates. The first set of updates to be seen apply immediately (e.g.: a new + * cluster). Please always keep in mind that the use of sandbox technologies may change this + * behavior. + * + * If this is not set, we default to a merge window of 1000ms. To disable it, set the merge + * window to 0. + * + * Note: merging does not apply to cluster membership changes (e.g.: adds/removes); this is + * because merging those updates isn't currently safe. See + * https://github.com/envoyproxy/envoy/pull/3941. + */ + 'update_merge_window'?: (_google_protobuf_Duration | null); + /** + * If set to true, Envoy will :ref:`exclude ` new hosts + * when computing load balancing weights until they have been health checked for the first time. + * This will have no effect unless active health checking is also configured. + */ + 'ignore_new_hosts_until_first_hc'?: (boolean); + /** + * If set to `true`, the cluster manager will drain all existing + * connections to upstream hosts whenever hosts are added or removed from the cluster. + */ + 'close_connections_on_host_set_change'?: (boolean); + /** + * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) + */ + 'consistent_hashing_lb_config'?: (_envoy_config_cluster_v3_Cluster_CommonLbConfig_ConsistentHashingLbConfig | null); + 'locality_config_specifier'?: "zone_aware_lb_config"|"locality_weighted_lb_config"; +} + +/** + * Common configuration for all load balancer implementations. + * [#next-free-field: 8] + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig__Output { + /** + * Configures the :ref:`healthy panic threshold `. + * If not specified, the default is 50%. + * To disable panic mode, set to 0%. + * + * .. note:: + * The specified percent will be truncated to the nearest 1%. + */ + 'healthy_panic_threshold': (_envoy_type_v3_Percent__Output | null); + 'zone_aware_lb_config'?: (_envoy_config_cluster_v3_Cluster_CommonLbConfig_ZoneAwareLbConfig__Output | null); + 'locality_weighted_lb_config'?: (_envoy_config_cluster_v3_Cluster_CommonLbConfig_LocalityWeightedLbConfig__Output | null); + /** + * If set, all health check/weight/metadata updates that happen within this duration will be + * merged and delivered in one shot when the duration expires. The start of the duration is when + * the first update happens. This is useful for big clusters, with potentially noisy deploys + * that might trigger excessive CPU usage due to a constant stream of healthcheck state changes + * or metadata updates. The first set of updates to be seen apply immediately (e.g.: a new + * cluster). Please always keep in mind that the use of sandbox technologies may change this + * behavior. + * + * If this is not set, we default to a merge window of 1000ms. To disable it, set the merge + * window to 0. + * + * Note: merging does not apply to cluster membership changes (e.g.: adds/removes); this is + * because merging those updates isn't currently safe. See + * https://github.com/envoyproxy/envoy/pull/3941. + */ + 'update_merge_window': (_google_protobuf_Duration__Output | null); + /** + * If set to true, Envoy will :ref:`exclude ` new hosts + * when computing load balancing weights until they have been health checked for the first time. + * This will have no effect unless active health checking is also configured. + */ + 'ignore_new_hosts_until_first_hc': (boolean); + /** + * If set to `true`, the cluster manager will drain all existing + * connections to upstream hosts whenever hosts are added or removed from the cluster. + */ + 'close_connections_on_host_set_change': (boolean); + /** + * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) + */ + 'consistent_hashing_lb_config': (_envoy_config_cluster_v3_Cluster_CommonLbConfig_ConsistentHashingLbConfig__Output | null); + 'locality_config_specifier': "zone_aware_lb_config"|"locality_weighted_lb_config"; +} + +/** + * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig_ConsistentHashingLbConfig { + /** + * If set to `true`, the cluster will use hostname instead of the resolved + * address as the key to consistently hash to an upstream host. Only valid for StrictDNS clusters with hostnames which resolve to a single IP address. + */ + 'use_hostname_for_hashing'?: (boolean); + /** + * Configures percentage of average cluster load to bound per upstream host. For example, with a value of 150 + * no upstream host will get a load more than 1.5 times the average load of all the hosts in the cluster. + * If not specified, the load is not bounded for any upstream host. Typical value for this parameter is between 120 and 200. + * Minimum is 100. + * + * Applies to both Ring Hash and Maglev load balancers. + * + * This is implemented based on the method described in the paper https://arxiv.org/abs/1608.01350. For the specified + * `hash_balance_factor`, requests to any upstream host are capped at `hash_balance_factor/100` times the average number of requests + * across the cluster. When a request arrives for an upstream host that is currently serving at its max capacity, linear probing + * is used to identify an eligible host. Further, the linear probe is implemented using a random jump in hosts ring/table to identify + * the eligible host (this technique is as described in the paper https://arxiv.org/abs/1908.08762 - the random jump avoids the + * cascading overflow effect when choosing the next host in the ring/table). + * + * If weights are specified on the hosts, they are respected. + * + * This is an O(N) algorithm, unlike other load balancers. Using a lower `hash_balance_factor` results in more hosts + * being probed, so use a higher value if you require better performance. + */ + 'hash_balance_factor'?: (_google_protobuf_UInt32Value | null); +} + +/** + * Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig_ConsistentHashingLbConfig__Output { + /** + * If set to `true`, the cluster will use hostname instead of the resolved + * address as the key to consistently hash to an upstream host. Only valid for StrictDNS clusters with hostnames which resolve to a single IP address. + */ + 'use_hostname_for_hashing': (boolean); + /** + * Configures percentage of average cluster load to bound per upstream host. For example, with a value of 150 + * no upstream host will get a load more than 1.5 times the average load of all the hosts in the cluster. + * If not specified, the load is not bounded for any upstream host. Typical value for this parameter is between 120 and 200. + * Minimum is 100. + * + * Applies to both Ring Hash and Maglev load balancers. + * + * This is implemented based on the method described in the paper https://arxiv.org/abs/1608.01350. For the specified + * `hash_balance_factor`, requests to any upstream host are capped at `hash_balance_factor/100` times the average number of requests + * across the cluster. When a request arrives for an upstream host that is currently serving at its max capacity, linear probing + * is used to identify an eligible host. Further, the linear probe is implemented using a random jump in hosts ring/table to identify + * the eligible host (this technique is as described in the paper https://arxiv.org/abs/1908.08762 - the random jump avoids the + * cascading overflow effect when choosing the next host in the ring/table). + * + * If weights are specified on the hosts, they are respected. + * + * This is an O(N) algorithm, unlike other load balancers. Using a lower `hash_balance_factor` results in more hosts + * being probed, so use a higher value if you require better performance. + */ + 'hash_balance_factor': (_google_protobuf_UInt32Value__Output | null); +} + +/** + * Extended cluster type. + */ +export interface _envoy_config_cluster_v3_Cluster_CustomClusterType { + /** + * The type of the cluster to instantiate. The name must match a supported cluster type. + */ + 'name'?: (string); + /** + * Cluster specific configuration which depends on the cluster being instantiated. + * See the supported cluster for further documentation. + * [#extension-category: envoy.clusters] + */ + 'typed_config'?: (_google_protobuf_Any | null); +} + +/** + * Extended cluster type. + */ +export interface _envoy_config_cluster_v3_Cluster_CustomClusterType__Output { + /** + * The type of the cluster to instantiate. The name must match a supported cluster type. + */ + 'name': (string); + /** + * Cluster specific configuration which depends on the cluster being instantiated. + * See the supported cluster for further documentation. + * [#extension-category: envoy.clusters] + */ + 'typed_config': (_google_protobuf_Any__Output | null); +} + +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +/** + * Refer to :ref:`service discovery type ` + * for an explanation on each type. + */ +export enum _envoy_config_cluster_v3_Cluster_DiscoveryType { + /** + * Refer to the :ref:`static discovery type` + * for an explanation. + */ + STATIC = 0, + /** + * Refer to the :ref:`strict DNS discovery + * type` + * for an explanation. + */ + STRICT_DNS = 1, + /** + * Refer to the :ref:`logical DNS discovery + * type` + * for an explanation. + */ + LOGICAL_DNS = 2, + /** + * Refer to the :ref:`service discovery type` + * for an explanation. + */ + EDS = 3, + /** + * Refer to the :ref:`original destination discovery + * type` + * for an explanation. + */ + ORIGINAL_DST = 4, +} + +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +/** + * When V4_ONLY is selected, the DNS resolver will only perform a lookup for + * addresses in the IPv4 family. If V6_ONLY is selected, the DNS resolver will + * only perform a lookup for addresses in the IPv6 family. If AUTO is + * specified, the DNS resolver will first perform a lookup for addresses in + * the IPv6 family and fallback to a lookup for addresses in the IPv4 family. + * This is semantically equivalent to a non-existent V6_PREFERRED option. + * AUTO is a legacy name that is more opaque than + * necessary and will be deprecated in favor of V6_PREFERRED in a future major version of the API. + * If V4_PREFERRED is specified, the DNS resolver will first perform a lookup for addresses in the + * IPv4 family and fallback to a lookup for addresses in the IPv6 family. i.e., the callback + * target will only get v6 addresses if there were NO v4 addresses to return. + * For cluster types other than + * :ref:`STRICT_DNS` and + * :ref:`LOGICAL_DNS`, + * this setting is + * ignored. + * [#next-major-version: deprecate AUTO in favor of a V6_PREFERRED option.] + */ +export enum _envoy_config_cluster_v3_Cluster_DnsLookupFamily { + AUTO = 0, + V4_ONLY = 1, + V6_ONLY = 2, + V4_PREFERRED = 3, +} + +/** + * Only valid when discovery type is EDS. + */ +export interface _envoy_config_cluster_v3_Cluster_EdsClusterConfig { + /** + * Configuration for the source of EDS updates for this Cluster. + */ + 'eds_config'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * Optional alternative to cluster name to present to EDS. This does not + * have the same restrictions as cluster name, i.e. it may be arbitrary + * length. This may be a xdstp:// URL. + */ + 'service_name'?: (string); +} + +/** + * Only valid when discovery type is EDS. + */ +export interface _envoy_config_cluster_v3_Cluster_EdsClusterConfig__Output { + /** + * Configuration for the source of EDS updates for this Cluster. + */ + 'eds_config': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * Optional alternative to cluster name to present to EDS. This does not + * have the same restrictions as cluster name, i.e. it may be arbitrary + * length. This may be a xdstp:// URL. + */ + 'service_name': (string); +} + +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +/** + * The hash function used to hash hosts onto the ketama ring. + */ +export enum _envoy_config_cluster_v3_Cluster_RingHashLbConfig_HashFunction { + /** + * Use `xxHash `_, this is the default hash function. + */ + XX_HASH = 0, + /** + * Use `MurmurHash2 `_, this is compatible with + * std:hash in GNU libstdc++ 3.4.20 or above. This is typically the case when compiled + * on Linux and not macOS. + */ + MURMUR_HASH_2 = 1, +} + +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +/** + * Refer to :ref:`load balancer type ` architecture + * overview section for information on each type. + */ +export enum _envoy_config_cluster_v3_Cluster_LbPolicy { + /** + * Refer to the :ref:`round robin load balancing + * policy` + * for an explanation. + */ + ROUND_ROBIN = 0, + /** + * Refer to the :ref:`least request load balancing + * policy` + * for an explanation. + */ + LEAST_REQUEST = 1, + /** + * Refer to the :ref:`ring hash load balancing + * policy` + * for an explanation. + */ + RING_HASH = 2, + /** + * Refer to the :ref:`random load balancing + * policy` + * for an explanation. + */ + RANDOM = 3, + /** + * Refer to the :ref:`Maglev load balancing policy` + * for an explanation. + */ + MAGLEV = 5, + /** + * This load balancer type must be specified if the configured cluster provides a cluster + * specific load balancer. Consult the configured cluster's documentation for whether to set + * this option or not. + */ + CLUSTER_PROVIDED = 6, + /** + * Use the new :ref:`load_balancing_policy + * ` field to determine the LB policy. + * [#next-major-version: In the v3 API, we should consider deprecating the lb_policy field + * and instead using the new load_balancing_policy field as the one and only mechanism for + * configuring this.] + */ + LOAD_BALANCING_POLICY_CONFIG = 7, +} + +/** + * Optionally divide the endpoints in this cluster into subsets defined by + * endpoint metadata and selected by route and weighted cluster metadata. + * [#next-free-field: 8] + */ +export interface _envoy_config_cluster_v3_Cluster_LbSubsetConfig { + /** + * The behavior used when no endpoint subset matches the selected route's + * metadata. The value defaults to + * :ref:`NO_FALLBACK`. + */ + 'fallback_policy'?: (_envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy | keyof typeof _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy); + /** + * Specifies the default subset of endpoints used during fallback if + * fallback_policy is + * :ref:`DEFAULT_SUBSET`. + * Each field in default_subset is + * compared to the matching LbEndpoint.Metadata under the *envoy.lb* + * namespace. It is valid for no hosts to match, in which case the behavior + * is the same as a fallback_policy of + * :ref:`NO_FALLBACK`. + */ + 'default_subset'?: (_google_protobuf_Struct | null); + /** + * For each entry, LbEndpoint.Metadata's + * *envoy.lb* namespace is traversed and a subset is created for each unique + * combination of key and value. For example: + * + * .. code-block:: json + * + * { "subset_selectors": [ + * { "keys": [ "version" ] }, + * { "keys": [ "stage", "hardware_type" ] } + * ]} + * + * A subset is matched when the metadata from the selected route and + * weighted cluster contains the same keys and values as the subset's + * metadata. The same host may appear in multiple subsets. + */ + 'subset_selectors'?: (_envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector)[]; + /** + * If true, routing to subsets will take into account the localities and locality weights of the + * endpoints when making the routing decision. + * + * There are some potential pitfalls associated with enabling this feature, as the resulting + * traffic split after applying both a subset match and locality weights might be undesirable. + * + * Consider for example a situation in which you have 50/50 split across two localities X/Y + * which have 100 hosts each without subsetting. If the subset LB results in X having only 1 + * host selected but Y having 100, then a lot more load is being dumped on the single host in X + * than originally anticipated in the load balancing assignment delivered via EDS. + */ + 'locality_weight_aware'?: (boolean); + /** + * When used with locality_weight_aware, scales the weight of each locality by the ratio + * of hosts in the subset vs hosts in the original subset. This aims to even out the load + * going to an individual locality if said locality is disproportionately affected by the + * subset predicate. + */ + 'scale_locality_weight'?: (boolean); + /** + * If true, when a fallback policy is configured and its corresponding subset fails to find + * a host this will cause any host to be selected instead. + * + * This is useful when using the default subset as the fallback policy, given the default + * subset might become empty. With this option enabled, if that happens the LB will attempt + * to select a host from the entire cluster. + */ + 'panic_mode_any'?: (boolean); + /** + * If true, metadata specified for a metadata key will be matched against the corresponding + * endpoint metadata if the endpoint metadata matches the value exactly OR it is a list value + * and any of the elements in the list matches the criteria. + */ + 'list_as_any'?: (boolean); +} + +/** + * Optionally divide the endpoints in this cluster into subsets defined by + * endpoint metadata and selected by route and weighted cluster metadata. + * [#next-free-field: 8] + */ +export interface _envoy_config_cluster_v3_Cluster_LbSubsetConfig__Output { + /** + * The behavior used when no endpoint subset matches the selected route's + * metadata. The value defaults to + * :ref:`NO_FALLBACK`. + */ + 'fallback_policy': (keyof typeof _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy); + /** + * Specifies the default subset of endpoints used during fallback if + * fallback_policy is + * :ref:`DEFAULT_SUBSET`. + * Each field in default_subset is + * compared to the matching LbEndpoint.Metadata under the *envoy.lb* + * namespace. It is valid for no hosts to match, in which case the behavior + * is the same as a fallback_policy of + * :ref:`NO_FALLBACK`. + */ + 'default_subset': (_google_protobuf_Struct__Output | null); + /** + * For each entry, LbEndpoint.Metadata's + * *envoy.lb* namespace is traversed and a subset is created for each unique + * combination of key and value. For example: + * + * .. code-block:: json + * + * { "subset_selectors": [ + * { "keys": [ "version" ] }, + * { "keys": [ "stage", "hardware_type" ] } + * ]} + * + * A subset is matched when the metadata from the selected route and + * weighted cluster contains the same keys and values as the subset's + * metadata. The same host may appear in multiple subsets. + */ + 'subset_selectors': (_envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector__Output)[]; + /** + * If true, routing to subsets will take into account the localities and locality weights of the + * endpoints when making the routing decision. + * + * There are some potential pitfalls associated with enabling this feature, as the resulting + * traffic split after applying both a subset match and locality weights might be undesirable. + * + * Consider for example a situation in which you have 50/50 split across two localities X/Y + * which have 100 hosts each without subsetting. If the subset LB results in X having only 1 + * host selected but Y having 100, then a lot more load is being dumped on the single host in X + * than originally anticipated in the load balancing assignment delivered via EDS. + */ + 'locality_weight_aware': (boolean); + /** + * When used with locality_weight_aware, scales the weight of each locality by the ratio + * of hosts in the subset vs hosts in the original subset. This aims to even out the load + * going to an individual locality if said locality is disproportionately affected by the + * subset predicate. + */ + 'scale_locality_weight': (boolean); + /** + * If true, when a fallback policy is configured and its corresponding subset fails to find + * a host this will cause any host to be selected instead. + * + * This is useful when using the default subset as the fallback policy, given the default + * subset might become empty. With this option enabled, if that happens the LB will attempt + * to select a host from the entire cluster. + */ + 'panic_mode_any': (boolean); + /** + * If true, metadata specified for a metadata key will be matched against the corresponding + * endpoint metadata if the endpoint metadata matches the value exactly OR it is a list value + * and any of the elements in the list matches the criteria. + */ + 'list_as_any': (boolean); +} + +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +/** + * If NO_FALLBACK is selected, a result + * equivalent to no healthy hosts is reported. If ANY_ENDPOINT is selected, + * any cluster endpoint may be returned (subject to policy, health checks, + * etc). If DEFAULT_SUBSET is selected, load balancing is performed over the + * endpoints matching the values from the default_subset field. + */ +export enum _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetFallbackPolicy { + NO_FALLBACK = 0, + ANY_ENDPOINT = 1, + DEFAULT_SUBSET = 2, +} + +/** + * Specifications for subsets. + */ +export interface _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector { + /** + * List of keys to match with the weighted cluster metadata. + */ + 'keys'?: (string)[]; + /** + * Selects a mode of operation in which each subset has only one host. This mode uses the same rules for + * choosing a host, but updating hosts is faster, especially for large numbers of hosts. + * + * If a match is found to a host, that host will be used regardless of priority levels, unless the host is unhealthy. + * + * Currently, this mode is only supported if `subset_selectors` has only one entry, and `keys` contains + * only one entry. + * + * When this mode is enabled, configurations that contain more than one host with the same metadata value for the single key in `keys` + * will use only one of the hosts with the given key; no requests will be routed to the others. The cluster gauge + * :ref:`lb_subsets_single_host_per_subset_duplicate` indicates how many duplicates are + * present in the current configuration. + */ + 'single_host_per_subset'?: (boolean); + /** + * The behavior used when no endpoint subset matches the selected route's + * metadata. + */ + 'fallback_policy'?: (_envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy | keyof typeof _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy); + /** + * Subset of + * :ref:`keys` used by + * :ref:`KEYS_SUBSET` + * fallback policy. + * It has to be a non empty list if KEYS_SUBSET fallback policy is selected. + * For any other fallback policy the parameter is not used and should not be set. + * Only values also present in + * :ref:`keys` are allowed, but + * `fallback_keys_subset` cannot be equal to `keys`. + */ + 'fallback_keys_subset'?: (string)[]; +} + +/** + * Specifications for subsets. + */ +export interface _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector__Output { + /** + * List of keys to match with the weighted cluster metadata. + */ + 'keys': (string)[]; + /** + * Selects a mode of operation in which each subset has only one host. This mode uses the same rules for + * choosing a host, but updating hosts is faster, especially for large numbers of hosts. + * + * If a match is found to a host, that host will be used regardless of priority levels, unless the host is unhealthy. + * + * Currently, this mode is only supported if `subset_selectors` has only one entry, and `keys` contains + * only one entry. + * + * When this mode is enabled, configurations that contain more than one host with the same metadata value for the single key in `keys` + * will use only one of the hosts with the given key; no requests will be routed to the others. The cluster gauge + * :ref:`lb_subsets_single_host_per_subset_duplicate` indicates how many duplicates are + * present in the current configuration. + */ + 'single_host_per_subset': (boolean); + /** + * The behavior used when no endpoint subset matches the selected route's + * metadata. + */ + 'fallback_policy': (keyof typeof _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy); + /** + * Subset of + * :ref:`keys` used by + * :ref:`KEYS_SUBSET` + * fallback policy. + * It has to be a non empty list if KEYS_SUBSET fallback policy is selected. + * For any other fallback policy the parameter is not used and should not be set. + * Only values also present in + * :ref:`keys` are allowed, but + * `fallback_keys_subset` cannot be equal to `keys`. + */ + 'fallback_keys_subset': (string)[]; +} + +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +/** + * Allows to override top level fallback policy per selector. + */ +export enum _envoy_config_cluster_v3_Cluster_LbSubsetConfig_LbSubsetSelector_LbSubsetSelectorFallbackPolicy { + /** + * If NOT_DEFINED top level config fallback policy is used instead. + */ + NOT_DEFINED = 0, + /** + * If NO_FALLBACK is selected, a result equivalent to no healthy hosts is reported. + */ + NO_FALLBACK = 1, + /** + * If ANY_ENDPOINT is selected, any cluster endpoint may be returned + * (subject to policy, health checks, etc). + */ + ANY_ENDPOINT = 2, + /** + * If DEFAULT_SUBSET is selected, load balancing is performed over the + * endpoints matching the values from the default_subset field. + */ + DEFAULT_SUBSET = 3, + /** + * If KEYS_SUBSET is selected, subset selector matching is performed again with metadata + * keys reduced to + * :ref:`fallback_keys_subset`. + * It allows for a fallback to a different, less specific selector if some of the keys of + * the selector are considered optional. + */ + KEYS_SUBSET = 4, +} + +/** + * Specific configuration for the LeastRequest load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_LeastRequestLbConfig { + /** + * The number of random healthy hosts from which the host with the fewest active requests will + * be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. + */ + 'choice_count'?: (_google_protobuf_UInt32Value | null); + /** + * The following formula is used to calculate the dynamic weights when hosts have different load + * balancing weights: + * + * `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + * + * The larger the active request bias is, the more aggressively active requests will lower the + * effective weight when all host weights are not equal. + * + * `active_request_bias` must be greater than or equal to 0.0. + * + * When `active_request_bias == 0.0` the Least Request Load Balancer doesn't consider the number + * of active requests at the time it picks a host and behaves like the Round Robin Load + * Balancer. + * + * When `active_request_bias > 0.0` the Least Request Load Balancer scales the load balancing + * weight by the number of active requests at the time it does a pick. + * + * The value is cached for performance reasons and refreshed whenever one of the Load Balancer's + * host sets changes, e.g., whenever there is a host membership update or a host load balancing + * weight change. + * + * .. note:: + * This setting only takes effect if all host weights are not equal. + */ + 'active_request_bias'?: (_envoy_config_core_v3_RuntimeDouble | null); + /** + * Configuration for slow start mode. + * If this configuration is not set, slow start will not be not enabled. + */ + 'slow_start_config'?: (_envoy_config_cluster_v3_Cluster_SlowStartConfig | null); +} + +/** + * Specific configuration for the LeastRequest load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_LeastRequestLbConfig__Output { + /** + * The number of random healthy hosts from which the host with the fewest active requests will + * be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. + */ + 'choice_count': (_google_protobuf_UInt32Value__Output | null); + /** + * The following formula is used to calculate the dynamic weights when hosts have different load + * balancing weights: + * + * `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + * + * The larger the active request bias is, the more aggressively active requests will lower the + * effective weight when all host weights are not equal. + * + * `active_request_bias` must be greater than or equal to 0.0. + * + * When `active_request_bias == 0.0` the Least Request Load Balancer doesn't consider the number + * of active requests at the time it picks a host and behaves like the Round Robin Load + * Balancer. + * + * When `active_request_bias > 0.0` the Least Request Load Balancer scales the load balancing + * weight by the number of active requests at the time it does a pick. + * + * The value is cached for performance reasons and refreshed whenever one of the Load Balancer's + * host sets changes, e.g., whenever there is a host membership update or a host load balancing + * weight change. + * + * .. note:: + * This setting only takes effect if all host weights are not equal. + */ + 'active_request_bias': (_envoy_config_core_v3_RuntimeDouble__Output | null); + /** + * Configuration for slow start mode. + * If this configuration is not set, slow start will not be not enabled. + */ + 'slow_start_config': (_envoy_config_cluster_v3_Cluster_SlowStartConfig__Output | null); +} + +/** + * Configuration for :ref:`locality weighted load balancing + * ` + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig_LocalityWeightedLbConfig { +} + +/** + * Configuration for :ref:`locality weighted load balancing + * ` + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig_LocalityWeightedLbConfig__Output { +} + +/** + * Specific configuration for the :ref:`Maglev` + * load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_MaglevLbConfig { + /** + * The table size for Maglev hashing. The Maglev aims for ‘minimal disruption’ rather than an absolute guarantee. + * Minimal disruption means that when the set of upstreams changes, a connection will likely be sent to the same + * upstream as it was before. Increasing the table size reduces the amount of disruption. + * The table size must be prime number limited to 5000011. If it is not specified, the default is 65537. + */ + 'table_size'?: (_google_protobuf_UInt64Value | null); +} + +/** + * Specific configuration for the :ref:`Maglev` + * load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_MaglevLbConfig__Output { + /** + * The table size for Maglev hashing. The Maglev aims for ‘minimal disruption’ rather than an absolute guarantee. + * Minimal disruption means that when the set of upstreams changes, a connection will likely be sent to the same + * upstream as it was before. Increasing the table size reduces the amount of disruption. + * The table size must be prime number limited to 5000011. If it is not specified, the default is 65537. + */ + 'table_size': (_google_protobuf_UInt64Value__Output | null); +} + +/** + * Specific configuration for the + * :ref:`Original Destination ` + * load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_OriginalDstLbConfig { + /** + * When true, :ref:`x-envoy-original-dst-host + * ` can be used to override destination + * address. + * + * .. attention:: + * + * This header isn't sanitized by default, so enabling this feature allows HTTP clients to + * route traffic to arbitrary hosts and/or ports, which may have serious security + * consequences. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. + */ + 'use_http_header'?: (boolean); +} + +/** + * Specific configuration for the + * :ref:`Original Destination ` + * load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_OriginalDstLbConfig__Output { + /** + * When true, :ref:`x-envoy-original-dst-host + * ` can be used to override destination + * address. + * + * .. attention:: + * + * This header isn't sanitized by default, so enabling this feature allows HTTP clients to + * route traffic to arbitrary hosts and/or ports, which may have serious security + * consequences. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. + */ + 'use_http_header': (boolean); +} + +export interface _envoy_config_cluster_v3_Cluster_PreconnectPolicy { + /** + * Indicates how many streams (rounded up) can be anticipated per-upstream for each + * incoming stream. This is useful for high-QPS or latency-sensitive services. Preconnecting + * will only be done if the upstream is healthy and the cluster has traffic. + * + * For example if this is 2, for an incoming HTTP/1.1 stream, 2 connections will be + * established, one for the new incoming stream, and one for a presumed follow-up stream. For + * HTTP/2, only one connection would be established by default as one connection can + * serve both the original and presumed follow-up stream. + * + * In steady state for non-multiplexed connections a value of 1.5 would mean if there were 100 + * active streams, there would be 100 connections in use, and 50 connections preconnected. + * This might be a useful value for something like short lived single-use connections, + * for example proxying HTTP/1.1 if keep-alive were false and each stream resulted in connection + * termination. It would likely be overkill for long lived connections, such as TCP proxying SMTP + * or regular HTTP/1.1 with keep-alive. For long lived traffic, a value of 1.05 would be more + * reasonable, where for every 100 connections, 5 preconnected connections would be in the queue + * in case of unexpected disconnects where the connection could not be reused. + * + * If this value is not set, or set explicitly to one, Envoy will fetch as many connections + * as needed to serve streams in flight. This means in steady state if a connection is torn down, + * a subsequent streams will pay an upstream-rtt latency penalty waiting for a new connection. + * + * This is limited somewhat arbitrarily to 3 because preconnecting too aggressively can + * harm latency more than the preconnecting helps. + */ + 'per_upstream_preconnect_ratio'?: (_google_protobuf_DoubleValue | null); + /** + * Indicates how many many streams (rounded up) can be anticipated across a cluster for each + * stream, useful for low QPS services. This is currently supported for a subset of + * deterministic non-hash-based load-balancing algorithms (weighted round robin, random). + * Unlike *per_upstream_preconnect_ratio* this preconnects across the upstream instances in a + * cluster, doing best effort predictions of what upstream would be picked next and + * pre-establishing a connection. + * + * Preconnecting will be limited to one preconnect per configured upstream in the cluster and will + * only be done if there are healthy upstreams and the cluster has traffic. + * + * For example if preconnecting is set to 2 for a round robin HTTP/2 cluster, on the first + * incoming stream, 2 connections will be preconnected - one to the first upstream for this + * cluster, one to the second on the assumption there will be a follow-up stream. + * + * If this value is not set, or set explicitly to one, Envoy will fetch as many connections + * as needed to serve streams in flight, so during warm up and in steady state if a connection + * is closed (and per_upstream_preconnect_ratio is not set), there will be a latency hit for + * connection establishment. + * + * If both this and preconnect_ratio are set, Envoy will make sure both predicted needs are met, + * basically preconnecting max(predictive-preconnect, per-upstream-preconnect), for each + * upstream. + */ + 'predictive_preconnect_ratio'?: (_google_protobuf_DoubleValue | null); +} + +export interface _envoy_config_cluster_v3_Cluster_PreconnectPolicy__Output { + /** + * Indicates how many streams (rounded up) can be anticipated per-upstream for each + * incoming stream. This is useful for high-QPS or latency-sensitive services. Preconnecting + * will only be done if the upstream is healthy and the cluster has traffic. + * + * For example if this is 2, for an incoming HTTP/1.1 stream, 2 connections will be + * established, one for the new incoming stream, and one for a presumed follow-up stream. For + * HTTP/2, only one connection would be established by default as one connection can + * serve both the original and presumed follow-up stream. + * + * In steady state for non-multiplexed connections a value of 1.5 would mean if there were 100 + * active streams, there would be 100 connections in use, and 50 connections preconnected. + * This might be a useful value for something like short lived single-use connections, + * for example proxying HTTP/1.1 if keep-alive were false and each stream resulted in connection + * termination. It would likely be overkill for long lived connections, such as TCP proxying SMTP + * or regular HTTP/1.1 with keep-alive. For long lived traffic, a value of 1.05 would be more + * reasonable, where for every 100 connections, 5 preconnected connections would be in the queue + * in case of unexpected disconnects where the connection could not be reused. + * + * If this value is not set, or set explicitly to one, Envoy will fetch as many connections + * as needed to serve streams in flight. This means in steady state if a connection is torn down, + * a subsequent streams will pay an upstream-rtt latency penalty waiting for a new connection. + * + * This is limited somewhat arbitrarily to 3 because preconnecting too aggressively can + * harm latency more than the preconnecting helps. + */ + 'per_upstream_preconnect_ratio': (_google_protobuf_DoubleValue__Output | null); + /** + * Indicates how many many streams (rounded up) can be anticipated across a cluster for each + * stream, useful for low QPS services. This is currently supported for a subset of + * deterministic non-hash-based load-balancing algorithms (weighted round robin, random). + * Unlike *per_upstream_preconnect_ratio* this preconnects across the upstream instances in a + * cluster, doing best effort predictions of what upstream would be picked next and + * pre-establishing a connection. + * + * Preconnecting will be limited to one preconnect per configured upstream in the cluster and will + * only be done if there are healthy upstreams and the cluster has traffic. + * + * For example if preconnecting is set to 2 for a round robin HTTP/2 cluster, on the first + * incoming stream, 2 connections will be preconnected - one to the first upstream for this + * cluster, one to the second on the assumption there will be a follow-up stream. + * + * If this value is not set, or set explicitly to one, Envoy will fetch as many connections + * as needed to serve streams in flight, so during warm up and in steady state if a connection + * is closed (and per_upstream_preconnect_ratio is not set), there will be a latency hit for + * connection establishment. + * + * If both this and preconnect_ratio are set, Envoy will make sure both predicted needs are met, + * basically preconnecting max(predictive-preconnect, per-upstream-preconnect), for each + * upstream. + */ + 'predictive_preconnect_ratio': (_google_protobuf_DoubleValue__Output | null); +} + +export interface _envoy_config_cluster_v3_Cluster_RefreshRate { + /** + * Specifies the base interval between refreshes. This parameter is required and must be greater + * than zero and less than + * :ref:`max_interval `. + */ + 'base_interval'?: (_google_protobuf_Duration | null); + /** + * Specifies the maximum interval between refreshes. This parameter is optional, but must be + * greater than or equal to the + * :ref:`base_interval ` if set. The default + * is 10 times the :ref:`base_interval `. + */ + 'max_interval'?: (_google_protobuf_Duration | null); +} + +export interface _envoy_config_cluster_v3_Cluster_RefreshRate__Output { + /** + * Specifies the base interval between refreshes. This parameter is required and must be greater + * than zero and less than + * :ref:`max_interval `. + */ + 'base_interval': (_google_protobuf_Duration__Output | null); + /** + * Specifies the maximum interval between refreshes. This parameter is optional, but must be + * greater than or equal to the + * :ref:`base_interval ` if set. The default + * is 10 times the :ref:`base_interval `. + */ + 'max_interval': (_google_protobuf_Duration__Output | null); +} + +/** + * Specific configuration for the :ref:`RingHash` + * load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_RingHashLbConfig { + /** + * Minimum hash ring size. The larger the ring is (that is, the more hashes there are for each + * provided host) the better the request distribution will reflect the desired weights. Defaults + * to 1024 entries, and limited to 8M entries. See also + * :ref:`maximum_ring_size`. + */ + 'minimum_ring_size'?: (_google_protobuf_UInt64Value | null); + /** + * The hash function used to hash hosts onto the ketama ring. The value defaults to + * :ref:`XX_HASH`. + */ + 'hash_function'?: (_envoy_config_cluster_v3_Cluster_RingHashLbConfig_HashFunction | keyof typeof _envoy_config_cluster_v3_Cluster_RingHashLbConfig_HashFunction); + /** + * Maximum hash ring size. Defaults to 8M entries, and limited to 8M entries, but can be lowered + * to further constrain resource use. See also + * :ref:`minimum_ring_size`. + */ + 'maximum_ring_size'?: (_google_protobuf_UInt64Value | null); +} + +/** + * Specific configuration for the :ref:`RingHash` + * load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_RingHashLbConfig__Output { + /** + * Minimum hash ring size. The larger the ring is (that is, the more hashes there are for each + * provided host) the better the request distribution will reflect the desired weights. Defaults + * to 1024 entries, and limited to 8M entries. See also + * :ref:`maximum_ring_size`. + */ + 'minimum_ring_size': (_google_protobuf_UInt64Value__Output | null); + /** + * The hash function used to hash hosts onto the ketama ring. The value defaults to + * :ref:`XX_HASH`. + */ + 'hash_function': (keyof typeof _envoy_config_cluster_v3_Cluster_RingHashLbConfig_HashFunction); + /** + * Maximum hash ring size. Defaults to 8M entries, and limited to 8M entries, but can be lowered + * to further constrain resource use. See also + * :ref:`minimum_ring_size`. + */ + 'maximum_ring_size': (_google_protobuf_UInt64Value__Output | null); +} + +/** + * Specific configuration for the RoundRobin load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_RoundRobinLbConfig { + /** + * Configuration for slow start mode. + * If this configuration is not set, slow start will not be not enabled. + */ + 'slow_start_config'?: (_envoy_config_cluster_v3_Cluster_SlowStartConfig | null); +} + +/** + * Specific configuration for the RoundRobin load balancing policy. + */ +export interface _envoy_config_cluster_v3_Cluster_RoundRobinLbConfig__Output { + /** + * Configuration for slow start mode. + * If this configuration is not set, slow start will not be not enabled. + */ + 'slow_start_config': (_envoy_config_cluster_v3_Cluster_SlowStartConfig__Output | null); +} + +/** + * Configuration for :ref:`slow start mode `. + */ +export interface _envoy_config_cluster_v3_Cluster_SlowStartConfig { + /** + * Represents the size of slow start window. + * If set, the newly created host remains in slow start mode starting from its creation time + * for the duration of slow start window. + */ + 'slow_start_window'?: (_google_protobuf_Duration | null); + /** + * This parameter controls the speed of traffic increase over the slow start window. Defaults to 1.0, + * so that endpoint would get linearly increasing amount of traffic. + * When increasing the value for this parameter, the speed of traffic ramp-up increases non-linearly. + * The value of aggression parameter should be greater than 0.0. + * By tuning the parameter, is possible to achieve polynomial or exponential shape of ramp-up curve. + * + * During slow start window, effective weight of an endpoint would be scaled with time factor and aggression: + * `new_weight = weight * time_factor ^ (1 / aggression)`, + * where `time_factor=(time_since_start_seconds / slow_start_time_seconds)`. + * + * As time progresses, more and more traffic would be sent to endpoint, which is in slow start window. + * Once host exits slow start, time_factor and aggression no longer affect its weight. + */ + 'aggression'?: (_envoy_config_core_v3_RuntimeDouble | null); +} + +/** + * Configuration for :ref:`slow start mode `. + */ +export interface _envoy_config_cluster_v3_Cluster_SlowStartConfig__Output { + /** + * Represents the size of slow start window. + * If set, the newly created host remains in slow start mode starting from its creation time + * for the duration of slow start window. + */ + 'slow_start_window': (_google_protobuf_Duration__Output | null); + /** + * This parameter controls the speed of traffic increase over the slow start window. Defaults to 1.0, + * so that endpoint would get linearly increasing amount of traffic. + * When increasing the value for this parameter, the speed of traffic ramp-up increases non-linearly. + * The value of aggression parameter should be greater than 0.0. + * By tuning the parameter, is possible to achieve polynomial or exponential shape of ramp-up curve. + * + * During slow start window, effective weight of an endpoint would be scaled with time factor and aggression: + * `new_weight = weight * time_factor ^ (1 / aggression)`, + * where `time_factor=(time_since_start_seconds / slow_start_time_seconds)`. + * + * As time progresses, more and more traffic would be sent to endpoint, which is in slow start window. + * Once host exits slow start, time_factor and aggression no longer affect its weight. + */ + 'aggression': (_envoy_config_core_v3_RuntimeDouble__Output | null); +} + +/** + * TransportSocketMatch specifies what transport socket config will be used + * when the match conditions are satisfied. + */ +export interface _envoy_config_cluster_v3_Cluster_TransportSocketMatch { + /** + * The name of the match, used in stats generation. + */ + 'name'?: (string); + /** + * Optional endpoint metadata match criteria. + * The connection to the endpoint with metadata matching what is set in this field + * will use the transport socket configuration specified here. + * The endpoint's metadata entry in *envoy.transport_socket_match* is used to match + * against the values specified in this field. + */ + 'match'?: (_google_protobuf_Struct | null); + /** + * The configuration of the transport socket. + * [#extension-category: envoy.transport_sockets.upstream] + */ + 'transport_socket'?: (_envoy_config_core_v3_TransportSocket | null); +} + +/** + * TransportSocketMatch specifies what transport socket config will be used + * when the match conditions are satisfied. + */ +export interface _envoy_config_cluster_v3_Cluster_TransportSocketMatch__Output { + /** + * The name of the match, used in stats generation. + */ + 'name': (string); + /** + * Optional endpoint metadata match criteria. + * The connection to the endpoint with metadata matching what is set in this field + * will use the transport socket configuration specified here. + * The endpoint's metadata entry in *envoy.transport_socket_match* is used to match + * against the values specified in this field. + */ + 'match': (_google_protobuf_Struct__Output | null); + /** + * The configuration of the transport socket. + * [#extension-category: envoy.transport_sockets.upstream] + */ + 'transport_socket': (_envoy_config_core_v3_TransportSocket__Output | null); +} + +/** + * Configuration for :ref:`zone aware routing + * `. + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig_ZoneAwareLbConfig { + /** + * Configures percentage of requests that will be considered for zone aware routing + * if zone aware routing is configured. If not specified, the default is 100%. + * * :ref:`runtime values `. + * * :ref:`Zone aware routing support `. + */ + 'routing_enabled'?: (_envoy_type_v3_Percent | null); + /** + * Configures minimum upstream cluster size required for zone aware routing + * If upstream cluster size is less than specified, zone aware routing is not performed + * even if zone aware routing is configured. If not specified, the default is 6. + * * :ref:`runtime values `. + * * :ref:`Zone aware routing support `. + */ + 'min_cluster_size'?: (_google_protobuf_UInt64Value | null); + /** + * If set to true, Envoy will not consider any hosts when the cluster is in :ref:`panic + * mode`. Instead, the cluster will fail all + * requests as if all hosts are unhealthy. This can help avoid potentially overwhelming a + * failing service. + */ + 'fail_traffic_on_panic'?: (boolean); +} + +/** + * Configuration for :ref:`zone aware routing + * `. + */ +export interface _envoy_config_cluster_v3_Cluster_CommonLbConfig_ZoneAwareLbConfig__Output { + /** + * Configures percentage of requests that will be considered for zone aware routing + * if zone aware routing is configured. If not specified, the default is 100%. + * * :ref:`runtime values `. + * * :ref:`Zone aware routing support `. + */ + 'routing_enabled': (_envoy_type_v3_Percent__Output | null); + /** + * Configures minimum upstream cluster size required for zone aware routing + * If upstream cluster size is less than specified, zone aware routing is not performed + * even if zone aware routing is configured. If not specified, the default is 6. + * * :ref:`runtime values `. + * * :ref:`Zone aware routing support `. + */ + 'min_cluster_size': (_google_protobuf_UInt64Value__Output | null); + /** + * If set to true, Envoy will not consider any hosts when the cluster is in :ref:`panic + * mode`. Instead, the cluster will fail all + * requests as if all hosts are unhealthy. This can help avoid potentially overwhelming a + * failing service. + */ + 'fail_traffic_on_panic': (boolean); +} + +/** + * Configuration for a single upstream cluster. + * [#next-free-field: 57] + */ +export interface Cluster { + /** + * Supplies the name of the cluster which must be unique across all clusters. + * The cluster name is used when emitting + * :ref:`statistics ` if :ref:`alt_stat_name + * ` is not provided. + * Any ``:`` in the cluster name will be converted to ``_`` when emitting statistics. + */ + 'name'?: (string); + /** + * The :ref:`service discovery type ` + * to use for resolving the cluster. + */ + 'type'?: (_envoy_config_cluster_v3_Cluster_DiscoveryType | keyof typeof _envoy_config_cluster_v3_Cluster_DiscoveryType); + /** + * Configuration to use for EDS updates for the Cluster. + */ + 'eds_cluster_config'?: (_envoy_config_cluster_v3_Cluster_EdsClusterConfig | null); + /** + * The timeout for new network connections to hosts in the cluster. + * If not set, a default value of 5s will be used. + */ + 'connect_timeout'?: (_google_protobuf_Duration | null); + /** + * Soft limit on size of the cluster’s connections read and write buffers. If + * unspecified, an implementation defined default is applied (1MiB). + */ + 'per_connection_buffer_limit_bytes'?: (_google_protobuf_UInt32Value | null); + /** + * The :ref:`load balancer type ` to use + * when picking a host in the cluster. + */ + 'lb_policy'?: (_envoy_config_cluster_v3_Cluster_LbPolicy | keyof typeof _envoy_config_cluster_v3_Cluster_LbPolicy); + /** + * Optional :ref:`active health checking ` + * configuration for the cluster. If no + * configuration is specified no health checking will be done and all cluster + * members will be considered healthy at all times. + */ + 'health_checks'?: (_envoy_config_core_v3_HealthCheck)[]; + /** + * Optional maximum requests for a single upstream connection. This parameter + * is respected by both the HTTP/1.1 and HTTP/2 connection pool + * implementations. If not specified, there is no limit. Setting this + * parameter to 1 will effectively disable keep alive. + * + * .. attention:: + * This field has been deprecated in favor of the :ref:`max_requests_per_connection ` field. + */ + 'max_requests_per_connection'?: (_google_protobuf_UInt32Value | null); + /** + * Optional :ref:`circuit breaking ` for the cluster. + */ + 'circuit_breakers'?: (_envoy_config_cluster_v3_CircuitBreakers | null); + /** + * Additional options when handling HTTP1 requests. + * This has been deprecated in favor of http_protocol_options fields in the + * :ref:`http_protocol_options ` message. + * http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'http_protocol_options'?: (_envoy_config_core_v3_Http1ProtocolOptions | null); + /** + * Even if default HTTP2 protocol options are desired, this field must be + * set so that Envoy will assume that the upstream supports HTTP/2 when + * making new HTTP connection pool connections. Currently, Envoy only + * supports prior knowledge for upstream connections. Even if TLS is used + * with ALPN, `http2_protocol_options` must be specified. As an aside this allows HTTP/2 + * connections to happen over plain text. + * This has been deprecated in favor of http2_protocol_options fields in the + * :ref:`http_protocol_options ` + * message. http2_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'http2_protocol_options'?: (_envoy_config_core_v3_Http2ProtocolOptions | null); + /** + * If the DNS refresh rate is specified and the cluster type is either + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`, + * this value is used as the cluster’s DNS refresh + * rate. The value configured must be at least 1ms. If this setting is not specified, the + * value defaults to 5000ms. For cluster types other than + * :ref:`STRICT_DNS` + * and :ref:`LOGICAL_DNS` + * this setting is ignored. + */ + 'dns_refresh_rate'?: (_google_protobuf_Duration | null); + /** + * The DNS IP address resolution policy. If this setting is not specified, the + * value defaults to + * :ref:`AUTO`. + */ + 'dns_lookup_family'?: (_envoy_config_cluster_v3_Cluster_DnsLookupFamily | keyof typeof _envoy_config_cluster_v3_Cluster_DnsLookupFamily); + /** + * If DNS resolvers are specified and the cluster type is either + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`, + * this value is used to specify the cluster’s dns resolvers. + * If this setting is not specified, the value defaults to the default + * resolver, which uses /etc/resolv.conf for configuration. For cluster types + * other than + * :ref:`STRICT_DNS` + * and :ref:`LOGICAL_DNS` + * this setting is ignored. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple's API only allows overriding DNS resolvers via system settings. + * This field is deprecated in favor of *dns_resolution_config* + * which aggregates all of the DNS resolver configuration in a single message. + */ + 'dns_resolvers'?: (_envoy_config_core_v3_Address)[]; + /** + * If specified, outlier detection will be enabled for this upstream cluster. + * Each of the configuration values can be overridden via + * :ref:`runtime values `. + */ + 'outlier_detection'?: (_envoy_config_cluster_v3_OutlierDetection | null); + /** + * The interval for removing stale hosts from a cluster type + * :ref:`ORIGINAL_DST`. + * Hosts are considered stale if they have not been used + * as upstream destinations during this interval. New hosts are added + * to original destination clusters on demand as new connections are + * redirected to Envoy, causing the number of hosts in the cluster to + * grow over time. Hosts that are not stale (they are actively used as + * destinations) are kept in the cluster, which allows connections to + * them remain open, saving the latency that would otherwise be spent + * on opening new connections. If this setting is not specified, the + * value defaults to 5000ms. For cluster types other than + * :ref:`ORIGINAL_DST` + * this setting is ignored. + */ + 'cleanup_interval'?: (_google_protobuf_Duration | null); + /** + * Optional configuration used to bind newly established upstream connections. + * This overrides any bind_config specified in the bootstrap proto. + * If the address and port are empty, no bind will be performed. + */ + 'upstream_bind_config'?: (_envoy_config_core_v3_BindConfig | null); + /** + * Configuration for load balancing subsetting. + */ + 'lb_subset_config'?: (_envoy_config_cluster_v3_Cluster_LbSubsetConfig | null); + /** + * Optional configuration for the Ring Hash load balancing policy. + */ + 'ring_hash_lb_config'?: (_envoy_config_cluster_v3_Cluster_RingHashLbConfig | null); + /** + * Optional custom transport socket implementation to use for upstream connections. + * To setup TLS, set a transport socket with name `envoy.transport_sockets.tls` and + * :ref:`UpstreamTlsContexts ` in the `typed_config`. + * If no transport socket configuration is specified, new connections + * will be set up with plaintext. + */ + 'transport_socket'?: (_envoy_config_core_v3_TransportSocket | null); + /** + * The Metadata field can be used to provide additional information about the + * cluster. It can be used for stats, logging, and varying filter behavior. + * Fields should use reverse DNS notation to denote which entity within Envoy + * will need the information. For instance, if the metadata is intended for + * the Router filter, the filter name should be specified as *envoy.filters.http.router*. + */ + 'metadata'?: (_envoy_config_core_v3_Metadata | null); + /** + * Determines how Envoy selects the protocol used to speak to upstream hosts. + * This has been deprecated in favor of setting explicit protocol selection + * in the :ref:`http_protocol_options + * ` message. + * http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + */ + 'protocol_selection'?: (_envoy_config_cluster_v3_Cluster_ClusterProtocolSelection | keyof typeof _envoy_config_cluster_v3_Cluster_ClusterProtocolSelection); + /** + * Common configuration for all load balancer implementations. + */ + 'common_lb_config'?: (_envoy_config_cluster_v3_Cluster_CommonLbConfig | null); + /** + * An optional alternative to the cluster name to be used for observability. This name is used + * emitting stats for the cluster and access logging the cluster name. This will appear as + * additional information in configuration dumps of a cluster's current status as + * :ref:`observability_name ` + * and as an additional tag "upstream_cluster.name" while tracing. Note: access logging using + * this field is presently enabled with runtime feature + * `envoy.reloadable_features.use_observable_cluster_name`. Any ``:`` in the name will be + * converted to ``_`` when emitting statistics. This should not be confused with :ref:`Router + * Filter Header `. + */ + 'alt_stat_name'?: (string); + /** + * Additional options when handling HTTP requests upstream. These options will be applicable to + * both HTTP1 and HTTP2 requests. + * This has been deprecated in favor of + * :ref:`common_http_protocol_options ` + * in the :ref:`http_protocol_options ` message. + * common_http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'common_http_protocol_options'?: (_envoy_config_core_v3_HttpProtocolOptions | null); + /** + * Optional options for upstream connections. + */ + 'upstream_connection_options'?: (_envoy_config_cluster_v3_UpstreamConnectionOptions | null); + /** + * If an upstream host becomes unhealthy (as determined by the configured health checks + * or outlier detection), immediately close all connections to the failed host. + * + * .. note:: + * + * This is currently only supported for connections created by tcp_proxy. + * + * .. note:: + * + * The current implementation of this feature closes all connections immediately when + * the unhealthy status is detected. If there are a large number of connections open + * to an upstream host that becomes unhealthy, Envoy may spend a substantial amount of + * time exclusively closing these connections, and not processing any other traffic. + */ + 'close_connections_on_host_health_failure'?: (boolean); + /** + * If set to true, Envoy will ignore the health value of a host when processing its removal + * from service discovery. This means that if active health checking is used, Envoy will *not* + * wait for the endpoint to go unhealthy before removing it. + */ + 'ignore_health_on_host_removal'?: (boolean); + /** + * Setting this is required for specifying members of + * :ref:`STATIC`, + * :ref:`STRICT_DNS` + * or :ref:`LOGICAL_DNS` clusters. + * This field supersedes the *hosts* field in the v2 API. + * + * .. attention:: + * + * Setting this allows non-EDS cluster types to contain embedded EDS equivalent + * :ref:`endpoint assignments`. + */ + 'load_assignment'?: (_envoy_config_endpoint_v3_ClusterLoadAssignment | null); + /** + * Optional configuration for the Original Destination load balancing policy. + */ + 'original_dst_lb_config'?: (_envoy_config_cluster_v3_Cluster_OriginalDstLbConfig | null); + /** + * The extension_protocol_options field is used to provide extension-specific protocol options + * for upstream connections. The key should match the extension filter name, such as + * "envoy.filters.network.thrift_proxy". See the extension's documentation for details on + * specific options. + * [#next-major-version: make this a list of typed extensions.] + */ + 'typed_extension_protocol_options'?: ({[key: string]: _google_protobuf_Any}); + /** + * Optional configuration for the LeastRequest load balancing policy. + */ + 'least_request_lb_config'?: (_envoy_config_cluster_v3_Cluster_LeastRequestLbConfig | null); + /** + * The custom cluster type. + */ + 'cluster_type'?: (_envoy_config_cluster_v3_Cluster_CustomClusterType | null); + /** + * Optional configuration for setting cluster's DNS refresh rate. If the value is set to true, + * cluster's DNS refresh rate will be set to resource record's TTL which comes from DNS + * resolution. + */ + 'respect_dns_ttl'?: (boolean); + /** + * An (optional) network filter chain, listed in the order the filters should be applied. + * The chain will be applied to all outgoing connections that Envoy makes to the upstream + * servers of this cluster. + */ + 'filters'?: (_envoy_config_cluster_v3_Filter)[]; + /** + * New mechanism for LB policy configuration. Used only if the + * :ref:`lb_policy` field has the value + * :ref:`LOAD_BALANCING_POLICY_CONFIG`. + */ + 'load_balancing_policy'?: (_envoy_config_cluster_v3_LoadBalancingPolicy | null); + /** + * [#not-implemented-hide:] + * If present, tells the client where to send load reports via LRS. If not present, the + * client will fall back to a client-side default, which may be either (a) don't send any + * load reports or (b) send load reports for all clusters to a single default server + * (which may be configured in the bootstrap file). + * + * Note that if multiple clusters point to the same LRS server, the client may choose to + * create a separate stream for each cluster or it may choose to coalesce the data for + * multiple clusters onto a single stream. Either way, the client must make sure to send + * the data for any given cluster on no more than one stream. + * + * [#next-major-version: In the v3 API, we should consider restructuring this somehow, + * maybe by allowing LRS to go on the ADS stream, or maybe by moving some of the negotiation + * from the LRS stream here.] + */ + 'lrs_server'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * Configuration to use different transport sockets for different endpoints. + * The entry of *envoy.transport_socket_match* in the + * :ref:`LbEndpoint.Metadata ` + * is used to match against the transport sockets as they appear in the list. The first + * :ref:`match ` is used. + * For example, with the following match + * + * .. code-block:: yaml + * + * transport_socket_matches: + * - name: "enableMTLS" + * match: + * acceptMTLS: true + * transport_socket: + * name: envoy.transport_sockets.tls + * config: { ... } # tls socket configuration + * - name: "defaultToPlaintext" + * match: {} + * transport_socket: + * name: envoy.transport_sockets.raw_buffer + * + * Connections to the endpoints whose metadata value under *envoy.transport_socket_match* + * having "acceptMTLS"/"true" key/value pair use the "enableMTLS" socket configuration. + * + * If a :ref:`socket match ` with empty match + * criteria is provided, that always match any endpoint. For example, the "defaultToPlaintext" + * socket match in case above. + * + * If an endpoint metadata's value under *envoy.transport_socket_match* does not match any + * *TransportSocketMatch*, socket configuration fallbacks to use the *tls_context* or + * *transport_socket* specified in this cluster. + * + * This field allows gradual and flexible transport socket configuration changes. + * + * The metadata of endpoints in EDS can indicate transport socket capabilities. For example, + * an endpoint's metadata can have two key value pairs as "acceptMTLS": "true", + * "acceptPlaintext": "true". While some other endpoints, only accepting plaintext traffic + * has "acceptPlaintext": "true" metadata information. + * + * Then the xDS server can configure the CDS to a client, Envoy A, to send mutual TLS + * traffic for endpoints with "acceptMTLS": "true", by adding a corresponding + * *TransportSocketMatch* in this field. Other client Envoys receive CDS without + * *transport_socket_match* set, and still send plain text traffic to the same cluster. + * + * This field can be used to specify custom transport socket configurations for health + * checks by adding matching key/value pairs in a health check's + * :ref:`transport socket match criteria ` field. + * + * [#comment:TODO(incfly): add a detailed architecture doc on intended usage.] + */ + 'transport_socket_matches'?: (_envoy_config_cluster_v3_Cluster_TransportSocketMatch)[]; + /** + * If the DNS failure refresh rate is specified and the cluster type is either + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`, + * this is used as the cluster’s DNS refresh rate when requests are failing. If this setting is + * not specified, the failure refresh rate defaults to the DNS refresh rate. For cluster types + * other than :ref:`STRICT_DNS` and + * :ref:`LOGICAL_DNS` this setting is + * ignored. + */ + 'dns_failure_refresh_rate'?: (_envoy_config_cluster_v3_Cluster_RefreshRate | null); + /** + * Always use TCP queries instead of UDP queries for DNS lookups. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple' API only uses UDP for DNS resolution. + * This field is deprecated in favor of *dns_resolution_config* + * which aggregates all of the DNS resolver configuration in a single message. + */ + 'use_tcp_for_dns_lookups'?: (boolean); + /** + * HTTP protocol options that are applied only to upstream HTTP connections. + * These options apply to all HTTP versions. + * This has been deprecated in favor of + * :ref:`upstream_http_protocol_options ` + * in the :ref:`http_protocol_options ` message. + * upstream_http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'upstream_http_protocol_options'?: (_envoy_config_core_v3_UpstreamHttpProtocolOptions | null); + /** + * If track_timeout_budgets is true, the :ref:`timeout budget histograms + * ` will be published for each + * request. These show what percentage of a request's per try and global timeout was used. A value + * of 0 would indicate that none of the timeout was used or that the timeout was infinite. A value + * of 100 would indicate that the request took the entirety of the timeout given to it. + * + * .. attention:: + * + * This field has been deprecated in favor of `timeout_budgets`, part of + * :ref:`track_cluster_stats `. + */ + 'track_timeout_budgets'?: (boolean); + /** + * Optional customization and configuration of upstream connection pool, and upstream type. + * + * Currently this field only applies for HTTP traffic but is designed for eventual use for custom + * TCP upstreams. + * + * For HTTP traffic, Envoy will generally take downstream HTTP and send it upstream as upstream + * HTTP, using the http connection pool and the codec from `http2_protocol_options` + * + * For routes where CONNECT termination is configured, Envoy will take downstream CONNECT + * requests and forward the CONNECT payload upstream over raw TCP using the tcp connection pool. + * + * The default pool used is the generic connection pool which creates the HTTP upstream for most + * HTTP requests, and the TCP upstream if CONNECT termination is configured. + * + * If users desire custom connection pool or upstream behavior, for example terminating + * CONNECT only if a custom filter indicates it is appropriate, the custom factories + * can be registered and configured here. + * [#extension-category: envoy.upstreams] + */ + 'upstream_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + /** + * Configuration to track optional cluster stats. + */ + 'track_cluster_stats'?: (_envoy_config_cluster_v3_TrackClusterStats | null); + /** + * Preconnect configuration for this cluster. + */ + 'preconnect_policy'?: (_envoy_config_cluster_v3_Cluster_PreconnectPolicy | null); + /** + * If `connection_pool_per_downstream_connection` is true, the cluster will use a separate + * connection pool for every downstream connection + */ + 'connection_pool_per_downstream_connection'?: (boolean); + /** + * Optional configuration for the Maglev load balancing policy. + */ + 'maglev_lb_config'?: (_envoy_config_cluster_v3_Cluster_MaglevLbConfig | null); + /** + * DNS resolution configuration which includes the underlying dns resolver addresses and options. + * *dns_resolution_config* will be deprecated once + * :ref:'typed_dns_resolver_config ' + * is fully supported. + */ + 'dns_resolution_config'?: (_envoy_config_core_v3_DnsResolutionConfig | null); + /** + * Optional configuration for having cluster readiness block on warm-up. Currently, only applicable for + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`. + * If true, cluster readiness blocks on warm-up. If false, the cluster will complete + * initialization whether or not warm-up has completed. Defaults to true. + */ + 'wait_for_warm_on_init'?: (_google_protobuf_BoolValue | null); + /** + * DNS resolver type configuration extension. This extension can be used to configure c-ares, apple, + * or any other DNS resolver types and the related parameters. + * For example, an object of :ref:`DnsResolutionConfig ` + * can be packed into this *typed_dns_resolver_config*. This configuration will replace the + * :ref:'dns_resolution_config ' + * configuration eventually. + * TODO(yanjunxiang): Investigate the deprecation plan for *dns_resolution_config*. + * During the transition period when both *dns_resolution_config* and *typed_dns_resolver_config* exists, + * this configuration is optional. + * When *typed_dns_resolver_config* is in place, Envoy will use it and ignore *dns_resolution_config*. + * When *typed_dns_resolver_config* is missing, the default behavior is in place. + * [#not-implemented-hide:] + */ + 'typed_dns_resolver_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + /** + * Optional configuration for the RoundRobin load balancing policy. + */ + 'round_robin_lb_config'?: (_envoy_config_cluster_v3_Cluster_RoundRobinLbConfig | null); + 'cluster_discovery_type'?: "type"|"cluster_type"; + /** + * Optional configuration for the load balancing algorithm selected by + * LbPolicy. Currently only + * :ref:`RING_HASH`, + * :ref:`MAGLEV` and + * :ref:`LEAST_REQUEST` + * has additional configuration options. + * Specifying ring_hash_lb_config or maglev_lb_config or least_request_lb_config without setting the corresponding + * LbPolicy will generate an error at runtime. + */ + 'lb_config'?: "ring_hash_lb_config"|"maglev_lb_config"|"original_dst_lb_config"|"least_request_lb_config"|"round_robin_lb_config"; +} + +/** + * Configuration for a single upstream cluster. + * [#next-free-field: 57] + */ +export interface Cluster__Output { + /** + * Supplies the name of the cluster which must be unique across all clusters. + * The cluster name is used when emitting + * :ref:`statistics ` if :ref:`alt_stat_name + * ` is not provided. + * Any ``:`` in the cluster name will be converted to ``_`` when emitting statistics. + */ + 'name': (string); + /** + * The :ref:`service discovery type ` + * to use for resolving the cluster. + */ + 'type'?: (keyof typeof _envoy_config_cluster_v3_Cluster_DiscoveryType); + /** + * Configuration to use for EDS updates for the Cluster. + */ + 'eds_cluster_config': (_envoy_config_cluster_v3_Cluster_EdsClusterConfig__Output | null); + /** + * The timeout for new network connections to hosts in the cluster. + * If not set, a default value of 5s will be used. + */ + 'connect_timeout': (_google_protobuf_Duration__Output | null); + /** + * Soft limit on size of the cluster’s connections read and write buffers. If + * unspecified, an implementation defined default is applied (1MiB). + */ + 'per_connection_buffer_limit_bytes': (_google_protobuf_UInt32Value__Output | null); + /** + * The :ref:`load balancer type ` to use + * when picking a host in the cluster. + */ + 'lb_policy': (keyof typeof _envoy_config_cluster_v3_Cluster_LbPolicy); + /** + * Optional :ref:`active health checking ` + * configuration for the cluster. If no + * configuration is specified no health checking will be done and all cluster + * members will be considered healthy at all times. + */ + 'health_checks': (_envoy_config_core_v3_HealthCheck__Output)[]; + /** + * Optional maximum requests for a single upstream connection. This parameter + * is respected by both the HTTP/1.1 and HTTP/2 connection pool + * implementations. If not specified, there is no limit. Setting this + * parameter to 1 will effectively disable keep alive. + * + * .. attention:: + * This field has been deprecated in favor of the :ref:`max_requests_per_connection ` field. + */ + 'max_requests_per_connection': (_google_protobuf_UInt32Value__Output | null); + /** + * Optional :ref:`circuit breaking ` for the cluster. + */ + 'circuit_breakers': (_envoy_config_cluster_v3_CircuitBreakers__Output | null); + /** + * Additional options when handling HTTP1 requests. + * This has been deprecated in favor of http_protocol_options fields in the + * :ref:`http_protocol_options ` message. + * http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'http_protocol_options': (_envoy_config_core_v3_Http1ProtocolOptions__Output | null); + /** + * Even if default HTTP2 protocol options are desired, this field must be + * set so that Envoy will assume that the upstream supports HTTP/2 when + * making new HTTP connection pool connections. Currently, Envoy only + * supports prior knowledge for upstream connections. Even if TLS is used + * with ALPN, `http2_protocol_options` must be specified. As an aside this allows HTTP/2 + * connections to happen over plain text. + * This has been deprecated in favor of http2_protocol_options fields in the + * :ref:`http_protocol_options ` + * message. http2_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'http2_protocol_options': (_envoy_config_core_v3_Http2ProtocolOptions__Output | null); + /** + * If the DNS refresh rate is specified and the cluster type is either + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`, + * this value is used as the cluster’s DNS refresh + * rate. The value configured must be at least 1ms. If this setting is not specified, the + * value defaults to 5000ms. For cluster types other than + * :ref:`STRICT_DNS` + * and :ref:`LOGICAL_DNS` + * this setting is ignored. + */ + 'dns_refresh_rate': (_google_protobuf_Duration__Output | null); + /** + * The DNS IP address resolution policy. If this setting is not specified, the + * value defaults to + * :ref:`AUTO`. + */ + 'dns_lookup_family': (keyof typeof _envoy_config_cluster_v3_Cluster_DnsLookupFamily); + /** + * If DNS resolvers are specified and the cluster type is either + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`, + * this value is used to specify the cluster’s dns resolvers. + * If this setting is not specified, the value defaults to the default + * resolver, which uses /etc/resolv.conf for configuration. For cluster types + * other than + * :ref:`STRICT_DNS` + * and :ref:`LOGICAL_DNS` + * this setting is ignored. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple's API only allows overriding DNS resolvers via system settings. + * This field is deprecated in favor of *dns_resolution_config* + * which aggregates all of the DNS resolver configuration in a single message. + */ + 'dns_resolvers': (_envoy_config_core_v3_Address__Output)[]; + /** + * If specified, outlier detection will be enabled for this upstream cluster. + * Each of the configuration values can be overridden via + * :ref:`runtime values `. + */ + 'outlier_detection': (_envoy_config_cluster_v3_OutlierDetection__Output | null); + /** + * The interval for removing stale hosts from a cluster type + * :ref:`ORIGINAL_DST`. + * Hosts are considered stale if they have not been used + * as upstream destinations during this interval. New hosts are added + * to original destination clusters on demand as new connections are + * redirected to Envoy, causing the number of hosts in the cluster to + * grow over time. Hosts that are not stale (they are actively used as + * destinations) are kept in the cluster, which allows connections to + * them remain open, saving the latency that would otherwise be spent + * on opening new connections. If this setting is not specified, the + * value defaults to 5000ms. For cluster types other than + * :ref:`ORIGINAL_DST` + * this setting is ignored. + */ + 'cleanup_interval': (_google_protobuf_Duration__Output | null); + /** + * Optional configuration used to bind newly established upstream connections. + * This overrides any bind_config specified in the bootstrap proto. + * If the address and port are empty, no bind will be performed. + */ + 'upstream_bind_config': (_envoy_config_core_v3_BindConfig__Output | null); + /** + * Configuration for load balancing subsetting. + */ + 'lb_subset_config': (_envoy_config_cluster_v3_Cluster_LbSubsetConfig__Output | null); + /** + * Optional configuration for the Ring Hash load balancing policy. + */ + 'ring_hash_lb_config'?: (_envoy_config_cluster_v3_Cluster_RingHashLbConfig__Output | null); + /** + * Optional custom transport socket implementation to use for upstream connections. + * To setup TLS, set a transport socket with name `envoy.transport_sockets.tls` and + * :ref:`UpstreamTlsContexts ` in the `typed_config`. + * If no transport socket configuration is specified, new connections + * will be set up with plaintext. + */ + 'transport_socket': (_envoy_config_core_v3_TransportSocket__Output | null); + /** + * The Metadata field can be used to provide additional information about the + * cluster. It can be used for stats, logging, and varying filter behavior. + * Fields should use reverse DNS notation to denote which entity within Envoy + * will need the information. For instance, if the metadata is intended for + * the Router filter, the filter name should be specified as *envoy.filters.http.router*. + */ + 'metadata': (_envoy_config_core_v3_Metadata__Output | null); + /** + * Determines how Envoy selects the protocol used to speak to upstream hosts. + * This has been deprecated in favor of setting explicit protocol selection + * in the :ref:`http_protocol_options + * ` message. + * http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + */ + 'protocol_selection': (keyof typeof _envoy_config_cluster_v3_Cluster_ClusterProtocolSelection); + /** + * Common configuration for all load balancer implementations. + */ + 'common_lb_config': (_envoy_config_cluster_v3_Cluster_CommonLbConfig__Output | null); + /** + * An optional alternative to the cluster name to be used for observability. This name is used + * emitting stats for the cluster and access logging the cluster name. This will appear as + * additional information in configuration dumps of a cluster's current status as + * :ref:`observability_name ` + * and as an additional tag "upstream_cluster.name" while tracing. Note: access logging using + * this field is presently enabled with runtime feature + * `envoy.reloadable_features.use_observable_cluster_name`. Any ``:`` in the name will be + * converted to ``_`` when emitting statistics. This should not be confused with :ref:`Router + * Filter Header `. + */ + 'alt_stat_name': (string); + /** + * Additional options when handling HTTP requests upstream. These options will be applicable to + * both HTTP1 and HTTP2 requests. + * This has been deprecated in favor of + * :ref:`common_http_protocol_options ` + * in the :ref:`http_protocol_options ` message. + * common_http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'common_http_protocol_options': (_envoy_config_core_v3_HttpProtocolOptions__Output | null); + /** + * Optional options for upstream connections. + */ + 'upstream_connection_options': (_envoy_config_cluster_v3_UpstreamConnectionOptions__Output | null); + /** + * If an upstream host becomes unhealthy (as determined by the configured health checks + * or outlier detection), immediately close all connections to the failed host. + * + * .. note:: + * + * This is currently only supported for connections created by tcp_proxy. + * + * .. note:: + * + * The current implementation of this feature closes all connections immediately when + * the unhealthy status is detected. If there are a large number of connections open + * to an upstream host that becomes unhealthy, Envoy may spend a substantial amount of + * time exclusively closing these connections, and not processing any other traffic. + */ + 'close_connections_on_host_health_failure': (boolean); + /** + * If set to true, Envoy will ignore the health value of a host when processing its removal + * from service discovery. This means that if active health checking is used, Envoy will *not* + * wait for the endpoint to go unhealthy before removing it. + */ + 'ignore_health_on_host_removal': (boolean); + /** + * Setting this is required for specifying members of + * :ref:`STATIC`, + * :ref:`STRICT_DNS` + * or :ref:`LOGICAL_DNS` clusters. + * This field supersedes the *hosts* field in the v2 API. + * + * .. attention:: + * + * Setting this allows non-EDS cluster types to contain embedded EDS equivalent + * :ref:`endpoint assignments`. + */ + 'load_assignment': (_envoy_config_endpoint_v3_ClusterLoadAssignment__Output | null); + /** + * Optional configuration for the Original Destination load balancing policy. + */ + 'original_dst_lb_config'?: (_envoy_config_cluster_v3_Cluster_OriginalDstLbConfig__Output | null); + /** + * The extension_protocol_options field is used to provide extension-specific protocol options + * for upstream connections. The key should match the extension filter name, such as + * "envoy.filters.network.thrift_proxy". See the extension's documentation for details on + * specific options. + * [#next-major-version: make this a list of typed extensions.] + */ + 'typed_extension_protocol_options': ({[key: string]: _google_protobuf_Any__Output}); + /** + * Optional configuration for the LeastRequest load balancing policy. + */ + 'least_request_lb_config'?: (_envoy_config_cluster_v3_Cluster_LeastRequestLbConfig__Output | null); + /** + * The custom cluster type. + */ + 'cluster_type'?: (_envoy_config_cluster_v3_Cluster_CustomClusterType__Output | null); + /** + * Optional configuration for setting cluster's DNS refresh rate. If the value is set to true, + * cluster's DNS refresh rate will be set to resource record's TTL which comes from DNS + * resolution. + */ + 'respect_dns_ttl': (boolean); + /** + * An (optional) network filter chain, listed in the order the filters should be applied. + * The chain will be applied to all outgoing connections that Envoy makes to the upstream + * servers of this cluster. + */ + 'filters': (_envoy_config_cluster_v3_Filter__Output)[]; + /** + * New mechanism for LB policy configuration. Used only if the + * :ref:`lb_policy` field has the value + * :ref:`LOAD_BALANCING_POLICY_CONFIG`. + */ + 'load_balancing_policy': (_envoy_config_cluster_v3_LoadBalancingPolicy__Output | null); + /** + * [#not-implemented-hide:] + * If present, tells the client where to send load reports via LRS. If not present, the + * client will fall back to a client-side default, which may be either (a) don't send any + * load reports or (b) send load reports for all clusters to a single default server + * (which may be configured in the bootstrap file). + * + * Note that if multiple clusters point to the same LRS server, the client may choose to + * create a separate stream for each cluster or it may choose to coalesce the data for + * multiple clusters onto a single stream. Either way, the client must make sure to send + * the data for any given cluster on no more than one stream. + * + * [#next-major-version: In the v3 API, we should consider restructuring this somehow, + * maybe by allowing LRS to go on the ADS stream, or maybe by moving some of the negotiation + * from the LRS stream here.] + */ + 'lrs_server': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * Configuration to use different transport sockets for different endpoints. + * The entry of *envoy.transport_socket_match* in the + * :ref:`LbEndpoint.Metadata ` + * is used to match against the transport sockets as they appear in the list. The first + * :ref:`match ` is used. + * For example, with the following match + * + * .. code-block:: yaml + * + * transport_socket_matches: + * - name: "enableMTLS" + * match: + * acceptMTLS: true + * transport_socket: + * name: envoy.transport_sockets.tls + * config: { ... } # tls socket configuration + * - name: "defaultToPlaintext" + * match: {} + * transport_socket: + * name: envoy.transport_sockets.raw_buffer + * + * Connections to the endpoints whose metadata value under *envoy.transport_socket_match* + * having "acceptMTLS"/"true" key/value pair use the "enableMTLS" socket configuration. + * + * If a :ref:`socket match ` with empty match + * criteria is provided, that always match any endpoint. For example, the "defaultToPlaintext" + * socket match in case above. + * + * If an endpoint metadata's value under *envoy.transport_socket_match* does not match any + * *TransportSocketMatch*, socket configuration fallbacks to use the *tls_context* or + * *transport_socket* specified in this cluster. + * + * This field allows gradual and flexible transport socket configuration changes. + * + * The metadata of endpoints in EDS can indicate transport socket capabilities. For example, + * an endpoint's metadata can have two key value pairs as "acceptMTLS": "true", + * "acceptPlaintext": "true". While some other endpoints, only accepting plaintext traffic + * has "acceptPlaintext": "true" metadata information. + * + * Then the xDS server can configure the CDS to a client, Envoy A, to send mutual TLS + * traffic for endpoints with "acceptMTLS": "true", by adding a corresponding + * *TransportSocketMatch* in this field. Other client Envoys receive CDS without + * *transport_socket_match* set, and still send plain text traffic to the same cluster. + * + * This field can be used to specify custom transport socket configurations for health + * checks by adding matching key/value pairs in a health check's + * :ref:`transport socket match criteria ` field. + * + * [#comment:TODO(incfly): add a detailed architecture doc on intended usage.] + */ + 'transport_socket_matches': (_envoy_config_cluster_v3_Cluster_TransportSocketMatch__Output)[]; + /** + * If the DNS failure refresh rate is specified and the cluster type is either + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`, + * this is used as the cluster’s DNS refresh rate when requests are failing. If this setting is + * not specified, the failure refresh rate defaults to the DNS refresh rate. For cluster types + * other than :ref:`STRICT_DNS` and + * :ref:`LOGICAL_DNS` this setting is + * ignored. + */ + 'dns_failure_refresh_rate': (_envoy_config_cluster_v3_Cluster_RefreshRate__Output | null); + /** + * Always use TCP queries instead of UDP queries for DNS lookups. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple' API only uses UDP for DNS resolution. + * This field is deprecated in favor of *dns_resolution_config* + * which aggregates all of the DNS resolver configuration in a single message. + */ + 'use_tcp_for_dns_lookups': (boolean); + /** + * HTTP protocol options that are applied only to upstream HTTP connections. + * These options apply to all HTTP versions. + * This has been deprecated in favor of + * :ref:`upstream_http_protocol_options ` + * in the :ref:`http_protocol_options ` message. + * upstream_http_protocol_options can be set via the cluster's + * :ref:`extension_protocol_options`. + * See :ref:`upstream_http_protocol_options + * ` + * for example usage. + */ + 'upstream_http_protocol_options': (_envoy_config_core_v3_UpstreamHttpProtocolOptions__Output | null); + /** + * If track_timeout_budgets is true, the :ref:`timeout budget histograms + * ` will be published for each + * request. These show what percentage of a request's per try and global timeout was used. A value + * of 0 would indicate that none of the timeout was used or that the timeout was infinite. A value + * of 100 would indicate that the request took the entirety of the timeout given to it. + * + * .. attention:: + * + * This field has been deprecated in favor of `timeout_budgets`, part of + * :ref:`track_cluster_stats `. + */ + 'track_timeout_budgets': (boolean); + /** + * Optional customization and configuration of upstream connection pool, and upstream type. + * + * Currently this field only applies for HTTP traffic but is designed for eventual use for custom + * TCP upstreams. + * + * For HTTP traffic, Envoy will generally take downstream HTTP and send it upstream as upstream + * HTTP, using the http connection pool and the codec from `http2_protocol_options` + * + * For routes where CONNECT termination is configured, Envoy will take downstream CONNECT + * requests and forward the CONNECT payload upstream over raw TCP using the tcp connection pool. + * + * The default pool used is the generic connection pool which creates the HTTP upstream for most + * HTTP requests, and the TCP upstream if CONNECT termination is configured. + * + * If users desire custom connection pool or upstream behavior, for example terminating + * CONNECT only if a custom filter indicates it is appropriate, the custom factories + * can be registered and configured here. + * [#extension-category: envoy.upstreams] + */ + 'upstream_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + /** + * Configuration to track optional cluster stats. + */ + 'track_cluster_stats': (_envoy_config_cluster_v3_TrackClusterStats__Output | null); + /** + * Preconnect configuration for this cluster. + */ + 'preconnect_policy': (_envoy_config_cluster_v3_Cluster_PreconnectPolicy__Output | null); + /** + * If `connection_pool_per_downstream_connection` is true, the cluster will use a separate + * connection pool for every downstream connection + */ + 'connection_pool_per_downstream_connection': (boolean); + /** + * Optional configuration for the Maglev load balancing policy. + */ + 'maglev_lb_config'?: (_envoy_config_cluster_v3_Cluster_MaglevLbConfig__Output | null); + /** + * DNS resolution configuration which includes the underlying dns resolver addresses and options. + * *dns_resolution_config* will be deprecated once + * :ref:'typed_dns_resolver_config ' + * is fully supported. + */ + 'dns_resolution_config': (_envoy_config_core_v3_DnsResolutionConfig__Output | null); + /** + * Optional configuration for having cluster readiness block on warm-up. Currently, only applicable for + * :ref:`STRICT_DNS`, + * or :ref:`LOGICAL_DNS`. + * If true, cluster readiness blocks on warm-up. If false, the cluster will complete + * initialization whether or not warm-up has completed. Defaults to true. + */ + 'wait_for_warm_on_init': (_google_protobuf_BoolValue__Output | null); + /** + * DNS resolver type configuration extension. This extension can be used to configure c-ares, apple, + * or any other DNS resolver types and the related parameters. + * For example, an object of :ref:`DnsResolutionConfig ` + * can be packed into this *typed_dns_resolver_config*. This configuration will replace the + * :ref:'dns_resolution_config ' + * configuration eventually. + * TODO(yanjunxiang): Investigate the deprecation plan for *dns_resolution_config*. + * During the transition period when both *dns_resolution_config* and *typed_dns_resolver_config* exists, + * this configuration is optional. + * When *typed_dns_resolver_config* is in place, Envoy will use it and ignore *dns_resolution_config*. + * When *typed_dns_resolver_config* is missing, the default behavior is in place. + * [#not-implemented-hide:] + */ + 'typed_dns_resolver_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + /** + * Optional configuration for the RoundRobin load balancing policy. + */ + 'round_robin_lb_config'?: (_envoy_config_cluster_v3_Cluster_RoundRobinLbConfig__Output | null); + 'cluster_discovery_type': "type"|"cluster_type"; + /** + * Optional configuration for the load balancing algorithm selected by + * LbPolicy. Currently only + * :ref:`RING_HASH`, + * :ref:`MAGLEV` and + * :ref:`LEAST_REQUEST` + * has additional configuration options. + * Specifying ring_hash_lb_config or maglev_lb_config or least_request_lb_config without setting the corresponding + * LbPolicy will generate an error at runtime. + */ + 'lb_config': "ring_hash_lb_config"|"maglev_lb_config"|"original_dst_lb_config"|"least_request_lb_config"|"round_robin_lb_config"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/ClusterCollection.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/ClusterCollection.ts new file mode 100644 index 000000000..8b1394d4b --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/ClusterCollection.ts @@ -0,0 +1,19 @@ +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +import type { CollectionEntry as _xds_core_v3_CollectionEntry, CollectionEntry__Output as _xds_core_v3_CollectionEntry__Output } from '../../../../xds/core/v3/CollectionEntry'; + +/** + * Cluster list collections. Entries are *Cluster* resources or references. + * [#not-implemented-hide:] + */ +export interface ClusterCollection { + 'entries'?: (_xds_core_v3_CollectionEntry | null); +} + +/** + * Cluster list collections. Entries are *Cluster* resources or references. + * [#not-implemented-hide:] + */ +export interface ClusterCollection__Output { + 'entries': (_xds_core_v3_CollectionEntry__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/Filter.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/Filter.ts similarity index 59% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/Filter.ts rename to packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/Filter.ts index 5608fadf2..9d9031b68 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/Filter.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/Filter.ts @@ -1,29 +1,31 @@ -// Original file: deps/envoy-api/envoy/api/v2/cluster/filter.proto +// Original file: deps/envoy-api/envoy/config/cluster/v3/filter.proto import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; export interface Filter { /** * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. + * supported upstream filter. Note that Envoy's :ref:`downstream network + * filters ` are not valid upstream filters. */ 'name'?: (string); /** * Filter specific configuration which depends on the filter being * instantiated. See the supported filters for further documentation. */ - 'typed_config'?: (_google_protobuf_Any); + 'typed_config'?: (_google_protobuf_Any | null); } export interface Filter__Output { /** * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. + * supported upstream filter. Note that Envoy's :ref:`downstream network + * filters ` are not valid upstream filters. */ 'name': (string); /** * Filter specific configuration which depends on the filter being * instantiated. See the supported filters for further documentation. */ - 'typed_config'?: (_google_protobuf_Any__Output); + 'typed_config': (_google_protobuf_Any__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/LoadBalancingPolicy.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/LoadBalancingPolicy.ts similarity index 70% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/LoadBalancingPolicy.ts rename to packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/LoadBalancingPolicy.ts index f79112a1c..78d4a6bfd 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/LoadBalancingPolicy.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/LoadBalancingPolicy.ts @@ -1,36 +1,17 @@ -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; -export interface _envoy_api_v2_LoadBalancingPolicy_Policy { - /** - * Required. The name of the LB policy. - */ - 'name'?: (string); - /** - * Optional config for the LB policy. - * No more than one of these two fields may be populated. - */ - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); +export interface _envoy_config_cluster_v3_LoadBalancingPolicy_Policy { + 'typed_extension_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); } -export interface _envoy_api_v2_LoadBalancingPolicy_Policy__Output { - /** - * Required. The name of the LB policy. - */ - 'name': (string); - /** - * Optional config for the LB policy. - * No more than one of these two fields may be populated. - */ - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); +export interface _envoy_config_cluster_v3_LoadBalancingPolicy_Policy__Output { + 'typed_extension_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); } /** - * [#not-implemented-hide:] Extensible load balancing policy configuration. + * Extensible load balancing policy configuration. * * Every LB policy defined via this mechanism will be identified via a unique name using reverse * DNS notation. If the policy needs configuration parameters, it must define a message for its @@ -56,11 +37,11 @@ export interface LoadBalancingPolicy { * supports. This provides a mechanism for starting to use new LB policies that are not yet * supported by all clients. */ - 'policies'?: (_envoy_api_v2_LoadBalancingPolicy_Policy)[]; + 'policies'?: (_envoy_config_cluster_v3_LoadBalancingPolicy_Policy)[]; } /** - * [#not-implemented-hide:] Extensible load balancing policy configuration. + * Extensible load balancing policy configuration. * * Every LB policy defined via this mechanism will be identified via a unique name using reverse * DNS notation. If the policy needs configuration parameters, it must define a message for its @@ -86,5 +67,5 @@ export interface LoadBalancingPolicy__Output { * supports. This provides a mechanism for starting to use new LB policies that are not yet * supported by all clients. */ - 'policies': (_envoy_api_v2_LoadBalancingPolicy_Policy__Output)[]; + 'policies': (_envoy_config_cluster_v3_LoadBalancingPolicy_Policy__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/OutlierDetection.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/OutlierDetection.ts similarity index 68% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/OutlierDetection.ts rename to packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/OutlierDetection.ts index 53c1b4609..789004ad4 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/cluster/OutlierDetection.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/OutlierDetection.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/cluster/outlier_detection.proto +// Original file: deps/envoy-api/envoy/config/cluster/v3/outlier_detection.proto import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; @@ -6,7 +6,7 @@ import type { Duration as _google_protobuf_Duration, Duration__Output as _google /** * See the :ref:`architecture overview ` for * more information on outlier detection. - * [#next-free-field: 21] + * [#next-free-field: 22] */ export interface OutlierDetection { /** @@ -14,43 +14,44 @@ export interface OutlierDetection { * to 5xx error codes before a consecutive 5xx ejection * occurs. Defaults to 5. */ - 'consecutive_5xx'?: (_google_protobuf_UInt32Value); + 'consecutive_5xx'?: (_google_protobuf_UInt32Value | null); /** * The time interval between ejection analysis sweeps. This can result in * both new ejections as well as hosts being returned to service. Defaults * to 10000ms or 10s. */ - 'interval'?: (_google_protobuf_Duration); + 'interval'?: (_google_protobuf_Duration | null); /** * The base time that a host is ejected for. The real time is equal to the - * base time multiplied by the number of times the host has been ejected. + * base time multiplied by the number of times the host has been ejected and is + * capped by :ref:`max_ejection_time`. * Defaults to 30000ms or 30s. */ - 'base_ejection_time'?: (_google_protobuf_Duration); + 'base_ejection_time'?: (_google_protobuf_Duration | null); /** * The maximum % of an upstream cluster that can be ejected due to outlier * detection. Defaults to 10% but will eject at least one host regardless of the value. */ - 'max_ejection_percent'?: (_google_protobuf_UInt32Value); + 'max_ejection_percent'?: (_google_protobuf_UInt32Value | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through consecutive 5xx. This setting can be used to disable * ejection or to ramp it up slowly. Defaults to 100. */ - 'enforcing_consecutive_5xx'?: (_google_protobuf_UInt32Value); + 'enforcing_consecutive_5xx'?: (_google_protobuf_UInt32Value | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through success rate statistics. This setting can be used to * disable ejection or to ramp it up slowly. Defaults to 100. */ - 'enforcing_success_rate'?: (_google_protobuf_UInt32Value); + 'enforcing_success_rate'?: (_google_protobuf_UInt32Value | null); /** * The number of hosts in a cluster that must have enough request volume to * detect success rate outliers. If the number of hosts is less than this * setting, outlier detection via success rate statistics is not performed * for any host in the cluster. Defaults to 5. */ - 'success_rate_minimum_hosts'?: (_google_protobuf_UInt32Value); + 'success_rate_minimum_hosts'?: (_google_protobuf_UInt32Value | null); /** * The minimum number of total requests that must be collected in one * interval (as defined by the interval duration above) to include this host @@ -58,7 +59,7 @@ export interface OutlierDetection { * setting, outlier detection via success rate statistics is not performed * for that host. Defaults to 100. */ - 'success_rate_request_volume'?: (_google_protobuf_UInt32Value); + 'success_rate_request_volume'?: (_google_protobuf_UInt32Value | null); /** * This factor is used to determine the ejection threshold for success rate * outlier ejection. The ejection threshold is the difference between the @@ -68,59 +69,59 @@ export interface OutlierDetection { * double. That is, if the desired factor is 1.9, the runtime value should * be 1900. Defaults to 1900. */ - 'success_rate_stdev_factor'?: (_google_protobuf_UInt32Value); + 'success_rate_stdev_factor'?: (_google_protobuf_UInt32Value | null); /** * The number of consecutive gateway failures (502, 503, 504 status codes) * before a consecutive gateway failure ejection occurs. Defaults to 5. */ - 'consecutive_gateway_failure'?: (_google_protobuf_UInt32Value); + 'consecutive_gateway_failure'?: (_google_protobuf_UInt32Value | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through consecutive gateway failures. This setting can be * used to disable ejection or to ramp it up slowly. Defaults to 0. */ - 'enforcing_consecutive_gateway_failure'?: (_google_protobuf_UInt32Value); + 'enforcing_consecutive_gateway_failure'?: (_google_protobuf_UInt32Value | null); /** * Determines whether to distinguish local origin failures from external errors. If set to true * the following configuration parameters are taken into account: - * :ref:`consecutive_local_origin_failure`, - * :ref:`enforcing_consecutive_local_origin_failure` + * :ref:`consecutive_local_origin_failure`, + * :ref:`enforcing_consecutive_local_origin_failure` * and - * :ref:`enforcing_local_origin_success_rate`. + * :ref:`enforcing_local_origin_success_rate`. * Defaults to false. */ 'split_external_local_origin_errors'?: (boolean); /** * The number of consecutive locally originated failures before ejection * occurs. Defaults to 5. Parameter takes effect only when - * :ref:`split_external_local_origin_errors` + * :ref:`split_external_local_origin_errors` * is set to true. */ - 'consecutive_local_origin_failure'?: (_google_protobuf_UInt32Value); + 'consecutive_local_origin_failure'?: (_google_protobuf_UInt32Value | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through consecutive locally originated failures. This setting can be * used to disable ejection or to ramp it up slowly. Defaults to 100. * Parameter takes effect only when - * :ref:`split_external_local_origin_errors` + * :ref:`split_external_local_origin_errors` * is set to true. */ - 'enforcing_consecutive_local_origin_failure'?: (_google_protobuf_UInt32Value); + 'enforcing_consecutive_local_origin_failure'?: (_google_protobuf_UInt32Value | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through success rate statistics for locally originated errors. * This setting can be used to disable ejection or to ramp it up slowly. Defaults to 100. * Parameter takes effect only when - * :ref:`split_external_local_origin_errors` + * :ref:`split_external_local_origin_errors` * is set to true. */ - 'enforcing_local_origin_success_rate'?: (_google_protobuf_UInt32Value); + 'enforcing_local_origin_success_rate'?: (_google_protobuf_UInt32Value | null); /** * The failure percentage to use when determining failure percentage-based outlier detection. If * the failure percentage of a given host is greater than or equal to this value, it will be * ejected. Defaults to 85. */ - 'failure_percentage_threshold'?: (_google_protobuf_UInt32Value); + 'failure_percentage_threshold'?: (_google_protobuf_UInt32Value | null); /** * The % chance that a host will be actually ejected when an outlier status is detected through * failure percentage statistics. This setting can be used to disable ejection or to ramp it up @@ -129,32 +130,38 @@ export interface OutlierDetection { * [#next-major-version: setting this without setting failure_percentage_threshold should be * invalid in v4.] */ - 'enforcing_failure_percentage'?: (_google_protobuf_UInt32Value); + 'enforcing_failure_percentage'?: (_google_protobuf_UInt32Value | null); /** * The % chance that a host will be actually ejected when an outlier status is detected through * local-origin failure percentage statistics. This setting can be used to disable ejection or to * ramp it up slowly. Defaults to 0. */ - 'enforcing_failure_percentage_local_origin'?: (_google_protobuf_UInt32Value); + 'enforcing_failure_percentage_local_origin'?: (_google_protobuf_UInt32Value | null); /** * The minimum number of hosts in a cluster in order to perform failure percentage-based ejection. * If the total number of hosts in the cluster is less than this value, failure percentage-based * ejection will not be performed. Defaults to 5. */ - 'failure_percentage_minimum_hosts'?: (_google_protobuf_UInt32Value); + 'failure_percentage_minimum_hosts'?: (_google_protobuf_UInt32Value | null); /** * The minimum number of total requests that must be collected in one interval (as defined by the * interval duration above) to perform failure percentage-based ejection for this host. If the * volume is lower than this setting, failure percentage-based ejection will not be performed for * this host. Defaults to 50. */ - 'failure_percentage_request_volume'?: (_google_protobuf_UInt32Value); + 'failure_percentage_request_volume'?: (_google_protobuf_UInt32Value | null); + /** + * The maximum time that a host is ejected for. See :ref:`base_ejection_time` + * for more information. If not specified, the default value (300000ms or 300s) or + * :ref:`base_ejection_time` value is applied, whatever is larger. + */ + 'max_ejection_time'?: (_google_protobuf_Duration | null); } /** * See the :ref:`architecture overview ` for * more information on outlier detection. - * [#next-free-field: 21] + * [#next-free-field: 22] */ export interface OutlierDetection__Output { /** @@ -162,43 +169,44 @@ export interface OutlierDetection__Output { * to 5xx error codes before a consecutive 5xx ejection * occurs. Defaults to 5. */ - 'consecutive_5xx'?: (_google_protobuf_UInt32Value__Output); + 'consecutive_5xx': (_google_protobuf_UInt32Value__Output | null); /** * The time interval between ejection analysis sweeps. This can result in * both new ejections as well as hosts being returned to service. Defaults * to 10000ms or 10s. */ - 'interval'?: (_google_protobuf_Duration__Output); + 'interval': (_google_protobuf_Duration__Output | null); /** * The base time that a host is ejected for. The real time is equal to the - * base time multiplied by the number of times the host has been ejected. + * base time multiplied by the number of times the host has been ejected and is + * capped by :ref:`max_ejection_time`. * Defaults to 30000ms or 30s. */ - 'base_ejection_time'?: (_google_protobuf_Duration__Output); + 'base_ejection_time': (_google_protobuf_Duration__Output | null); /** * The maximum % of an upstream cluster that can be ejected due to outlier * detection. Defaults to 10% but will eject at least one host regardless of the value. */ - 'max_ejection_percent'?: (_google_protobuf_UInt32Value__Output); + 'max_ejection_percent': (_google_protobuf_UInt32Value__Output | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through consecutive 5xx. This setting can be used to disable * ejection or to ramp it up slowly. Defaults to 100. */ - 'enforcing_consecutive_5xx'?: (_google_protobuf_UInt32Value__Output); + 'enforcing_consecutive_5xx': (_google_protobuf_UInt32Value__Output | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through success rate statistics. This setting can be used to * disable ejection or to ramp it up slowly. Defaults to 100. */ - 'enforcing_success_rate'?: (_google_protobuf_UInt32Value__Output); + 'enforcing_success_rate': (_google_protobuf_UInt32Value__Output | null); /** * The number of hosts in a cluster that must have enough request volume to * detect success rate outliers. If the number of hosts is less than this * setting, outlier detection via success rate statistics is not performed * for any host in the cluster. Defaults to 5. */ - 'success_rate_minimum_hosts'?: (_google_protobuf_UInt32Value__Output); + 'success_rate_minimum_hosts': (_google_protobuf_UInt32Value__Output | null); /** * The minimum number of total requests that must be collected in one * interval (as defined by the interval duration above) to include this host @@ -206,7 +214,7 @@ export interface OutlierDetection__Output { * setting, outlier detection via success rate statistics is not performed * for that host. Defaults to 100. */ - 'success_rate_request_volume'?: (_google_protobuf_UInt32Value__Output); + 'success_rate_request_volume': (_google_protobuf_UInt32Value__Output | null); /** * This factor is used to determine the ejection threshold for success rate * outlier ejection. The ejection threshold is the difference between the @@ -216,59 +224,59 @@ export interface OutlierDetection__Output { * double. That is, if the desired factor is 1.9, the runtime value should * be 1900. Defaults to 1900. */ - 'success_rate_stdev_factor'?: (_google_protobuf_UInt32Value__Output); + 'success_rate_stdev_factor': (_google_protobuf_UInt32Value__Output | null); /** * The number of consecutive gateway failures (502, 503, 504 status codes) * before a consecutive gateway failure ejection occurs. Defaults to 5. */ - 'consecutive_gateway_failure'?: (_google_protobuf_UInt32Value__Output); + 'consecutive_gateway_failure': (_google_protobuf_UInt32Value__Output | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through consecutive gateway failures. This setting can be * used to disable ejection or to ramp it up slowly. Defaults to 0. */ - 'enforcing_consecutive_gateway_failure'?: (_google_protobuf_UInt32Value__Output); + 'enforcing_consecutive_gateway_failure': (_google_protobuf_UInt32Value__Output | null); /** * Determines whether to distinguish local origin failures from external errors. If set to true * the following configuration parameters are taken into account: - * :ref:`consecutive_local_origin_failure`, - * :ref:`enforcing_consecutive_local_origin_failure` + * :ref:`consecutive_local_origin_failure`, + * :ref:`enforcing_consecutive_local_origin_failure` * and - * :ref:`enforcing_local_origin_success_rate`. + * :ref:`enforcing_local_origin_success_rate`. * Defaults to false. */ 'split_external_local_origin_errors': (boolean); /** * The number of consecutive locally originated failures before ejection * occurs. Defaults to 5. Parameter takes effect only when - * :ref:`split_external_local_origin_errors` + * :ref:`split_external_local_origin_errors` * is set to true. */ - 'consecutive_local_origin_failure'?: (_google_protobuf_UInt32Value__Output); + 'consecutive_local_origin_failure': (_google_protobuf_UInt32Value__Output | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through consecutive locally originated failures. This setting can be * used to disable ejection or to ramp it up slowly. Defaults to 100. * Parameter takes effect only when - * :ref:`split_external_local_origin_errors` + * :ref:`split_external_local_origin_errors` * is set to true. */ - 'enforcing_consecutive_local_origin_failure'?: (_google_protobuf_UInt32Value__Output); + 'enforcing_consecutive_local_origin_failure': (_google_protobuf_UInt32Value__Output | null); /** * The % chance that a host will be actually ejected when an outlier status * is detected through success rate statistics for locally originated errors. * This setting can be used to disable ejection or to ramp it up slowly. Defaults to 100. * Parameter takes effect only when - * :ref:`split_external_local_origin_errors` + * :ref:`split_external_local_origin_errors` * is set to true. */ - 'enforcing_local_origin_success_rate'?: (_google_protobuf_UInt32Value__Output); + 'enforcing_local_origin_success_rate': (_google_protobuf_UInt32Value__Output | null); /** * The failure percentage to use when determining failure percentage-based outlier detection. If * the failure percentage of a given host is greater than or equal to this value, it will be * ejected. Defaults to 85. */ - 'failure_percentage_threshold'?: (_google_protobuf_UInt32Value__Output); + 'failure_percentage_threshold': (_google_protobuf_UInt32Value__Output | null); /** * The % chance that a host will be actually ejected when an outlier status is detected through * failure percentage statistics. This setting can be used to disable ejection or to ramp it up @@ -277,24 +285,30 @@ export interface OutlierDetection__Output { * [#next-major-version: setting this without setting failure_percentage_threshold should be * invalid in v4.] */ - 'enforcing_failure_percentage'?: (_google_protobuf_UInt32Value__Output); + 'enforcing_failure_percentage': (_google_protobuf_UInt32Value__Output | null); /** * The % chance that a host will be actually ejected when an outlier status is detected through * local-origin failure percentage statistics. This setting can be used to disable ejection or to * ramp it up slowly. Defaults to 0. */ - 'enforcing_failure_percentage_local_origin'?: (_google_protobuf_UInt32Value__Output); + 'enforcing_failure_percentage_local_origin': (_google_protobuf_UInt32Value__Output | null); /** * The minimum number of hosts in a cluster in order to perform failure percentage-based ejection. * If the total number of hosts in the cluster is less than this value, failure percentage-based * ejection will not be performed. Defaults to 5. */ - 'failure_percentage_minimum_hosts'?: (_google_protobuf_UInt32Value__Output); + 'failure_percentage_minimum_hosts': (_google_protobuf_UInt32Value__Output | null); /** * The minimum number of total requests that must be collected in one interval (as defined by the * interval duration above) to perform failure percentage-based ejection for this host. If the * volume is lower than this setting, failure percentage-based ejection will not be performed for * this host. Defaults to 50. */ - 'failure_percentage_request_volume'?: (_google_protobuf_UInt32Value__Output); + 'failure_percentage_request_volume': (_google_protobuf_UInt32Value__Output | null); + /** + * The maximum time that a host is ejected for. See :ref:`base_ejection_time` + * for more information. If not specified, the default value (300000ms or 300s) or + * :ref:`base_ejection_time` value is applied, whatever is larger. + */ + 'max_ejection_time': (_google_protobuf_Duration__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/TrackClusterStats.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/TrackClusterStats.ts new file mode 100644 index 000000000..a65d1fd8d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/TrackClusterStats.ts @@ -0,0 +1,36 @@ +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + + +export interface TrackClusterStats { + /** + * If timeout_budgets is true, the :ref:`timeout budget histograms + * ` will be published for each + * request. These show what percentage of a request's per try and global timeout was used. A value + * of 0 would indicate that none of the timeout was used or that the timeout was infinite. A value + * of 100 would indicate that the request took the entirety of the timeout given to it. + */ + 'timeout_budgets'?: (boolean); + /** + * If request_response_sizes is true, then the :ref:`histograms + * ` tracking header and body sizes + * of requests and responses will be published. + */ + 'request_response_sizes'?: (boolean); +} + +export interface TrackClusterStats__Output { + /** + * If timeout_budgets is true, the :ref:`timeout budget histograms + * ` will be published for each + * request. These show what percentage of a request's per try and global timeout was used. A value + * of 0 would indicate that none of the timeout was used or that the timeout was infinite. A value + * of 100 would indicate that the request took the entirety of the timeout given to it. + */ + 'timeout_budgets': (boolean); + /** + * If request_response_sizes is true, then the :ref:`histograms + * ` tracking header and body sizes + * of requests and responses will be published. + */ + 'request_response_sizes': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/UpstreamBindConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/UpstreamBindConfig.ts similarity index 58% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/UpstreamBindConfig.ts rename to packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/UpstreamBindConfig.ts index 966ccca85..f2dbd0608 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/UpstreamBindConfig.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/UpstreamBindConfig.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/cluster.proto +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto -import type { Address as _envoy_api_v2_core_Address, Address__Output as _envoy_api_v2_core_Address__Output } from '../../../envoy/api/v2/core/Address'; +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; /** * An extensible structure containing the address Envoy should bind to when @@ -10,7 +10,7 @@ export interface UpstreamBindConfig { /** * The address Envoy should bind to when establishing upstream connections. */ - 'source_address'?: (_envoy_api_v2_core_Address); + 'source_address'?: (_envoy_config_core_v3_Address | null); } /** @@ -21,5 +21,5 @@ export interface UpstreamBindConfig__Output { /** * The address Envoy should bind to when establishing upstream connections. */ - 'source_address'?: (_envoy_api_v2_core_Address__Output); + 'source_address': (_envoy_config_core_v3_Address__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/UpstreamConnectionOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/UpstreamConnectionOptions.ts new file mode 100644 index 000000000..483d1072d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/cluster/v3/UpstreamConnectionOptions.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/config/cluster/v3/cluster.proto + +import type { TcpKeepalive as _envoy_config_core_v3_TcpKeepalive, TcpKeepalive__Output as _envoy_config_core_v3_TcpKeepalive__Output } from '../../../../envoy/config/core/v3/TcpKeepalive'; + +export interface UpstreamConnectionOptions { + /** + * If set then set SO_KEEPALIVE on the socket to enable TCP Keepalives. + */ + 'tcp_keepalive'?: (_envoy_config_core_v3_TcpKeepalive | null); +} + +export interface UpstreamConnectionOptions__Output { + /** + * If set then set SO_KEEPALIVE on the socket to enable TCP Keepalives. + */ + 'tcp_keepalive': (_envoy_config_core_v3_TcpKeepalive__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Address.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Address.ts new file mode 100644 index 000000000..32c483344 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Address.ts @@ -0,0 +1,35 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto + +import type { SocketAddress as _envoy_config_core_v3_SocketAddress, SocketAddress__Output as _envoy_config_core_v3_SocketAddress__Output } from '../../../../envoy/config/core/v3/SocketAddress'; +import type { Pipe as _envoy_config_core_v3_Pipe, Pipe__Output as _envoy_config_core_v3_Pipe__Output } from '../../../../envoy/config/core/v3/Pipe'; +import type { EnvoyInternalAddress as _envoy_config_core_v3_EnvoyInternalAddress, EnvoyInternalAddress__Output as _envoy_config_core_v3_EnvoyInternalAddress__Output } from '../../../../envoy/config/core/v3/EnvoyInternalAddress'; + +/** + * Addresses specify either a logical or physical address and port, which are + * used to tell Envoy where to bind/listen, connect to upstream and find + * management servers. + */ +export interface Address { + 'socket_address'?: (_envoy_config_core_v3_SocketAddress | null); + 'pipe'?: (_envoy_config_core_v3_Pipe | null); + /** + * [#not-implemented-hide:] + */ + 'envoy_internal_address'?: (_envoy_config_core_v3_EnvoyInternalAddress | null); + 'address'?: "socket_address"|"pipe"|"envoy_internal_address"; +} + +/** + * Addresses specify either a logical or physical address and port, which are + * used to tell Envoy where to bind/listen, connect to upstream and find + * management servers. + */ +export interface Address__Output { + 'socket_address'?: (_envoy_config_core_v3_SocketAddress__Output | null); + 'pipe'?: (_envoy_config_core_v3_Pipe__Output | null); + /** + * [#not-implemented-hide:] + */ + 'envoy_internal_address'?: (_envoy_config_core_v3_EnvoyInternalAddress__Output | null); + 'address': "socket_address"|"pipe"|"envoy_internal_address"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/AggregatedConfigSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AggregatedConfigSource.ts similarity index 57% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/AggregatedConfigSource.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/AggregatedConfigSource.ts index 6837dd0db..428ab4b56 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/AggregatedConfigSource.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AggregatedConfigSource.ts @@ -1,9 +1,9 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/config_source.proto +// Original file: deps/envoy-api/envoy/config/core/v3/config_source.proto /** * Aggregated Discovery Service (ADS) options. This is currently empty, but when - * set in :ref:`ConfigSource ` can be used to + * set in :ref:`ConfigSource ` can be used to * specify that ADS is to be used. */ export interface AggregatedConfigSource { @@ -11,7 +11,7 @@ export interface AggregatedConfigSource { /** * Aggregated Discovery Service (ADS) options. This is currently empty, but when - * set in :ref:`ConfigSource ` can be used to + * set in :ref:`ConfigSource ` can be used to * specify that ADS is to be used. */ export interface AggregatedConfigSource__Output { diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AlternateProtocolsCacheOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AlternateProtocolsCacheOptions.ts new file mode 100644 index 000000000..6fb167174 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AlternateProtocolsCacheOptions.ts @@ -0,0 +1,72 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +/** + * Configures the alternate protocols cache which tracks alternate protocols that can be used to + * make an HTTP connection to an origin server. See https://tools.ietf.org/html/rfc7838 for + * HTTP Alternative Services and https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-04 + * for the "HTTPS" DNS resource record. + */ +export interface AlternateProtocolsCacheOptions { + /** + * The name of the cache. Multiple named caches allow independent alternate protocols cache + * configurations to operate within a single Envoy process using different configurations. All + * alternate protocols cache options with the same name *must* be equal in all fields when + * referenced from different configuration components. Configuration will fail to load if this is + * not the case. + */ + 'name'?: (string); + /** + * The maximum number of entries that the cache will hold. If not specified defaults to 1024. + * + * .. note: + * + * The implementation is approximate and enforced independently on each worker thread, thus + * it is possible for the maximum entries in the cache to go slightly above the configured + * value depending on timing. This is similar to how other circuit breakers work. + */ + 'max_entries'?: (_google_protobuf_UInt32Value | null); + /** + * Allows configuring a persistent + * :ref:`key value store ` to flush + * alternate protocols entries to disk. + * This function is currently only supported if concurrency is 1 + */ + 'key_value_store_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); +} + +/** + * Configures the alternate protocols cache which tracks alternate protocols that can be used to + * make an HTTP connection to an origin server. See https://tools.ietf.org/html/rfc7838 for + * HTTP Alternative Services and https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-04 + * for the "HTTPS" DNS resource record. + */ +export interface AlternateProtocolsCacheOptions__Output { + /** + * The name of the cache. Multiple named caches allow independent alternate protocols cache + * configurations to operate within a single Envoy process using different configurations. All + * alternate protocols cache options with the same name *must* be equal in all fields when + * referenced from different configuration components. Configuration will fail to load if this is + * not the case. + */ + 'name': (string); + /** + * The maximum number of entries that the cache will hold. If not specified defaults to 1024. + * + * .. note: + * + * The implementation is approximate and enforced independently on each worker thread, thus + * it is possible for the maximum entries in the cache to go slightly above the configured + * value depending on timing. This is similar to how other circuit breakers work. + */ + 'max_entries': (_google_protobuf_UInt32Value__Output | null); + /** + * Allows configuring a persistent + * :ref:`key value store ` to flush + * alternate protocols entries to disk. + * This function is currently only supported if concurrency is 1 + */ + 'key_value_store_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ApiConfigSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ApiConfigSource.ts similarity index 62% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/ApiConfigSource.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/ApiConfigSource.ts index a99924d9b..b303a08d8 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ApiConfigSource.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ApiConfigSource.ts @@ -1,21 +1,21 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/config_source.proto +// Original file: deps/envoy-api/envoy/config/core/v3/config_source.proto import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; -import type { GrpcService as _envoy_api_v2_core_GrpcService, GrpcService__Output as _envoy_api_v2_core_GrpcService__Output } from '../../../../envoy/api/v2/core/GrpcService'; -import type { RateLimitSettings as _envoy_api_v2_core_RateLimitSettings, RateLimitSettings__Output as _envoy_api_v2_core_RateLimitSettings__Output } from '../../../../envoy/api/v2/core/RateLimitSettings'; -import type { ApiVersion as _envoy_api_v2_core_ApiVersion } from '../../../../envoy/api/v2/core/ApiVersion'; +import type { GrpcService as _envoy_config_core_v3_GrpcService, GrpcService__Output as _envoy_config_core_v3_GrpcService__Output } from '../../../../envoy/config/core/v3/GrpcService'; +import type { RateLimitSettings as _envoy_config_core_v3_RateLimitSettings, RateLimitSettings__Output as _envoy_config_core_v3_RateLimitSettings__Output } from '../../../../envoy/config/core/v3/RateLimitSettings'; +import type { ApiVersion as _envoy_config_core_v3_ApiVersion } from '../../../../envoy/config/core/v3/ApiVersion'; -// Original file: deps/envoy-api/envoy/api/v2/core/config_source.proto +// Original file: deps/envoy-api/envoy/config/core/v3/config_source.proto /** * APIs may be fetched via either REST or gRPC. */ -export enum _envoy_api_v2_core_ApiConfigSource_ApiType { +export enum _envoy_config_core_v3_ApiConfigSource_ApiType { /** * Ideally this would be 'reserved 0' but one can't reserve the default * value. Instead we throw an exception if this is ever used. */ - UNSUPPORTED_REST_LEGACY = 0, + DEPRECATED_AND_UNAVAILABLE_DO_NOT_USE = 0, /** * REST-JSON v2 API. The `canonical JSON encoding * `_ for @@ -23,7 +23,7 @@ export enum _envoy_api_v2_core_ApiConfigSource_ApiType { */ REST = 1, /** - * gRPC v2 API. + * SotW gRPC service. */ GRPC = 2, /** @@ -32,6 +32,18 @@ export enum _envoy_api_v2_core_ApiConfigSource_ApiType { * with every update, the xDS server only sends what has changed since the last update. */ DELTA_GRPC = 3, + /** + * SotW xDS gRPC with ADS. All resources which resolve to this configuration source will be + * multiplexed on a single connection to an ADS endpoint. + * [#not-implemented-hide:] + */ + AGGREGATED_GRPC = 5, + /** + * Delta xDS gRPC with ADS. All resources which resolve to this configuration source will be + * multiplexed on a single connection to an ADS endpoint. + * [#not-implemented-hide:] + */ + AGGREGATED_DELTA_GRPC = 6, } /** @@ -43,7 +55,7 @@ export interface ApiConfigSource { /** * API type (gRPC, REST, delta gRPC) */ - 'api_type'?: (_envoy_api_v2_core_ApiConfigSource_ApiType | keyof typeof _envoy_api_v2_core_ApiConfigSource_ApiType); + 'api_type'?: (_envoy_config_core_v3_ApiConfigSource_ApiType | keyof typeof _envoy_config_core_v3_ApiConfigSource_ApiType); /** * Cluster names should be used only with REST. If > 1 * cluster is defined, clusters will be cycled through if any kind of failure @@ -58,21 +70,21 @@ export interface ApiConfigSource { /** * For REST APIs, the delay between successive polls. */ - 'refresh_delay'?: (_google_protobuf_Duration); + 'refresh_delay'?: (_google_protobuf_Duration | null); /** * Multiple gRPC services be provided for GRPC. If > 1 cluster is defined, * services will be cycled through if any kind of failure occurs. */ - 'grpc_services'?: (_envoy_api_v2_core_GrpcService)[]; + 'grpc_services'?: (_envoy_config_core_v3_GrpcService)[]; /** * For REST APIs, the request timeout. If not set, a default value of 1s will be used. */ - 'request_timeout'?: (_google_protobuf_Duration); + 'request_timeout'?: (_google_protobuf_Duration | null); /** * For GRPC APIs, the rate limit settings. If present, discovery requests made by Envoy will be * rate limited. */ - 'rate_limit_settings'?: (_envoy_api_v2_core_RateLimitSettings); + 'rate_limit_settings'?: (_envoy_config_core_v3_RateLimitSettings | null); /** * Skip the node identifier in subsequent discovery requests for streaming gRPC config types. */ @@ -81,7 +93,7 @@ export interface ApiConfigSource { * API version for xDS transport protocol. This describes the xDS gRPC/REST * endpoint and version of [Delta]DiscoveryRequest/Response used on the wire. */ - 'transport_api_version'?: (_envoy_api_v2_core_ApiVersion | keyof typeof _envoy_api_v2_core_ApiVersion); + 'transport_api_version'?: (_envoy_config_core_v3_ApiVersion | keyof typeof _envoy_config_core_v3_ApiVersion); } /** @@ -93,7 +105,7 @@ export interface ApiConfigSource__Output { /** * API type (gRPC, REST, delta gRPC) */ - 'api_type': (keyof typeof _envoy_api_v2_core_ApiConfigSource_ApiType); + 'api_type': (keyof typeof _envoy_config_core_v3_ApiConfigSource_ApiType); /** * Cluster names should be used only with REST. If > 1 * cluster is defined, clusters will be cycled through if any kind of failure @@ -108,21 +120,21 @@ export interface ApiConfigSource__Output { /** * For REST APIs, the delay between successive polls. */ - 'refresh_delay'?: (_google_protobuf_Duration__Output); + 'refresh_delay': (_google_protobuf_Duration__Output | null); /** * Multiple gRPC services be provided for GRPC. If > 1 cluster is defined, * services will be cycled through if any kind of failure occurs. */ - 'grpc_services': (_envoy_api_v2_core_GrpcService__Output)[]; + 'grpc_services': (_envoy_config_core_v3_GrpcService__Output)[]; /** * For REST APIs, the request timeout. If not set, a default value of 1s will be used. */ - 'request_timeout'?: (_google_protobuf_Duration__Output); + 'request_timeout': (_google_protobuf_Duration__Output | null); /** * For GRPC APIs, the rate limit settings. If present, discovery requests made by Envoy will be * rate limited. */ - 'rate_limit_settings'?: (_envoy_api_v2_core_RateLimitSettings__Output); + 'rate_limit_settings': (_envoy_config_core_v3_RateLimitSettings__Output | null); /** * Skip the node identifier in subsequent discovery requests for streaming gRPC config types. */ @@ -131,5 +143,5 @@ export interface ApiConfigSource__Output { * API version for xDS transport protocol. This describes the xDS gRPC/REST * endpoint and version of [Delta]DiscoveryRequest/Response used on the wire. */ - 'transport_api_version': (keyof typeof _envoy_api_v2_core_ApiVersion); + 'transport_api_version': (keyof typeof _envoy_config_core_v3_ApiVersion); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ApiVersion.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ApiVersion.ts similarity index 69% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/ApiVersion.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/ApiVersion.ts index 7f03a5995..b46f6ec43 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ApiVersion.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ApiVersion.ts @@ -1,7 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/config_source.proto +// Original file: deps/envoy-api/envoy/config/core/v3/config_source.proto /** - * xDS API version. This is used to describe both resource and transport + * xDS API and non-xDS services version. This is used to describe both resource and transport * protocol versions (in distinct configuration fields). */ export enum ApiVersion { diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AsyncDataSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AsyncDataSource.ts new file mode 100644 index 000000000..aa152155b --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/AsyncDataSource.ts @@ -0,0 +1,34 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../envoy/config/core/v3/DataSource'; +import type { RemoteDataSource as _envoy_config_core_v3_RemoteDataSource, RemoteDataSource__Output as _envoy_config_core_v3_RemoteDataSource__Output } from '../../../../envoy/config/core/v3/RemoteDataSource'; + +/** + * Async data source which support async data fetch. + */ +export interface AsyncDataSource { + /** + * Local async data source. + */ + 'local'?: (_envoy_config_core_v3_DataSource | null); + /** + * Remote async data source. + */ + 'remote'?: (_envoy_config_core_v3_RemoteDataSource | null); + 'specifier'?: "local"|"remote"; +} + +/** + * Async data source which support async data fetch. + */ +export interface AsyncDataSource__Output { + /** + * Local async data source. + */ + 'local'?: (_envoy_config_core_v3_DataSource__Output | null); + /** + * Remote async data source. + */ + 'remote'?: (_envoy_config_core_v3_RemoteDataSource__Output | null); + 'specifier': "local"|"remote"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/BackoffStrategy.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/BackoffStrategy.ts similarity index 58% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/BackoffStrategy.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/BackoffStrategy.ts index 48f9d904d..1049dec0c 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/BackoffStrategy.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/BackoffStrategy.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/backoff.proto +// Original file: deps/envoy-api/envoy/config/core/v3/backoff.proto import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; @@ -9,17 +9,17 @@ export interface BackoffStrategy { /** * The base interval to be used for the next back off computation. It should * be greater than zero and less than or equal to :ref:`max_interval - * `. + * `. */ - 'base_interval'?: (_google_protobuf_Duration); + 'base_interval'?: (_google_protobuf_Duration | null); /** * Specifies the maximum interval between retries. This parameter is optional, * but must be greater than or equal to the :ref:`base_interval - * ` if set. The default + * ` if set. The default * is 10 times the :ref:`base_interval - * `. + * `. */ - 'max_interval'?: (_google_protobuf_Duration); + 'max_interval'?: (_google_protobuf_Duration | null); } /** @@ -29,15 +29,15 @@ export interface BackoffStrategy__Output { /** * The base interval to be used for the next back off computation. It should * be greater than zero and less than or equal to :ref:`max_interval - * `. + * `. */ - 'base_interval'?: (_google_protobuf_Duration__Output); + 'base_interval': (_google_protobuf_Duration__Output | null); /** * Specifies the maximum interval between retries. This parameter is optional, * but must be greater than or equal to the :ref:`base_interval - * ` if set. The default + * ` if set. The default * is 10 times the :ref:`base_interval - * `. + * `. */ - 'max_interval'?: (_google_protobuf_Duration__Output); + 'max_interval': (_google_protobuf_Duration__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/BindConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/BindConfig.ts similarity index 58% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/BindConfig.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/BindConfig.ts index f989494ea..d3b2cc584 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/BindConfig.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/BindConfig.ts @@ -1,49 +1,49 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/address.proto +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto -import type { SocketAddress as _envoy_api_v2_core_SocketAddress, SocketAddress__Output as _envoy_api_v2_core_SocketAddress__Output } from '../../../../envoy/api/v2/core/SocketAddress'; +import type { SocketAddress as _envoy_config_core_v3_SocketAddress, SocketAddress__Output as _envoy_config_core_v3_SocketAddress__Output } from '../../../../envoy/config/core/v3/SocketAddress'; import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { SocketOption as _envoy_api_v2_core_SocketOption, SocketOption__Output as _envoy_api_v2_core_SocketOption__Output } from '../../../../envoy/api/v2/core/SocketOption'; +import type { SocketOption as _envoy_config_core_v3_SocketOption, SocketOption__Output as _envoy_config_core_v3_SocketOption__Output } from '../../../../envoy/config/core/v3/SocketOption'; export interface BindConfig { /** * The address to bind to when creating a socket. */ - 'source_address'?: (_envoy_api_v2_core_SocketAddress); + 'source_address'?: (_envoy_config_core_v3_SocketAddress | null); /** * Whether to set the *IP_FREEBIND* option when creating the socket. When this * flag is set to true, allows the :ref:`source_address - * ` to be an IP address + * ` to be an IP address * that is not configured on the system running Envoy. When this flag is set * to false, the option *IP_FREEBIND* is disabled on the socket. When this * flag is not set (default), the socket is not modified, i.e. the option is * neither enabled nor disabled. */ - 'freebind'?: (_google_protobuf_BoolValue); + 'freebind'?: (_google_protobuf_BoolValue | null); /** * Additional socket options that may not be present in Envoy source code or * precompiled binaries. */ - 'socket_options'?: (_envoy_api_v2_core_SocketOption)[]; + 'socket_options'?: (_envoy_config_core_v3_SocketOption)[]; } export interface BindConfig__Output { /** * The address to bind to when creating a socket. */ - 'source_address'?: (_envoy_api_v2_core_SocketAddress__Output); + 'source_address': (_envoy_config_core_v3_SocketAddress__Output | null); /** * Whether to set the *IP_FREEBIND* option when creating the socket. When this * flag is set to true, allows the :ref:`source_address - * ` to be an IP address + * ` to be an IP address * that is not configured on the system running Envoy. When this flag is set * to false, the option *IP_FREEBIND* is disabled on the socket. When this * flag is not set (default), the socket is not modified, i.e. the option is * neither enabled nor disabled. */ - 'freebind'?: (_google_protobuf_BoolValue__Output); + 'freebind': (_google_protobuf_BoolValue__Output | null); /** * Additional socket options that may not be present in Envoy source code or * precompiled binaries. */ - 'socket_options': (_envoy_api_v2_core_SocketOption__Output)[]; + 'socket_options': (_envoy_config_core_v3_SocketOption__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/BuildVersion.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/BuildVersion.ts similarity index 61% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/BuildVersion.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/BuildVersion.ts index 009506fa2..1a86e918e 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/BuildVersion.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/BuildVersion.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto -import type { SemanticVersion as _envoy_type_SemanticVersion, SemanticVersion__Output as _envoy_type_SemanticVersion__Output } from '../../../../envoy/type/SemanticVersion'; +import type { SemanticVersion as _envoy_type_v3_SemanticVersion, SemanticVersion__Output as _envoy_type_v3_SemanticVersion__Output } from '../../../../envoy/type/v3/SemanticVersion'; import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; /** @@ -11,12 +11,12 @@ export interface BuildVersion { /** * SemVer version of extension. */ - 'version'?: (_envoy_type_SemanticVersion); + 'version'?: (_envoy_type_v3_SemanticVersion | null); /** * Free-form build information. - * Envoy defines several well known keys in the source/common/common/version.h file + * Envoy defines several well known keys in the source/common/version/version.h file */ - 'metadata'?: (_google_protobuf_Struct); + 'metadata'?: (_google_protobuf_Struct | null); } /** @@ -27,10 +27,10 @@ export interface BuildVersion__Output { /** * SemVer version of extension. */ - 'version'?: (_envoy_type_SemanticVersion__Output); + 'version': (_envoy_type_v3_SemanticVersion__Output | null); /** * Free-form build information. - * Envoy defines several well known keys in the source/common/common/version.h file + * Envoy defines several well known keys in the source/common/version/version.h file */ - 'metadata'?: (_google_protobuf_Struct__Output); + 'metadata': (_google_protobuf_Struct__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/CidrRange.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/CidrRange.ts similarity index 71% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/CidrRange.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/CidrRange.ts index 00c67734f..4e01fa354 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/CidrRange.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/CidrRange.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/address.proto +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; @@ -12,9 +12,9 @@ export interface CidrRange { */ 'address_prefix'?: (string); /** - * Length of prefix, e.g. 0, 32. + * Length of prefix, e.g. 0, 32. Defaults to 0 when unset. */ - 'prefix_len'?: (_google_protobuf_UInt32Value); + 'prefix_len'?: (_google_protobuf_UInt32Value | null); } /** @@ -27,7 +27,7 @@ export interface CidrRange__Output { */ 'address_prefix': (string); /** - * Length of prefix, e.g. 0, 32. + * Length of prefix, e.g. 0, 32. Defaults to 0 when unset. */ - 'prefix_len'?: (_google_protobuf_UInt32Value__Output); + 'prefix_len': (_google_protobuf_UInt32Value__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ConfigSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ConfigSource.ts similarity index 65% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/ConfigSource.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/ConfigSource.ts index 766af6148..a39c0f077 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ConfigSource.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ConfigSource.ts @@ -1,24 +1,25 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/config_source.proto +// Original file: deps/envoy-api/envoy/config/core/v3/config_source.proto -import type { ApiConfigSource as _envoy_api_v2_core_ApiConfigSource, ApiConfigSource__Output as _envoy_api_v2_core_ApiConfigSource__Output } from '../../../../envoy/api/v2/core/ApiConfigSource'; -import type { AggregatedConfigSource as _envoy_api_v2_core_AggregatedConfigSource, AggregatedConfigSource__Output as _envoy_api_v2_core_AggregatedConfigSource__Output } from '../../../../envoy/api/v2/core/AggregatedConfigSource'; +import type { ApiConfigSource as _envoy_config_core_v3_ApiConfigSource, ApiConfigSource__Output as _envoy_config_core_v3_ApiConfigSource__Output } from '../../../../envoy/config/core/v3/ApiConfigSource'; +import type { AggregatedConfigSource as _envoy_config_core_v3_AggregatedConfigSource, AggregatedConfigSource__Output as _envoy_config_core_v3_AggregatedConfigSource__Output } from '../../../../envoy/config/core/v3/AggregatedConfigSource'; import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; -import type { SelfConfigSource as _envoy_api_v2_core_SelfConfigSource, SelfConfigSource__Output as _envoy_api_v2_core_SelfConfigSource__Output } from '../../../../envoy/api/v2/core/SelfConfigSource'; -import type { ApiVersion as _envoy_api_v2_core_ApiVersion } from '../../../../envoy/api/v2/core/ApiVersion'; +import type { SelfConfigSource as _envoy_config_core_v3_SelfConfigSource, SelfConfigSource__Output as _envoy_config_core_v3_SelfConfigSource__Output } from '../../../../envoy/config/core/v3/SelfConfigSource'; +import type { ApiVersion as _envoy_config_core_v3_ApiVersion } from '../../../../envoy/config/core/v3/ApiVersion'; +import type { Authority as _xds_core_v3_Authority, Authority__Output as _xds_core_v3_Authority__Output } from '../../../../xds/core/v3/Authority'; /** * Configuration for :ref:`listeners `, :ref:`clusters * `, :ref:`routes - * `, :ref:`endpoints + * `, :ref:`endpoints * ` etc. may either be sourced from the * filesystem or from an xDS API source. Filesystem configs are watched with * inotify for updates. - * [#next-free-field: 7] + * [#next-free-field: 8] */ export interface ConfigSource { /** * Path on the filesystem to source and watch for configuration updates. - * When sourcing configuration for :ref:`secret `, + * When sourcing configuration for :ref:`secret `, * the certificate and key files are also watched for updates. * * .. note:: @@ -35,12 +36,12 @@ export interface ConfigSource { /** * API configuration source. */ - 'api_config_source'?: (_envoy_api_v2_core_ApiConfigSource); + 'api_config_source'?: (_envoy_config_core_v3_ApiConfigSource | null); /** * When set, ADS will be used to fetch resources. The ADS API configuration * source in the bootstrap configuration is used. */ - 'ads'?: (_envoy_api_v2_core_AggregatedConfigSource); + 'ads'?: (_envoy_config_core_v3_AggregatedConfigSource | null); /** * When this timeout is specified, Envoy will wait no longer than the specified time for first * config response on this xDS subscription during the :ref:`initialization process @@ -50,12 +51,12 @@ export interface ConfigSource { * means no timeout - Envoy will wait indefinitely for the first xDS config (unless another * timeout applies). The default is 15s. */ - 'initial_fetch_timeout'?: (_google_protobuf_Duration); + 'initial_fetch_timeout'?: (_google_protobuf_Duration | null); /** * [#not-implemented-hide:] * When set, the client will access the resources from the same server it got the * ConfigSource from, although not necessarily from the same stream. This is similar to the - * :ref:`ads` field, except that the client may use a + * :ref:`ads` field, except that the client may use a * different stream to the same server. As a result, this field can be used for things * like LRS that cannot be sent on an ADS stream. It can also be used to link from (e.g.) * LDS to RDS on the same server without requiring the management server to know its name @@ -64,29 +65,36 @@ export interface ConfigSource { * this field can implicitly mean to use the same stream in the case where the ConfigSource * is provided via ADS and the specified data can also be obtained via ADS.] */ - 'self'?: (_envoy_api_v2_core_SelfConfigSource); + 'self'?: (_envoy_config_core_v3_SelfConfigSource | null); /** * API version for xDS resources. This implies the type URLs that the client * will request for resources and the resource type that the client will in * turn expect to be delivered. */ - 'resource_api_version'?: (_envoy_api_v2_core_ApiVersion | keyof typeof _envoy_api_v2_core_ApiVersion); + 'resource_api_version'?: (_envoy_config_core_v3_ApiVersion | keyof typeof _envoy_config_core_v3_ApiVersion); + /** + * Authorities that this config source may be used for. An authority specified in a xdstp:// URL + * is resolved to a *ConfigSource* prior to configuration fetch. This field provides the + * association between authority name and configuration source. + * [#not-implemented-hide:] + */ + 'authorities'?: (_xds_core_v3_Authority)[]; 'config_source_specifier'?: "path"|"api_config_source"|"ads"|"self"; } /** * Configuration for :ref:`listeners `, :ref:`clusters * `, :ref:`routes - * `, :ref:`endpoints + * `, :ref:`endpoints * ` etc. may either be sourced from the * filesystem or from an xDS API source. Filesystem configs are watched with * inotify for updates. - * [#next-free-field: 7] + * [#next-free-field: 8] */ export interface ConfigSource__Output { /** * Path on the filesystem to source and watch for configuration updates. - * When sourcing configuration for :ref:`secret `, + * When sourcing configuration for :ref:`secret `, * the certificate and key files are also watched for updates. * * .. note:: @@ -103,12 +111,12 @@ export interface ConfigSource__Output { /** * API configuration source. */ - 'api_config_source'?: (_envoy_api_v2_core_ApiConfigSource__Output); + 'api_config_source'?: (_envoy_config_core_v3_ApiConfigSource__Output | null); /** * When set, ADS will be used to fetch resources. The ADS API configuration * source in the bootstrap configuration is used. */ - 'ads'?: (_envoy_api_v2_core_AggregatedConfigSource__Output); + 'ads'?: (_envoy_config_core_v3_AggregatedConfigSource__Output | null); /** * When this timeout is specified, Envoy will wait no longer than the specified time for first * config response on this xDS subscription during the :ref:`initialization process @@ -118,12 +126,12 @@ export interface ConfigSource__Output { * means no timeout - Envoy will wait indefinitely for the first xDS config (unless another * timeout applies). The default is 15s. */ - 'initial_fetch_timeout'?: (_google_protobuf_Duration__Output); + 'initial_fetch_timeout': (_google_protobuf_Duration__Output | null); /** * [#not-implemented-hide:] * When set, the client will access the resources from the same server it got the * ConfigSource from, although not necessarily from the same stream. This is similar to the - * :ref:`ads` field, except that the client may use a + * :ref:`ads` field, except that the client may use a * different stream to the same server. As a result, this field can be used for things * like LRS that cannot be sent on an ADS stream. It can also be used to link from (e.g.) * LDS to RDS on the same server without requiring the management server to know its name @@ -132,12 +140,19 @@ export interface ConfigSource__Output { * this field can implicitly mean to use the same stream in the case where the ConfigSource * is provided via ADS and the specified data can also be obtained via ADS.] */ - 'self'?: (_envoy_api_v2_core_SelfConfigSource__Output); + 'self'?: (_envoy_config_core_v3_SelfConfigSource__Output | null); /** * API version for xDS resources. This implies the type URLs that the client * will request for resources and the resource type that the client will in * turn expect to be delivered. */ - 'resource_api_version': (keyof typeof _envoy_api_v2_core_ApiVersion); + 'resource_api_version': (keyof typeof _envoy_config_core_v3_ApiVersion); + /** + * Authorities that this config source may be used for. An authority specified in a xdstp:// URL + * is resolved to a *ConfigSource* prior to configuration fetch. This field provides the + * association between authority name and configuration source. + * [#not-implemented-hide:] + */ + 'authorities': (_xds_core_v3_Authority__Output)[]; 'config_source_specifier': "path"|"api_config_source"|"ads"|"self"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ControlPlane.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ControlPlane.ts similarity index 91% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/ControlPlane.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/ControlPlane.ts index 551f693a2..dc55f8042 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/ControlPlane.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ControlPlane.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/DataSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DataSource.ts similarity index 92% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/DataSource.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/DataSource.ts index a04100054..cc29e084f 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/DataSource.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DataSource.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DnsResolutionConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DnsResolutionConfig.ts new file mode 100644 index 000000000..c87be12e2 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DnsResolutionConfig.ts @@ -0,0 +1,42 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/resolver.proto + +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; +import type { DnsResolverOptions as _envoy_config_core_v3_DnsResolverOptions, DnsResolverOptions__Output as _envoy_config_core_v3_DnsResolverOptions__Output } from '../../../../envoy/config/core/v3/DnsResolverOptions'; + +/** + * DNS resolution configuration which includes the underlying dns resolver addresses and options. + */ +export interface DnsResolutionConfig { + /** + * A list of dns resolver addresses. If specified, the DNS client library will perform resolution + * via the underlying DNS resolvers. Otherwise, the default system resolvers + * (e.g., /etc/resolv.conf) will be used. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple's API only allows overriding DNS resolvers via system settings. + */ + 'resolvers'?: (_envoy_config_core_v3_Address)[]; + /** + * Configuration of DNS resolver option flags which control the behavior of the DNS resolver. + */ + 'dns_resolver_options'?: (_envoy_config_core_v3_DnsResolverOptions | null); +} + +/** + * DNS resolution configuration which includes the underlying dns resolver addresses and options. + */ +export interface DnsResolutionConfig__Output { + /** + * A list of dns resolver addresses. If specified, the DNS client library will perform resolution + * via the underlying DNS resolvers. Otherwise, the default system resolvers + * (e.g., /etc/resolv.conf) will be used. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple's API only allows overriding DNS resolvers via system settings. + */ + 'resolvers': (_envoy_config_core_v3_Address__Output)[]; + /** + * Configuration of DNS resolver option flags which control the behavior of the DNS resolver. + */ + 'dns_resolver_options': (_envoy_config_core_v3_DnsResolverOptions__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DnsResolverOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DnsResolverOptions.ts new file mode 100644 index 000000000..11b68b150 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/DnsResolverOptions.ts @@ -0,0 +1,36 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/resolver.proto + + +/** + * Configuration of DNS resolver option flags which control the behavior of the DNS resolver. + */ +export interface DnsResolverOptions { + /** + * Use TCP for all DNS queries instead of the default protocol UDP. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple's API only uses UDP for DNS resolution. + */ + 'use_tcp_for_dns_lookups'?: (boolean); + /** + * Do not use the default search domains; only query hostnames as-is or as aliases. + */ + 'no_default_search_domain'?: (boolean); +} + +/** + * Configuration of DNS resolver option flags which control the behavior of the DNS resolver. + */ +export interface DnsResolverOptions__Output { + /** + * Use TCP for all DNS queries instead of the default protocol UDP. + * Setting this value causes failure if the + * ``envoy.restart_features.use_apple_api_for_dns_lookups`` runtime value is true during + * server startup. Apple's API only uses UDP for DNS resolution. + */ + 'use_tcp_for_dns_lookups': (boolean); + /** + * Do not use the default search domains; only query hostnames as-is or as aliases. + */ + 'no_default_search_domain': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/EnvoyInternalAddress.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/EnvoyInternalAddress.ts new file mode 100644 index 000000000..936e433db --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/EnvoyInternalAddress.ts @@ -0,0 +1,28 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto + + +/** + * [#not-implemented-hide:] The address represents an envoy internal listener. + * TODO(lambdai): Make this address available for listener and endpoint. + * TODO(asraa): When address available, remove workaround from test/server/server_fuzz_test.cc:30. + */ +export interface EnvoyInternalAddress { + /** + * [#not-implemented-hide:] The :ref:`listener name ` of the destination internal listener. + */ + 'server_listener_name'?: (string); + 'address_name_specifier'?: "server_listener_name"; +} + +/** + * [#not-implemented-hide:] The address represents an envoy internal listener. + * TODO(lambdai): Make this address available for listener and endpoint. + * TODO(asraa): When address available, remove workaround from test/server/server_fuzz_test.cc:30. + */ +export interface EnvoyInternalAddress__Output { + /** + * [#not-implemented-hide:] The :ref:`listener name ` of the destination internal listener. + */ + 'server_listener_name'?: (string); + 'address_name_specifier': "server_listener_name"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/EventServiceConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/EventServiceConfig.ts similarity index 57% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/EventServiceConfig.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/EventServiceConfig.ts index d0637578c..6226b97c8 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/EventServiceConfig.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/EventServiceConfig.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/event_service_config.proto +// Original file: deps/envoy-api/envoy/config/core/v3/event_service_config.proto -import type { GrpcService as _envoy_api_v2_core_GrpcService, GrpcService__Output as _envoy_api_v2_core_GrpcService__Output } from '../../../../envoy/api/v2/core/GrpcService'; +import type { GrpcService as _envoy_config_core_v3_GrpcService, GrpcService__Output as _envoy_config_core_v3_GrpcService__Output } from '../../../../envoy/config/core/v3/GrpcService'; /** * [#not-implemented-hide:] @@ -10,7 +10,7 @@ export interface EventServiceConfig { /** * Specifies the gRPC service that hosts the event reporting service. */ - 'grpc_service'?: (_envoy_api_v2_core_GrpcService); + 'grpc_service'?: (_envoy_config_core_v3_GrpcService | null); 'config_source_specifier'?: "grpc_service"; } @@ -22,6 +22,6 @@ export interface EventServiceConfig__Output { /** * Specifies the gRPC service that hosts the event reporting service. */ - 'grpc_service'?: (_envoy_api_v2_core_GrpcService__Output); + 'grpc_service'?: (_envoy_config_core_v3_GrpcService__Output | null); 'config_source_specifier': "grpc_service"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Extension.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Extension.ts similarity index 87% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/Extension.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/Extension.ts index 418c7a360..5f730bd22 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Extension.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Extension.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto -import type { BuildVersion as _envoy_api_v2_core_BuildVersion, BuildVersion__Output as _envoy_api_v2_core_BuildVersion__Output } from '../../../../envoy/api/v2/core/BuildVersion'; +import type { BuildVersion as _envoy_config_core_v3_BuildVersion, BuildVersion__Output as _envoy_config_core_v3_BuildVersion__Output } from '../../../../envoy/config/core/v3/BuildVersion'; /** * Version and identification for an Envoy extension. @@ -31,7 +31,7 @@ export interface Extension { * of other extensions and the Envoy API. * This field is not set when extension did not provide version information. */ - 'version'?: (_envoy_api_v2_core_BuildVersion); + 'version'?: (_envoy_config_core_v3_BuildVersion | null); /** * Indicates that the extension is present but was disabled via dynamic configuration. */ @@ -67,7 +67,7 @@ export interface Extension__Output { * of other extensions and the Envoy API. * This field is not set when extension did not provide version information. */ - 'version'?: (_envoy_api_v2_core_BuildVersion__Output); + 'version': (_envoy_config_core_v3_BuildVersion__Output | null); /** * Indicates that the extension is present but was disabled via dynamic configuration. */ diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ExtensionConfigSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ExtensionConfigSource.ts new file mode 100644 index 000000000..805762ef5 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ExtensionConfigSource.ts @@ -0,0 +1,72 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/extension.proto + +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../envoy/config/core/v3/ConfigSource'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +/** + * Configuration source specifier for a late-bound extension configuration. The + * parent resource is warmed until all the initial extension configurations are + * received, unless the flag to apply the default configuration is set. + * Subsequent extension updates are atomic on a per-worker basis. Once an + * extension configuration is applied to a request or a connection, it remains + * constant for the duration of processing. If the initial delivery of the + * extension configuration fails, due to a timeout for example, the optional + * default configuration is applied. Without a default configuration, the + * extension is disabled, until an extension configuration is received. The + * behavior of a disabled extension depends on the context. For example, a + * filter chain with a disabled extension filter rejects all incoming streams. + */ +export interface ExtensionConfigSource { + 'config_source'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * Optional default configuration to use as the initial configuration if + * there is a failure to receive the initial extension configuration or if + * `apply_default_config_without_warming` flag is set. + */ + 'default_config'?: (_google_protobuf_Any | null); + /** + * Use the default config as the initial configuration without warming and + * waiting for the first discovery response. Requires the default configuration + * to be supplied. + */ + 'apply_default_config_without_warming'?: (boolean); + /** + * A set of permitted extension type URLs. Extension configuration updates are rejected + * if they do not match any type URL in the set. + */ + 'type_urls'?: (string)[]; +} + +/** + * Configuration source specifier for a late-bound extension configuration. The + * parent resource is warmed until all the initial extension configurations are + * received, unless the flag to apply the default configuration is set. + * Subsequent extension updates are atomic on a per-worker basis. Once an + * extension configuration is applied to a request or a connection, it remains + * constant for the duration of processing. If the initial delivery of the + * extension configuration fails, due to a timeout for example, the optional + * default configuration is applied. Without a default configuration, the + * extension is disabled, until an extension configuration is received. The + * behavior of a disabled extension depends on the context. For example, a + * filter chain with a disabled extension filter rejects all incoming streams. + */ +export interface ExtensionConfigSource__Output { + 'config_source': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * Optional default configuration to use as the initial configuration if + * there is a failure to receive the initial extension configuration or if + * `apply_default_config_without_warming` flag is set. + */ + 'default_config': (_google_protobuf_Any__Output | null); + /** + * Use the default config as the initial configuration without warming and + * waiting for the first discovery response. Requires the default configuration + * to be supplied. + */ + 'apply_default_config_without_warming': (boolean); + /** + * A set of permitted extension type URLs. Extension configuration updates are rejected + * if they do not match any type URL in the set. + */ + 'type_urls': (string)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/GrpcProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/GrpcProtocolOptions.ts new file mode 100644 index 000000000..1f0376a1c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/GrpcProtocolOptions.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + +import type { Http2ProtocolOptions as _envoy_config_core_v3_Http2ProtocolOptions, Http2ProtocolOptions__Output as _envoy_config_core_v3_Http2ProtocolOptions__Output } from '../../../../envoy/config/core/v3/Http2ProtocolOptions'; + +/** + * [#not-implemented-hide:] + */ +export interface GrpcProtocolOptions { + 'http2_protocol_options'?: (_envoy_config_core_v3_Http2ProtocolOptions | null); +} + +/** + * [#not-implemented-hide:] + */ +export interface GrpcProtocolOptions__Output { + 'http2_protocol_options': (_envoy_config_core_v3_Http2ProtocolOptions__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/GrpcService.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/GrpcService.ts similarity index 56% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/GrpcService.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/GrpcService.ts index 3bc894b57..0d81f7340 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/GrpcService.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/GrpcService.ts @@ -1,9 +1,10 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/grpc_service.proto +// Original file: deps/envoy-api/envoy/config/core/v3/grpc_service.proto import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; -import type { HeaderValue as _envoy_api_v2_core_HeaderValue, HeaderValue__Output as _envoy_api_v2_core_HeaderValue__Output } from '../../../../envoy/api/v2/core/HeaderValue'; +import type { HeaderValue as _envoy_config_core_v3_HeaderValue, HeaderValue__Output as _envoy_config_core_v3_HeaderValue__Output } from '../../../../envoy/config/core/v3/HeaderValue'; import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { DataSource as _envoy_api_v2_core_DataSource, DataSource__Output as _envoy_api_v2_core_DataSource__Output } from '../../../../envoy/api/v2/core/DataSource'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../envoy/config/core/v3/DataSource'; import type { Empty as _google_protobuf_Empty, Empty__Output as _google_protobuf_Empty__Output } from '../../../../google/protobuf/Empty'; import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; import type { Long } from '@grpc/proto-loader'; @@ -11,7 +12,7 @@ import type { Long } from '@grpc/proto-loader'; /** * [#next-free-field: 8] */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials { /** * Access token credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#ad3a80da696ffdaea943f0f858d7a360d. @@ -21,7 +22,7 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials { * Google Compute Engine credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a6beb3ac70ff94bd2ebbd89b8f21d1f61 */ - 'google_compute_engine'?: (_google_protobuf_Empty); + 'google_compute_engine'?: (_google_protobuf_Empty | null); /** * Google refresh token credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a96901c997b91bc6513b08491e0dca37c. @@ -31,31 +32,31 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials { * Service Account JWT Access credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a92a9f959d6102461f66ee973d8e9d3aa. */ - 'service_account_jwt_access'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials); + 'service_account_jwt_access'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials | null); /** * Google IAM credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a9fc1fc101b41e680d47028166e76f9d0. */ - 'google_iam'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials); + 'google_iam'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials | null); /** * Custom authenticator credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a823c6a4b19ffc71fb33e90154ee2ad07. * https://grpc.io/docs/guides/auth.html#extending-grpc-to-support-other-authentication-mechanisms. */ - 'from_plugin'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin); + 'from_plugin'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin | null); /** * Custom security token service which implements OAuth 2.0 token exchange. * https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16 * See https://github.com/grpc/grpc/pull/19587. */ - 'sts_service'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_StsService); + 'sts_service'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_StsService | null); 'credential_specifier'?: "access_token"|"google_compute_engine"|"google_refresh_token"|"service_account_jwt_access"|"google_iam"|"from_plugin"|"sts_service"; } /** * [#next-free-field: 8] */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials__Output { /** * Access token credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#ad3a80da696ffdaea943f0f858d7a360d. @@ -65,7 +66,7 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials__Outp * Google Compute Engine credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a6beb3ac70ff94bd2ebbd89b8f21d1f61 */ - 'google_compute_engine'?: (_google_protobuf_Empty__Output); + 'google_compute_engine'?: (_google_protobuf_Empty__Output | null); /** * Google refresh token credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a96901c997b91bc6513b08491e0dca37c. @@ -75,38 +76,58 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials__Outp * Service Account JWT Access credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a92a9f959d6102461f66ee973d8e9d3aa. */ - 'service_account_jwt_access'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials__Output); + 'service_account_jwt_access'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials__Output | null); /** * Google IAM credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a9fc1fc101b41e680d47028166e76f9d0. */ - 'google_iam'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials__Output); + 'google_iam'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials__Output | null); /** * Custom authenticator credentials. * https://grpc.io/grpc/cpp/namespacegrpc.html#a823c6a4b19ffc71fb33e90154ee2ad07. * https://grpc.io/docs/guides/auth.html#extending-grpc-to-support-other-authentication-mechanisms. */ - 'from_plugin'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin__Output); + 'from_plugin'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin__Output | null); /** * Custom security token service which implements OAuth 2.0 token exchange. * https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16 * See https://github.com/grpc/grpc/pull/19587. */ - 'sts_service'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_StsService__Output); + 'sts_service'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_StsService__Output | null); 'credential_specifier': "access_token"|"google_compute_engine"|"google_refresh_token"|"service_account_jwt_access"|"google_iam"|"from_plugin"|"sts_service"; } +/** + * Channel arguments. + */ +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs { + /** + * See grpc_types.h GRPC_ARG #defines for keys that work here. + */ + 'args'?: ({[key: string]: _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs_Value}); +} + +/** + * Channel arguments. + */ +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs__Output { + /** + * See grpc_types.h GRPC_ARG #defines for keys that work here. + */ + 'args': ({[key: string]: _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs_Value__Output}); +} + /** * See https://grpc.io/docs/guides/auth.html#credential-types to understand Channel and Call * credential types. */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_ChannelCredentials { - 'ssl_credentials'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_SslCredentials); +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelCredentials { + 'ssl_credentials'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_SslCredentials | null); /** * https://grpc.io/grpc/cpp/namespacegrpc.html#a6beb3ac70ff94bd2ebbd89b8f21d1f61 */ - 'google_default'?: (_google_protobuf_Empty); - 'local_credentials'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_GoogleLocalCredentials); + 'google_default'?: (_google_protobuf_Empty | null); + 'local_credentials'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_GoogleLocalCredentials | null); 'credential_specifier'?: "ssl_credentials"|"google_default"|"local_credentials"; } @@ -114,50 +135,60 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_ChannelCredentials { * See https://grpc.io/docs/guides/auth.html#credential-types to understand Channel and Call * credential types. */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_ChannelCredentials__Output { - 'ssl_credentials'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_SslCredentials__Output); +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelCredentials__Output { + 'ssl_credentials'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_SslCredentials__Output | null); /** * https://grpc.io/grpc/cpp/namespacegrpc.html#a6beb3ac70ff94bd2ebbd89b8f21d1f61 */ - 'google_default'?: (_google_protobuf_Empty__Output); - 'local_credentials'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_GoogleLocalCredentials__Output); + 'google_default'?: (_google_protobuf_Empty__Output | null); + 'local_credentials'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_GoogleLocalCredentials__Output | null); 'credential_specifier': "ssl_credentials"|"google_default"|"local_credentials"; } -export interface _envoy_api_v2_core_GrpcService_EnvoyGrpc { +export interface _envoy_config_core_v3_GrpcService_EnvoyGrpc { /** * The name of the upstream gRPC cluster. SSL credentials will be supplied - * in the :ref:`Cluster ` :ref:`transport_socket - * `. + * in the :ref:`Cluster ` :ref:`transport_socket + * `. */ 'cluster_name'?: (string); + /** + * The `:authority` header in the grpc request. If this field is not set, the authority header value will be `cluster_name`. + * Note that this authority does not override the SNI. The SNI is provided by the transport socket of the cluster. + */ + 'authority'?: (string); } -export interface _envoy_api_v2_core_GrpcService_EnvoyGrpc__Output { +export interface _envoy_config_core_v3_GrpcService_EnvoyGrpc__Output { /** * The name of the upstream gRPC cluster. SSL credentials will be supplied - * in the :ref:`Cluster ` :ref:`transport_socket - * `. + * in the :ref:`Cluster ` :ref:`transport_socket + * `. */ 'cluster_name': (string); + /** + * The `:authority` header in the grpc request. If this field is not set, the authority header value will be `cluster_name`. + * Note that this authority does not override the SNI. The SNI is provided by the transport socket of the cluster. + */ + 'authority': (string); } /** - * [#next-free-field: 7] + * [#next-free-field: 9] */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc { /** * The target URI when using the `Google C++ gRPC client * `_. SSL credentials will be supplied in - * :ref:`channel_credentials `. + * :ref:`channel_credentials `. */ 'target_uri'?: (string); - 'channel_credentials'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_ChannelCredentials); + 'channel_credentials'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelCredentials | null); /** * A set of call credentials that can be composed with `channel credentials * `_. */ - 'call_credentials'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials)[]; + 'call_credentials'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials)[]; /** * The human readable prefix to use when emitting statistics for the gRPC * service. @@ -180,25 +211,34 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc { * Additional configuration for site-specific customizations of the Google * gRPC library. */ - 'config'?: (_google_protobuf_Struct); + 'config'?: (_google_protobuf_Struct | null); + /** + * How many bytes each stream can buffer internally. + * If not set an implementation defined default is applied (1MiB). + */ + 'per_stream_buffer_limit_bytes'?: (_google_protobuf_UInt32Value | null); + /** + * Custom channels args. + */ + 'channel_args'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs | null); } /** - * [#next-free-field: 7] + * [#next-free-field: 9] */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc__Output { /** * The target URI when using the `Google C++ gRPC client * `_. SSL credentials will be supplied in - * :ref:`channel_credentials `. + * :ref:`channel_credentials `. */ 'target_uri': (string); - 'channel_credentials'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc_ChannelCredentials__Output); + 'channel_credentials': (_envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelCredentials__Output | null); /** * A set of call credentials that can be composed with `channel credentials * `_. */ - 'call_credentials': (_envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials__Output)[]; + 'call_credentials': (_envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials__Output)[]; /** * The human readable prefix to use when emitting statistics for the gRPC * service. @@ -221,15 +261,24 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc__Output { * Additional configuration for site-specific customizations of the Google * gRPC library. */ - 'config'?: (_google_protobuf_Struct__Output); + 'config': (_google_protobuf_Struct__Output | null); + /** + * How many bytes each stream can buffer internally. + * If not set an implementation defined default is applied (1MiB). + */ + 'per_stream_buffer_limit_bytes': (_google_protobuf_UInt32Value__Output | null); + /** + * Custom channels args. + */ + 'channel_args': (_envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs__Output | null); } -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials { 'authorization_token'?: (string); 'authority_selector'?: (string); } -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_GoogleIAMCredentials__Output { 'authorization_token': (string); 'authority_selector': (string); } @@ -238,36 +287,40 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_Googl * Local channel credentials. Only UDS is supported for now. * See https://github.com/grpc/grpc/pull/15909. */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_GoogleLocalCredentials { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_GoogleLocalCredentials { } /** * Local channel credentials. Only UDS is supported for now. * See https://github.com/grpc/grpc/pull/15909. */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_GoogleLocalCredentials__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_GoogleLocalCredentials__Output { } -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin { 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - 'config_type'?: "config"|"typed_config"; + 'typed_config'?: (_google_protobuf_Any | null); + /** + * [#extension-category: envoy.grpc_credentials] + */ + 'config_type'?: "typed_config"; } -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_MetadataCredentialsFromPlugin__Output { 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - 'config_type': "config"|"typed_config"; + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * [#extension-category: envoy.grpc_credentials] + */ + 'config_type': "typed_config"; } -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials { 'json_key'?: (string); 'token_lifetime_seconds'?: (number | string | Long); } -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_ServiceAccountJWTAccessCredentials__Output { 'json_key': (string); 'token_lifetime_seconds': (string); } @@ -275,37 +328,37 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_Servi /** * See https://grpc.io/grpc/cpp/structgrpc_1_1_ssl_credentials_options.html. */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_SslCredentials { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_SslCredentials { /** * PEM encoded server root certificates. */ - 'root_certs'?: (_envoy_api_v2_core_DataSource); + 'root_certs'?: (_envoy_config_core_v3_DataSource | null); /** * PEM encoded client private key. */ - 'private_key'?: (_envoy_api_v2_core_DataSource); + 'private_key'?: (_envoy_config_core_v3_DataSource | null); /** * PEM encoded client certificate chain. */ - 'cert_chain'?: (_envoy_api_v2_core_DataSource); + 'cert_chain'?: (_envoy_config_core_v3_DataSource | null); } /** * See https://grpc.io/grpc/cpp/structgrpc_1_1_ssl_credentials_options.html. */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_SslCredentials__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_SslCredentials__Output { /** * PEM encoded server root certificates. */ - 'root_certs'?: (_envoy_api_v2_core_DataSource__Output); + 'root_certs': (_envoy_config_core_v3_DataSource__Output | null); /** * PEM encoded client private key. */ - 'private_key'?: (_envoy_api_v2_core_DataSource__Output); + 'private_key': (_envoy_config_core_v3_DataSource__Output | null); /** * PEM encoded client certificate chain. */ - 'cert_chain'?: (_envoy_api_v2_core_DataSource__Output); + 'cert_chain': (_envoy_config_core_v3_DataSource__Output | null); } /** @@ -315,7 +368,7 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_SslCredentials__Outpu * https://github.com/grpc/grpc/pull/19587. * [#next-free-field: 10] */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_StsService { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_StsService { /** * URI of the token exchange service that handles token exchange requests. * [#comment:TODO(asraa): Add URI validation when implemented. Tracked by @@ -369,7 +422,7 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_StsSe * https://github.com/grpc/grpc/pull/19587. * [#next-free-field: 10] */ -export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_StsService__Output { +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_CallCredentials_StsService__Output { /** * URI of the token exchange service that handles token exchange requests. * [#comment:TODO(asraa): Add URI validation when implemented. Tracked by @@ -416,9 +469,29 @@ export interface _envoy_api_v2_core_GrpcService_GoogleGrpc_CallCredentials_StsSe 'actor_token_type': (string); } +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs_Value { + 'string_value'?: (string); + 'int_value'?: (number | string | Long); + /** + * Pointer values are not supported, since they don't make any sense when + * delivered via the API. + */ + 'value_specifier'?: "string_value"|"int_value"; +} + +export interface _envoy_config_core_v3_GrpcService_GoogleGrpc_ChannelArgs_Value__Output { + 'string_value'?: (string); + 'int_value'?: (string); + /** + * Pointer values are not supported, since they don't make any sense when + * delivered via the API. + */ + 'value_specifier': "string_value"|"int_value"; +} + /** * gRPC service configuration. This is used by :ref:`ApiConfigSource - * ` and filter configurations. + * ` and filter configurations. * [#next-free-field: 6] */ export interface GrpcService { @@ -427,30 +500,32 @@ export interface GrpcService { * See the :ref:`gRPC services overview ` * documentation for discussion on gRPC client selection. */ - 'envoy_grpc'?: (_envoy_api_v2_core_GrpcService_EnvoyGrpc); + 'envoy_grpc'?: (_envoy_config_core_v3_GrpcService_EnvoyGrpc | null); /** * `Google C++ gRPC client `_ * See the :ref:`gRPC services overview ` * documentation for discussion on gRPC client selection. */ - 'google_grpc'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc); + 'google_grpc'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc | null); /** * The timeout for the gRPC request. This is the timeout for a specific * request. */ - 'timeout'?: (_google_protobuf_Duration); + 'timeout'?: (_google_protobuf_Duration | null); /** - * Additional metadata to include in streams initiated to the GrpcService. - * This can be used for scenarios in which additional ad hoc authorization - * headers (e.g. ``x-foo-bar: baz-key``) are to be injected. + * Additional metadata to include in streams initiated to the GrpcService. This can be used for + * scenarios in which additional ad hoc authorization headers (e.g. ``x-foo-bar: baz-key``) are to + * be injected. For more information, including details on header value syntax, see the + * documentation on :ref:`custom request headers + * `. */ - 'initial_metadata'?: (_envoy_api_v2_core_HeaderValue)[]; + 'initial_metadata'?: (_envoy_config_core_v3_HeaderValue)[]; 'target_specifier'?: "envoy_grpc"|"google_grpc"; } /** * gRPC service configuration. This is used by :ref:`ApiConfigSource - * ` and filter configurations. + * ` and filter configurations. * [#next-free-field: 6] */ export interface GrpcService__Output { @@ -459,23 +534,25 @@ export interface GrpcService__Output { * See the :ref:`gRPC services overview ` * documentation for discussion on gRPC client selection. */ - 'envoy_grpc'?: (_envoy_api_v2_core_GrpcService_EnvoyGrpc__Output); + 'envoy_grpc'?: (_envoy_config_core_v3_GrpcService_EnvoyGrpc__Output | null); /** * `Google C++ gRPC client `_ * See the :ref:`gRPC services overview ` * documentation for discussion on gRPC client selection. */ - 'google_grpc'?: (_envoy_api_v2_core_GrpcService_GoogleGrpc__Output); + 'google_grpc'?: (_envoy_config_core_v3_GrpcService_GoogleGrpc__Output | null); /** * The timeout for the gRPC request. This is the timeout for a specific * request. */ - 'timeout'?: (_google_protobuf_Duration__Output); + 'timeout': (_google_protobuf_Duration__Output | null); /** - * Additional metadata to include in streams initiated to the GrpcService. - * This can be used for scenarios in which additional ad hoc authorization - * headers (e.g. ``x-foo-bar: baz-key``) are to be injected. + * Additional metadata to include in streams initiated to the GrpcService. This can be used for + * scenarios in which additional ad hoc authorization headers (e.g. ``x-foo-bar: baz-key``) are to + * be injected. For more information, including details on header value syntax, see the + * documentation on :ref:`custom request headers + * `. */ - 'initial_metadata': (_envoy_api_v2_core_HeaderValue__Output)[]; + 'initial_metadata': (_envoy_config_core_v3_HeaderValue__Output)[]; 'target_specifier': "envoy_grpc"|"google_grpc"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderMap.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderMap.ts new file mode 100644 index 000000000..3ee496152 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderMap.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + +import type { HeaderValue as _envoy_config_core_v3_HeaderValue, HeaderValue__Output as _envoy_config_core_v3_HeaderValue__Output } from '../../../../envoy/config/core/v3/HeaderValue'; + +/** + * Wrapper for a set of headers. + */ +export interface HeaderMap { + 'headers'?: (_envoy_config_core_v3_HeaderValue)[]; +} + +/** + * Wrapper for a set of headers. + */ +export interface HeaderMap__Output { + 'headers': (_envoy_config_core_v3_HeaderValue__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderValue.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderValue.ts similarity index 92% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderValue.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderValue.ts index b36605324..a9fb6c07a 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HeaderValue.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderValue.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderValueOption.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderValueOption.ts new file mode 100644 index 000000000..7ba7e9d8d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HeaderValueOption.ts @@ -0,0 +1,69 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + +import type { HeaderValue as _envoy_config_core_v3_HeaderValue, HeaderValue__Output as _envoy_config_core_v3_HeaderValue__Output } from '../../../../envoy/config/core/v3/HeaderValue'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; + +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + +/** + * Describes the supported actions types for header append action. + */ +export enum _envoy_config_core_v3_HeaderValueOption_HeaderAppendAction { + /** + * This action will append the specified value to the existing values if the header + * already exists. If the header doesn't exist then this will add the header with + * specified key and value. + */ + APPEND_IF_EXISTS_OR_ADD = 0, + /** + * This action will add the header if it doesn't already exist. If the header + * already exists then this will be a no-op. + */ + ADD_IF_ABSENT = 1, + /** + * This action will overwrite the specified value by discarding any existing values if + * the header already exists. If the header doesn't exist then this will add the header + * with specified key and value. + */ + OVERWRITE_IF_EXISTS_OR_ADD = 2, +} + +/** + * Header name/value pair plus option to control append behavior. + */ +export interface HeaderValueOption { + /** + * Header name/value pair that this option applies to. + */ + 'header'?: (_envoy_config_core_v3_HeaderValue | null); + /** + * Should the value be appended? If true (default), the value is appended to + * existing values. Otherwise it replaces any existing values. + */ + 'append'?: (_google_protobuf_BoolValue | null); + /** + * [#not-implemented-hide:] Describes the action taken to append/overwrite the given value for an existing header + * or to only add this header if it's absent. Value defaults to :ref:`APPEND_IF_EXISTS_OR_ADD`. + */ + 'append_action'?: (_envoy_config_core_v3_HeaderValueOption_HeaderAppendAction | keyof typeof _envoy_config_core_v3_HeaderValueOption_HeaderAppendAction); +} + +/** + * Header name/value pair plus option to control append behavior. + */ +export interface HeaderValueOption__Output { + /** + * Header name/value pair that this option applies to. + */ + 'header': (_envoy_config_core_v3_HeaderValue__Output | null); + /** + * Should the value be appended? If true (default), the value is appended to + * existing values. Otherwise it replaces any existing values. + */ + 'append': (_google_protobuf_BoolValue__Output | null); + /** + * [#not-implemented-hide:] Describes the action taken to append/overwrite the given value for an existing header + * or to only add this header if it's absent. Value defaults to :ref:`APPEND_IF_EXISTS_OR_ADD`. + */ + 'append_action': (keyof typeof _envoy_config_core_v3_HeaderValueOption_HeaderAppendAction); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HealthCheck.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HealthCheck.ts similarity index 55% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/HealthCheck.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/HealthCheck.ts index 0b45042f3..8882de614 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HealthCheck.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HealthCheck.ts @@ -1,49 +1,49 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/health_check.proto +// Original file: deps/envoy-api/envoy/config/core/v3/health_check.proto import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { EventServiceConfig as _envoy_api_v2_core_EventServiceConfig, EventServiceConfig__Output as _envoy_api_v2_core_EventServiceConfig__Output } from '../../../../envoy/api/v2/core/EventServiceConfig'; -import type { HeaderValueOption as _envoy_api_v2_core_HeaderValueOption, HeaderValueOption__Output as _envoy_api_v2_core_HeaderValueOption__Output } from '../../../../envoy/api/v2/core/HeaderValueOption'; -import type { Int64Range as _envoy_type_Int64Range, Int64Range__Output as _envoy_type_Int64Range__Output } from '../../../../envoy/type/Int64Range'; -import type { CodecClientType as _envoy_type_CodecClientType } from '../../../../envoy/type/CodecClientType'; -import type { StringMatcher as _envoy_type_matcher_StringMatcher, StringMatcher__Output as _envoy_type_matcher_StringMatcher__Output } from '../../../../envoy/type/matcher/StringMatcher'; +import type { EventServiceConfig as _envoy_config_core_v3_EventServiceConfig, EventServiceConfig__Output as _envoy_config_core_v3_EventServiceConfig__Output } from '../../../../envoy/config/core/v3/EventServiceConfig'; import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import type { HeaderValueOption as _envoy_config_core_v3_HeaderValueOption, HeaderValueOption__Output as _envoy_config_core_v3_HeaderValueOption__Output } from '../../../../envoy/config/core/v3/HeaderValueOption'; +import type { Int64Range as _envoy_type_v3_Int64Range, Int64Range__Output as _envoy_type_v3_Int64Range__Output } from '../../../../envoy/type/v3/Int64Range'; +import type { CodecClientType as _envoy_type_v3_CodecClientType } from '../../../../envoy/type/v3/CodecClientType'; +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; import type { Long } from '@grpc/proto-loader'; /** * Custom health check. */ -export interface _envoy_api_v2_core_HealthCheck_CustomHealthCheck { +export interface _envoy_config_core_v3_HealthCheck_CustomHealthCheck { /** * The registered name of the custom health checker. */ 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); + 'typed_config'?: (_google_protobuf_Any | null); /** * A custom health checker specific configuration which depends on the custom health checker * being instantiated. See :api:`envoy/config/health_checker` for reference. + * [#extension-category: envoy.health_checkers] */ - 'config_type'?: "config"|"typed_config"; + 'config_type'?: "typed_config"; } /** * Custom health check. */ -export interface _envoy_api_v2_core_HealthCheck_CustomHealthCheck__Output { +export interface _envoy_config_core_v3_HealthCheck_CustomHealthCheck__Output { /** * The registered name of the custom health checker. */ 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); + 'typed_config'?: (_google_protobuf_Any__Output | null); /** * A custom health checker specific configuration which depends on the custom health checker * being instantiated. See :api:`envoy/config/health_checker` for reference. + * [#extension-category: envoy.health_checkers] */ - 'config_type': "config"|"typed_config"; + 'config_type': "typed_config"; } /** @@ -52,7 +52,7 @@ export interface _envoy_api_v2_core_HealthCheck_CustomHealthCheck__Output { * healthcheck. See `gRPC doc `_ * for details. */ -export interface _envoy_api_v2_core_HealthCheck_GrpcHealthCheck { +export interface _envoy_config_core_v3_HealthCheck_GrpcHealthCheck { /** * An optional service name parameter which will be sent to gRPC service in * `grpc.health.v1.HealthCheckRequest @@ -65,7 +65,7 @@ export interface _envoy_api_v2_core_HealthCheck_GrpcHealthCheck { * The value of the :authority header in the gRPC health check request. If * left empty (default value), the name of the cluster this health check is associated * with will be used. The authority header can be customized for a specific endpoint by setting - * the :ref:`hostname ` field. + * the :ref:`hostname ` field. */ 'authority'?: (string); } @@ -76,7 +76,7 @@ export interface _envoy_api_v2_core_HealthCheck_GrpcHealthCheck { * healthcheck. See `gRPC doc `_ * for details. */ -export interface _envoy_api_v2_core_HealthCheck_GrpcHealthCheck__Output { +export interface _envoy_config_core_v3_HealthCheck_GrpcHealthCheck__Output { /** * An optional service name parameter which will be sent to gRPC service in * `grpc.health.v1.HealthCheckRequest @@ -89,20 +89,20 @@ export interface _envoy_api_v2_core_HealthCheck_GrpcHealthCheck__Output { * The value of the :authority header in the gRPC health check request. If * left empty (default value), the name of the cluster this health check is associated * with will be used. The authority header can be customized for a specific endpoint by setting - * the :ref:`hostname ` field. + * the :ref:`hostname ` field. */ 'authority': (string); } /** - * [#next-free-field: 12] + * [#next-free-field: 13] */ -export interface _envoy_api_v2_core_HealthCheck_HttpHealthCheck { +export interface _envoy_config_core_v3_HealthCheck_HttpHealthCheck { /** * The value of the host header in the HTTP health check request. If * left empty (default value), the name of the cluster this health check is associated * with will be used. The host header can be customized for a specific endpoint by setting the - * :ref:`hostname ` field. + * :ref:`hostname ` field. */ 'host'?: (string); /** @@ -113,69 +113,65 @@ export interface _envoy_api_v2_core_HealthCheck_HttpHealthCheck { /** * [#not-implemented-hide:] HTTP specific payload. */ - 'send'?: (_envoy_api_v2_core_HealthCheck_Payload); + 'send'?: (_envoy_config_core_v3_HealthCheck_Payload | null); /** * [#not-implemented-hide:] HTTP specific response. */ - 'receive'?: (_envoy_api_v2_core_HealthCheck_Payload); - /** - * An optional service name parameter which is used to validate the identity of - * the health checked cluster. See the :ref:`architecture overview - * ` for more information. - * - * .. attention:: - * - * This field has been deprecated in favor of `service_name_matcher` for better flexibility - * over matching with service-cluster name. - */ - 'service_name'?: (string); + 'receive'?: (_envoy_config_core_v3_HealthCheck_Payload | null); /** * Specifies a list of HTTP headers that should be added to each request that is sent to the * health checked cluster. For more information, including details on header value syntax, see * the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'request_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Specifies a list of HTTP headers that should be removed from each request that is sent to the * health checked cluster. */ 'request_headers_to_remove'?: (string)[]; - /** - * If set, health checks will be made using http/2. - * Deprecated, use :ref:`codec_client_type - * ` instead. - */ - 'use_http2'?: (boolean); /** * Specifies a list of HTTP response statuses considered healthy. If provided, replaces default * 200-only policy - 200 must be included explicitly as needed. Ranges follow half-open - * semantics of :ref:`Int64Range `. The start and end of each + * semantics of :ref:`Int64Range `. The start and end of each * range are required. Only statuses in the range [100, 600) are allowed. */ - 'expected_statuses'?: (_envoy_type_Int64Range)[]; + 'expected_statuses'?: (_envoy_type_v3_Int64Range)[]; + /** + * Specifies a list of HTTP response statuses considered retriable. If provided, responses in this range + * will count towards the configured :ref:`unhealthy_threshold `, + * but will not result in the host being considered immediately unhealthy. Ranges follow half-open semantics of + * :ref:`Int64Range `. The start and end of each range are required. + * Only statuses in the range [100, 600) are allowed. The :ref:`expected_statuses ` + * field takes precedence for any range overlaps with this field i.e. if status code 200 is both retriable and expected, a 200 response will + * be considered a successful health check. By default all responses not in + * :ref:`expected_statuses ` will result in + * the host being considered immediately unhealthy i.e. if status code 200 is expected and there are no configured retriable statuses, any + * non-200 response will result in the host being marked unhealthy. + */ + 'retriable_statuses'?: (_envoy_type_v3_Int64Range)[]; /** * Use specified application protocol for health checks. */ - 'codec_client_type'?: (_envoy_type_CodecClientType | keyof typeof _envoy_type_CodecClientType); + 'codec_client_type'?: (_envoy_type_v3_CodecClientType | keyof typeof _envoy_type_v3_CodecClientType); /** * An optional service name parameter which is used to validate the identity of * the health checked cluster using a :ref:`StringMatcher - * `. See the :ref:`architecture overview + * `. See the :ref:`architecture overview * ` for more information. */ - 'service_name_matcher'?: (_envoy_type_matcher_StringMatcher); + 'service_name_matcher'?: (_envoy_type_matcher_v3_StringMatcher | null); } /** - * [#next-free-field: 12] + * [#next-free-field: 13] */ -export interface _envoy_api_v2_core_HealthCheck_HttpHealthCheck__Output { +export interface _envoy_config_core_v3_HealthCheck_HttpHealthCheck__Output { /** * The value of the host header in the HTTP health check request. If * left empty (default value), the name of the cluster this health check is associated * with will be used. The host header can be customized for a specific endpoint by setting the - * :ref:`hostname ` field. + * :ref:`hostname ` field. */ 'host': (string); /** @@ -186,64 +182,60 @@ export interface _envoy_api_v2_core_HealthCheck_HttpHealthCheck__Output { /** * [#not-implemented-hide:] HTTP specific payload. */ - 'send'?: (_envoy_api_v2_core_HealthCheck_Payload__Output); + 'send': (_envoy_config_core_v3_HealthCheck_Payload__Output | null); /** * [#not-implemented-hide:] HTTP specific response. */ - 'receive'?: (_envoy_api_v2_core_HealthCheck_Payload__Output); - /** - * An optional service name parameter which is used to validate the identity of - * the health checked cluster. See the :ref:`architecture overview - * ` for more information. - * - * .. attention:: - * - * This field has been deprecated in favor of `service_name_matcher` for better flexibility - * over matching with service-cluster name. - */ - 'service_name': (string); + 'receive': (_envoy_config_core_v3_HealthCheck_Payload__Output | null); /** * Specifies a list of HTTP headers that should be added to each request that is sent to the * health checked cluster. For more information, including details on header value syntax, see * the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'request_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Specifies a list of HTTP headers that should be removed from each request that is sent to the * health checked cluster. */ 'request_headers_to_remove': (string)[]; - /** - * If set, health checks will be made using http/2. - * Deprecated, use :ref:`codec_client_type - * ` instead. - */ - 'use_http2': (boolean); /** * Specifies a list of HTTP response statuses considered healthy. If provided, replaces default * 200-only policy - 200 must be included explicitly as needed. Ranges follow half-open - * semantics of :ref:`Int64Range `. The start and end of each + * semantics of :ref:`Int64Range `. The start and end of each * range are required. Only statuses in the range [100, 600) are allowed. */ - 'expected_statuses': (_envoy_type_Int64Range__Output)[]; + 'expected_statuses': (_envoy_type_v3_Int64Range__Output)[]; + /** + * Specifies a list of HTTP response statuses considered retriable. If provided, responses in this range + * will count towards the configured :ref:`unhealthy_threshold `, + * but will not result in the host being considered immediately unhealthy. Ranges follow half-open semantics of + * :ref:`Int64Range `. The start and end of each range are required. + * Only statuses in the range [100, 600) are allowed. The :ref:`expected_statuses ` + * field takes precedence for any range overlaps with this field i.e. if status code 200 is both retriable and expected, a 200 response will + * be considered a successful health check. By default all responses not in + * :ref:`expected_statuses ` will result in + * the host being considered immediately unhealthy i.e. if status code 200 is expected and there are no configured retriable statuses, any + * non-200 response will result in the host being marked unhealthy. + */ + 'retriable_statuses': (_envoy_type_v3_Int64Range__Output)[]; /** * Use specified application protocol for health checks. */ - 'codec_client_type': (keyof typeof _envoy_type_CodecClientType); + 'codec_client_type': (keyof typeof _envoy_type_v3_CodecClientType); /** * An optional service name parameter which is used to validate the identity of * the health checked cluster using a :ref:`StringMatcher - * `. See the :ref:`architecture overview + * `. See the :ref:`architecture overview * ` for more information. */ - 'service_name_matcher'?: (_envoy_type_matcher_StringMatcher__Output); + 'service_name_matcher': (_envoy_type_matcher_v3_StringMatcher__Output | null); } /** * Describes the encoding of the payload bytes in the payload. */ -export interface _envoy_api_v2_core_HealthCheck_Payload { +export interface _envoy_config_core_v3_HealthCheck_Payload { /** * Hex encoded payload. E.g., "000000FF". */ @@ -258,7 +250,7 @@ export interface _envoy_api_v2_core_HealthCheck_Payload { /** * Describes the encoding of the payload bytes in the payload. */ -export interface _envoy_api_v2_core_HealthCheck_Payload__Output { +export interface _envoy_config_core_v3_HealthCheck_Payload__Output { /** * Hex encoded payload. E.g., "000000FF". */ @@ -270,7 +262,7 @@ export interface _envoy_api_v2_core_HealthCheck_Payload__Output { 'payload': "text"|"binary"; } -export interface _envoy_api_v2_core_HealthCheck_RedisHealthCheck { +export interface _envoy_config_core_v3_HealthCheck_RedisHealthCheck { /** * If set, optionally perform ``EXISTS `` instead of ``PING``. A return value * from Redis of 0 (does not exist) is considered a passing healthcheck. A return value other @@ -280,7 +272,7 @@ export interface _envoy_api_v2_core_HealthCheck_RedisHealthCheck { 'key'?: (string); } -export interface _envoy_api_v2_core_HealthCheck_RedisHealthCheck__Output { +export interface _envoy_config_core_v3_HealthCheck_RedisHealthCheck__Output { /** * If set, optionally perform ``EXISTS `` instead of ``PING``. A return value * from Redis of 0 (does not exist) is considered a passing healthcheck. A return value other @@ -290,30 +282,30 @@ export interface _envoy_api_v2_core_HealthCheck_RedisHealthCheck__Output { 'key': (string); } -export interface _envoy_api_v2_core_HealthCheck_TcpHealthCheck { +export interface _envoy_config_core_v3_HealthCheck_TcpHealthCheck { /** * Empty payloads imply a connect-only health check. */ - 'send'?: (_envoy_api_v2_core_HealthCheck_Payload); + 'send'?: (_envoy_config_core_v3_HealthCheck_Payload | null); /** * When checking the response, “fuzzy” matching is performed such that each * binary block must be found, and in the order specified, but not * necessarily contiguous. */ - 'receive'?: (_envoy_api_v2_core_HealthCheck_Payload)[]; + 'receive'?: (_envoy_config_core_v3_HealthCheck_Payload)[]; } -export interface _envoy_api_v2_core_HealthCheck_TcpHealthCheck__Output { +export interface _envoy_config_core_v3_HealthCheck_TcpHealthCheck__Output { /** * Empty payloads imply a connect-only health check. */ - 'send'?: (_envoy_api_v2_core_HealthCheck_Payload__Output); + 'send': (_envoy_config_core_v3_HealthCheck_Payload__Output | null); /** * When checking the response, “fuzzy” matching is performed such that each * binary block must be found, and in the order specified, but not * necessarily contiguous. */ - 'receive': (_envoy_api_v2_core_HealthCheck_Payload__Output)[]; + 'receive': (_envoy_config_core_v3_HealthCheck_Payload__Output)[]; } /** @@ -322,11 +314,11 @@ export interface _envoy_api_v2_core_HealthCheck_TcpHealthCheck__Output { * * This allows overriding the cluster TLS settings, just for health check connections. */ -export interface _envoy_api_v2_core_HealthCheck_TlsOptions { +export interface _envoy_config_core_v3_HealthCheck_TlsOptions { /** * Specifies the ALPN protocols for health check connections. This is useful if the * corresponding upstream is using ALPN-based :ref:`FilterChainMatch - * ` along with different protocols for health checks + * ` along with different protocols for health checks * versus data connections. If empty, no ALPN protocols will be set on health check connections. */ 'alpn_protocols'?: (string)[]; @@ -338,66 +330,68 @@ export interface _envoy_api_v2_core_HealthCheck_TlsOptions { * * This allows overriding the cluster TLS settings, just for health check connections. */ -export interface _envoy_api_v2_core_HealthCheck_TlsOptions__Output { +export interface _envoy_config_core_v3_HealthCheck_TlsOptions__Output { /** * Specifies the ALPN protocols for health check connections. This is useful if the * corresponding upstream is using ALPN-based :ref:`FilterChainMatch - * ` along with different protocols for health checks + * ` along with different protocols for health checks * versus data connections. If empty, no ALPN protocols will be set on health check connections. */ 'alpn_protocols': (string)[]; } /** - * [#next-free-field: 23] + * [#next-free-field: 25] */ export interface HealthCheck { /** * The time to wait for a health check response. If the timeout is reached the * health check attempt will be considered a failure. */ - 'timeout'?: (_google_protobuf_Duration); + 'timeout'?: (_google_protobuf_Duration | null); /** * The interval between health checks. */ - 'interval'?: (_google_protobuf_Duration); + 'interval'?: (_google_protobuf_Duration | null); /** * An optional jitter amount in milliseconds. If specified, during every * interval Envoy will add interval_jitter to the wait time. */ - 'interval_jitter'?: (_google_protobuf_Duration); + 'interval_jitter'?: (_google_protobuf_Duration | null); /** * The number of unhealthy health checks required before a host is marked - * unhealthy. Note that for *http* health checking if a host responds with 503 - * this threshold is ignored and the host is considered unhealthy immediately. + * unhealthy. Note that for *http* health checking if a host responds with a code not in + * :ref:`expected_statuses ` + * or :ref:`retriable_statuses `, + * this threshold is ignored and the host is considered immediately unhealthy. */ - 'unhealthy_threshold'?: (_google_protobuf_UInt32Value); + 'unhealthy_threshold'?: (_google_protobuf_UInt32Value | null); /** * The number of healthy health checks required before a host is marked * healthy. Note that during startup, only a single successful health check is * required to mark a host healthy. */ - 'healthy_threshold'?: (_google_protobuf_UInt32Value); + 'healthy_threshold'?: (_google_protobuf_UInt32Value | null); /** * [#not-implemented-hide:] Non-serving port for health checking. */ - 'alt_port'?: (_google_protobuf_UInt32Value); + 'alt_port'?: (_google_protobuf_UInt32Value | null); /** * Reuse health check connection between health checks. Default is true. */ - 'reuse_connection'?: (_google_protobuf_BoolValue); + 'reuse_connection'?: (_google_protobuf_BoolValue | null); /** * HTTP health check. */ - 'http_health_check'?: (_envoy_api_v2_core_HealthCheck_HttpHealthCheck); + 'http_health_check'?: (_envoy_config_core_v3_HealthCheck_HttpHealthCheck | null); /** * TCP health check. */ - 'tcp_health_check'?: (_envoy_api_v2_core_HealthCheck_TcpHealthCheck); + 'tcp_health_check'?: (_envoy_config_core_v3_HealthCheck_TcpHealthCheck | null); /** * gRPC health check. */ - 'grpc_health_check'?: (_envoy_api_v2_core_HealthCheck_GrpcHealthCheck); + 'grpc_health_check'?: (_envoy_config_core_v3_HealthCheck_GrpcHealthCheck | null); /** * The "no traffic interval" is a special health check interval that is used when a cluster has * never had traffic routed to it. This lower interval allows cluster information to be kept up to @@ -408,11 +402,11 @@ export interface HealthCheck { * * The default value for "no traffic interval" is 60 seconds. */ - 'no_traffic_interval'?: (_google_protobuf_Duration); + 'no_traffic_interval'?: (_google_protobuf_Duration | null); /** * Custom health check. */ - 'custom_health_check'?: (_envoy_api_v2_core_HealthCheck_CustomHealthCheck); + 'custom_health_check'?: (_envoy_config_core_v3_HealthCheck_CustomHealthCheck | null); /** * The "unhealthy interval" is a health check interval that is used for hosts that are marked as * unhealthy. As soon as the host is marked as healthy, Envoy will shift back to using the @@ -420,7 +414,7 @@ export interface HealthCheck { * * The default value for "unhealthy interval" is the same as "interval". */ - 'unhealthy_interval'?: (_google_protobuf_Duration); + 'unhealthy_interval'?: (_google_protobuf_Duration | null); /** * The "unhealthy edge interval" is a special health check interval that is used for the first * health check right after a host is marked as unhealthy. For subsequent health checks @@ -429,7 +423,7 @@ export interface HealthCheck { * * The default value for "unhealthy edge interval" is the same as "unhealthy interval". */ - 'unhealthy_edge_interval'?: (_google_protobuf_Duration); + 'unhealthy_edge_interval'?: (_google_protobuf_Duration | null); /** * The "healthy edge interval" is a special health check interval that is used for the first * health check right after a host is marked as healthy. For subsequent health checks @@ -437,7 +431,7 @@ export interface HealthCheck { * * The default value for "healthy edge interval" is the same as the default interval. */ - 'healthy_edge_interval'?: (_google_protobuf_Duration); + 'healthy_edge_interval'?: (_google_protobuf_Duration | null); /** * Specifies the path to the :ref:`health check event log `. * If empty, no event log will be written. @@ -463,70 +457,121 @@ export interface HealthCheck { * checking after for a random time in ms between 0 and initial_jitter. This only * applies to the first health check. */ - 'initial_jitter'?: (_google_protobuf_Duration); + 'initial_jitter'?: (_google_protobuf_Duration | null); /** * This allows overriding the cluster TLS settings, just for health check connections. */ - 'tls_options'?: (_envoy_api_v2_core_HealthCheck_TlsOptions); + 'tls_options'?: (_envoy_config_core_v3_HealthCheck_TlsOptions | null); /** * [#not-implemented-hide:] * The gRPC service for the health check event service. * If empty, health check events won't be sent to a remote endpoint. */ - 'event_service'?: (_envoy_api_v2_core_EventServiceConfig); + 'event_service'?: (_envoy_config_core_v3_EventServiceConfig | null); + /** + * Optional key/value pairs that will be used to match a transport socket from those specified in the cluster's + * :ref:`tranport socket matches `. + * For example, the following match criteria + * + * .. code-block:: yaml + * + * transport_socket_match_criteria: + * useMTLS: true + * + * Will match the following :ref:`cluster socket match ` + * + * .. code-block:: yaml + * + * transport_socket_matches: + * - name: "useMTLS" + * match: + * useMTLS: true + * transport_socket: + * name: envoy.transport_sockets.tls + * config: { ... } # tls socket configuration + * + * If this field is set, then for health checks it will supersede an entry of *envoy.transport_socket* in the + * :ref:`LbEndpoint.Metadata `. + * This allows using different transport socket capabilities for health checking versus proxying to the + * endpoint. + * + * If the key/values pairs specified do not match any + * :ref:`transport socket matches `, + * the cluster's :ref:`transport socket ` + * will be used for health check socket configuration. + */ + 'transport_socket_match_criteria'?: (_google_protobuf_Struct | null); + /** + * The "no traffic healthy interval" is a special health check interval that + * is used for hosts that are currently passing active health checking + * (including new hosts) when the cluster has received no traffic. + * + * This is useful for when we want to send frequent health checks with + * `no_traffic_interval` but then revert to lower frequency `no_traffic_healthy_interval` once + * a host in the cluster is marked as healthy. + * + * Once a cluster has been used for traffic routing, Envoy will shift back to using the + * standard health check interval that is defined. + * + * If no_traffic_healthy_interval is not set, it will default to the + * no traffic interval and send that interval regardless of health state. + */ + 'no_traffic_healthy_interval'?: (_google_protobuf_Duration | null); 'health_checker'?: "http_health_check"|"tcp_health_check"|"grpc_health_check"|"custom_health_check"; } /** - * [#next-free-field: 23] + * [#next-free-field: 25] */ export interface HealthCheck__Output { /** * The time to wait for a health check response. If the timeout is reached the * health check attempt will be considered a failure. */ - 'timeout'?: (_google_protobuf_Duration__Output); + 'timeout': (_google_protobuf_Duration__Output | null); /** * The interval between health checks. */ - 'interval'?: (_google_protobuf_Duration__Output); + 'interval': (_google_protobuf_Duration__Output | null); /** * An optional jitter amount in milliseconds. If specified, during every * interval Envoy will add interval_jitter to the wait time. */ - 'interval_jitter'?: (_google_protobuf_Duration__Output); + 'interval_jitter': (_google_protobuf_Duration__Output | null); /** * The number of unhealthy health checks required before a host is marked - * unhealthy. Note that for *http* health checking if a host responds with 503 - * this threshold is ignored and the host is considered unhealthy immediately. + * unhealthy. Note that for *http* health checking if a host responds with a code not in + * :ref:`expected_statuses ` + * or :ref:`retriable_statuses `, + * this threshold is ignored and the host is considered immediately unhealthy. */ - 'unhealthy_threshold'?: (_google_protobuf_UInt32Value__Output); + 'unhealthy_threshold': (_google_protobuf_UInt32Value__Output | null); /** * The number of healthy health checks required before a host is marked * healthy. Note that during startup, only a single successful health check is * required to mark a host healthy. */ - 'healthy_threshold'?: (_google_protobuf_UInt32Value__Output); + 'healthy_threshold': (_google_protobuf_UInt32Value__Output | null); /** * [#not-implemented-hide:] Non-serving port for health checking. */ - 'alt_port'?: (_google_protobuf_UInt32Value__Output); + 'alt_port': (_google_protobuf_UInt32Value__Output | null); /** * Reuse health check connection between health checks. Default is true. */ - 'reuse_connection'?: (_google_protobuf_BoolValue__Output); + 'reuse_connection': (_google_protobuf_BoolValue__Output | null); /** * HTTP health check. */ - 'http_health_check'?: (_envoy_api_v2_core_HealthCheck_HttpHealthCheck__Output); + 'http_health_check'?: (_envoy_config_core_v3_HealthCheck_HttpHealthCheck__Output | null); /** * TCP health check. */ - 'tcp_health_check'?: (_envoy_api_v2_core_HealthCheck_TcpHealthCheck__Output); + 'tcp_health_check'?: (_envoy_config_core_v3_HealthCheck_TcpHealthCheck__Output | null); /** * gRPC health check. */ - 'grpc_health_check'?: (_envoy_api_v2_core_HealthCheck_GrpcHealthCheck__Output); + 'grpc_health_check'?: (_envoy_config_core_v3_HealthCheck_GrpcHealthCheck__Output | null); /** * The "no traffic interval" is a special health check interval that is used when a cluster has * never had traffic routed to it. This lower interval allows cluster information to be kept up to @@ -537,11 +582,11 @@ export interface HealthCheck__Output { * * The default value for "no traffic interval" is 60 seconds. */ - 'no_traffic_interval'?: (_google_protobuf_Duration__Output); + 'no_traffic_interval': (_google_protobuf_Duration__Output | null); /** * Custom health check. */ - 'custom_health_check'?: (_envoy_api_v2_core_HealthCheck_CustomHealthCheck__Output); + 'custom_health_check'?: (_envoy_config_core_v3_HealthCheck_CustomHealthCheck__Output | null); /** * The "unhealthy interval" is a health check interval that is used for hosts that are marked as * unhealthy. As soon as the host is marked as healthy, Envoy will shift back to using the @@ -549,7 +594,7 @@ export interface HealthCheck__Output { * * The default value for "unhealthy interval" is the same as "interval". */ - 'unhealthy_interval'?: (_google_protobuf_Duration__Output); + 'unhealthy_interval': (_google_protobuf_Duration__Output | null); /** * The "unhealthy edge interval" is a special health check interval that is used for the first * health check right after a host is marked as unhealthy. For subsequent health checks @@ -558,7 +603,7 @@ export interface HealthCheck__Output { * * The default value for "unhealthy edge interval" is the same as "unhealthy interval". */ - 'unhealthy_edge_interval'?: (_google_protobuf_Duration__Output); + 'unhealthy_edge_interval': (_google_protobuf_Duration__Output | null); /** * The "healthy edge interval" is a special health check interval that is used for the first * health check right after a host is marked as healthy. For subsequent health checks @@ -566,7 +611,7 @@ export interface HealthCheck__Output { * * The default value for "healthy edge interval" is the same as the default interval. */ - 'healthy_edge_interval'?: (_google_protobuf_Duration__Output); + 'healthy_edge_interval': (_google_protobuf_Duration__Output | null); /** * Specifies the path to the :ref:`health check event log `. * If empty, no event log will be written. @@ -592,16 +637,65 @@ export interface HealthCheck__Output { * checking after for a random time in ms between 0 and initial_jitter. This only * applies to the first health check. */ - 'initial_jitter'?: (_google_protobuf_Duration__Output); + 'initial_jitter': (_google_protobuf_Duration__Output | null); /** * This allows overriding the cluster TLS settings, just for health check connections. */ - 'tls_options'?: (_envoy_api_v2_core_HealthCheck_TlsOptions__Output); + 'tls_options': (_envoy_config_core_v3_HealthCheck_TlsOptions__Output | null); /** * [#not-implemented-hide:] * The gRPC service for the health check event service. * If empty, health check events won't be sent to a remote endpoint. */ - 'event_service'?: (_envoy_api_v2_core_EventServiceConfig__Output); + 'event_service': (_envoy_config_core_v3_EventServiceConfig__Output | null); + /** + * Optional key/value pairs that will be used to match a transport socket from those specified in the cluster's + * :ref:`tranport socket matches `. + * For example, the following match criteria + * + * .. code-block:: yaml + * + * transport_socket_match_criteria: + * useMTLS: true + * + * Will match the following :ref:`cluster socket match ` + * + * .. code-block:: yaml + * + * transport_socket_matches: + * - name: "useMTLS" + * match: + * useMTLS: true + * transport_socket: + * name: envoy.transport_sockets.tls + * config: { ... } # tls socket configuration + * + * If this field is set, then for health checks it will supersede an entry of *envoy.transport_socket* in the + * :ref:`LbEndpoint.Metadata `. + * This allows using different transport socket capabilities for health checking versus proxying to the + * endpoint. + * + * If the key/values pairs specified do not match any + * :ref:`transport socket matches `, + * the cluster's :ref:`transport socket ` + * will be used for health check socket configuration. + */ + 'transport_socket_match_criteria': (_google_protobuf_Struct__Output | null); + /** + * The "no traffic healthy interval" is a special health check interval that + * is used for hosts that are currently passing active health checking + * (including new hosts) when the cluster has received no traffic. + * + * This is useful for when we want to send frequent health checks with + * `no_traffic_interval` but then revert to lower frequency `no_traffic_healthy_interval` once + * a host in the cluster is marked as healthy. + * + * Once a cluster has been used for traffic routing, Envoy will shift back to using the + * standard health check interval that is defined. + * + * If no_traffic_healthy_interval is not set, it will default to the + * no traffic interval and send that interval regardless of health state. + */ + 'no_traffic_healthy_interval': (_google_protobuf_Duration__Output | null); 'health_checker': "http_health_check"|"tcp_health_check"|"grpc_health_check"|"custom_health_check"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HealthStatus.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HealthStatus.ts similarity index 91% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/HealthStatus.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/HealthStatus.ts index e1d572fa4..6ecbca272 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HealthStatus.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HealthStatus.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/health_check.proto +// Original file: deps/envoy-api/envoy/config/core/v3/health_check.proto /** * Endpoint health status. diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http1ProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http1ProtocolOptions.ts new file mode 100644 index 000000000..40b7408f6 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http1ProtocolOptions.ts @@ -0,0 +1,178 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +/** + * [#next-free-field: 9] + */ +export interface _envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat { + /** + * Formats the header by proper casing words: the first character and any character following + * a special character will be capitalized if it's an alpha character. For example, + * "content-type" becomes "Content-Type", and "foo$b#$are" becomes "Foo$B#$Are". + * Note that while this results in most headers following conventional casing, certain headers + * are not covered. For example, the "TE" header will be formatted as "Te". + */ + 'proper_case_words'?: (_envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords | null); + /** + * Configuration for stateful formatter extensions that allow using received headers to + * affect the output of encoding headers. E.g., preserving case during proxying. + * [#extension-category: envoy.http.stateful_header_formatters] + */ + 'stateful_formatter'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + 'header_format'?: "proper_case_words"|"stateful_formatter"; +} + +/** + * [#next-free-field: 9] + */ +export interface _envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat__Output { + /** + * Formats the header by proper casing words: the first character and any character following + * a special character will be capitalized if it's an alpha character. For example, + * "content-type" becomes "Content-Type", and "foo$b#$are" becomes "Foo$B#$Are". + * Note that while this results in most headers following conventional casing, certain headers + * are not covered. For example, the "TE" header will be formatted as "Te". + */ + 'proper_case_words'?: (_envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords__Output | null); + /** + * Configuration for stateful formatter extensions that allow using received headers to + * affect the output of encoding headers. E.g., preserving case during proxying. + * [#extension-category: envoy.http.stateful_header_formatters] + */ + 'stateful_formatter'?: (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + 'header_format': "proper_case_words"|"stateful_formatter"; +} + +export interface _envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords { +} + +export interface _envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat_ProperCaseWords__Output { +} + +/** + * [#next-free-field: 8] + */ +export interface Http1ProtocolOptions { + /** + * Handle HTTP requests with absolute URLs in the requests. These requests + * are generally sent by clients to forward/explicit proxies. This allows clients to configure + * envoy as their HTTP proxy. In Unix, for example, this is typically done by setting the + * *http_proxy* environment variable. + */ + 'allow_absolute_url'?: (_google_protobuf_BoolValue | null); + /** + * Handle incoming HTTP/1.0 and HTTP 0.9 requests. + * This is off by default, and not fully standards compliant. There is support for pre-HTTP/1.1 + * style connect logic, dechunking, and handling lack of client host iff + * *default_host_for_http_10* is configured. + */ + 'accept_http_10'?: (boolean); + /** + * A default host for HTTP/1.0 requests. This is highly suggested if *accept_http_10* is true as + * Envoy does not otherwise support HTTP/1.0 without a Host header. + * This is a no-op if *accept_http_10* is not true. + */ + 'default_host_for_http_10'?: (string); + /** + * Describes how the keys for response headers should be formatted. By default, all header keys + * are lower cased. + */ + 'header_key_format'?: (_envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat | null); + /** + * Enables trailers for HTTP/1. By default the HTTP/1 codec drops proxied trailers. + * + * .. attention:: + * + * Note that this only happens when Envoy is chunk encoding which occurs when: + * - The request is HTTP/1.1. + * - Is neither a HEAD only request nor a HTTP Upgrade. + * - Not a response to a HEAD request. + * - The content length header is not present. + */ + 'enable_trailers'?: (boolean); + /** + * Allows Envoy to process requests/responses with both `Content-Length` and `Transfer-Encoding` + * headers set. By default such messages are rejected, but if option is enabled - Envoy will + * remove Content-Length header and process message. + * See `RFC7230, sec. 3.3.3 ` for details. + * + * .. attention:: + * Enabling this option might lead to request smuggling vulnerability, especially if traffic + * is proxied via multiple layers of proxies. + */ + 'allow_chunked_length'?: (boolean); + /** + * Allows invalid HTTP messaging. When this option is false, then Envoy will terminate + * HTTP/1.1 connections upon receiving an invalid HTTP message. However, + * when this option is true, then Envoy will leave the HTTP/1.1 connection + * open where possible. + * If set, this overrides any HCM :ref:`stream_error_on_invalid_http_messaging + * `. + */ + 'override_stream_error_on_invalid_http_message'?: (_google_protobuf_BoolValue | null); +} + +/** + * [#next-free-field: 8] + */ +export interface Http1ProtocolOptions__Output { + /** + * Handle HTTP requests with absolute URLs in the requests. These requests + * are generally sent by clients to forward/explicit proxies. This allows clients to configure + * envoy as their HTTP proxy. In Unix, for example, this is typically done by setting the + * *http_proxy* environment variable. + */ + 'allow_absolute_url': (_google_protobuf_BoolValue__Output | null); + /** + * Handle incoming HTTP/1.0 and HTTP 0.9 requests. + * This is off by default, and not fully standards compliant. There is support for pre-HTTP/1.1 + * style connect logic, dechunking, and handling lack of client host iff + * *default_host_for_http_10* is configured. + */ + 'accept_http_10': (boolean); + /** + * A default host for HTTP/1.0 requests. This is highly suggested if *accept_http_10* is true as + * Envoy does not otherwise support HTTP/1.0 without a Host header. + * This is a no-op if *accept_http_10* is not true. + */ + 'default_host_for_http_10': (string); + /** + * Describes how the keys for response headers should be formatted. By default, all header keys + * are lower cased. + */ + 'header_key_format': (_envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat__Output | null); + /** + * Enables trailers for HTTP/1. By default the HTTP/1 codec drops proxied trailers. + * + * .. attention:: + * + * Note that this only happens when Envoy is chunk encoding which occurs when: + * - The request is HTTP/1.1. + * - Is neither a HEAD only request nor a HTTP Upgrade. + * - Not a response to a HEAD request. + * - The content length header is not present. + */ + 'enable_trailers': (boolean); + /** + * Allows Envoy to process requests/responses with both `Content-Length` and `Transfer-Encoding` + * headers set. By default such messages are rejected, but if option is enabled - Envoy will + * remove Content-Length header and process message. + * See `RFC7230, sec. 3.3.3 ` for details. + * + * .. attention:: + * Enabling this option might lead to request smuggling vulnerability, especially if traffic + * is proxied via multiple layers of proxies. + */ + 'allow_chunked_length': (boolean); + /** + * Allows invalid HTTP messaging. When this option is false, then Envoy will terminate + * HTTP/1.1 connections upon receiving an invalid HTTP message. However, + * when this option is true, then Envoy will leave the HTTP/1.1 connection + * open where possible. + * If set, this overrides any HCM :ref:`stream_error_on_invalid_http_messaging + * `. + */ + 'override_stream_error_on_invalid_http_message': (_google_protobuf_BoolValue__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Http2ProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http2ProtocolOptions.ts similarity index 57% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/Http2ProtocolOptions.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http2ProtocolOptions.ts index 893f61a15..786e2a00d 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Http2ProtocolOptions.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http2ProtocolOptions.ts @@ -1,39 +1,41 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/protocol.proto +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { KeepaliveSettings as _envoy_config_core_v3_KeepaliveSettings, KeepaliveSettings__Output as _envoy_config_core_v3_KeepaliveSettings__Output } from '../../../../envoy/config/core/v3/KeepaliveSettings'; /** * Defines a parameter to be sent in the SETTINGS frame. * See `RFC7540, sec. 6.5.1 `_ for details. */ -export interface _envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter { +export interface _envoy_config_core_v3_Http2ProtocolOptions_SettingsParameter { /** * The 16 bit parameter identifier. */ - 'identifier'?: (_google_protobuf_UInt32Value); + 'identifier'?: (_google_protobuf_UInt32Value | null); /** * The 32 bit parameter value. */ - 'value'?: (_google_protobuf_UInt32Value); + 'value'?: (_google_protobuf_UInt32Value | null); } /** * Defines a parameter to be sent in the SETTINGS frame. * See `RFC7540, sec. 6.5.1 `_ for details. */ -export interface _envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter__Output { +export interface _envoy_config_core_v3_Http2ProtocolOptions_SettingsParameter__Output { /** * The 16 bit parameter identifier. */ - 'identifier'?: (_google_protobuf_UInt32Value__Output); + 'identifier': (_google_protobuf_UInt32Value__Output | null); /** * The 32 bit parameter value. */ - 'value'?: (_google_protobuf_UInt32Value__Output); + 'value': (_google_protobuf_UInt32Value__Output | null); } /** - * [#next-free-field: 14] + * [#next-free-field: 16] */ export interface Http2ProtocolOptions { /** @@ -42,7 +44,7 @@ export interface Http2ProtocolOptions { * range from 0 to 4294967295 (2^32 - 1) and defaults to 4096. 0 effectively disables header * compression. */ - 'hpack_table_size'?: (_google_protobuf_UInt32Value); + 'hpack_table_size'?: (_google_protobuf_UInt32Value | null); /** * `Maximum concurrent streams `_ * allowed for peer on one HTTP/2 connection. Valid values range from 1 to 2147483647 (2^31 - 1) @@ -51,8 +53,12 @@ export interface Http2ProtocolOptions { * For upstream connections, this also limits how many streams Envoy will initiate concurrently * on a single connection. If the limit is reached, Envoy may queue requests or establish * additional connections (as allowed per circuit breaker limits). + * + * This acts as an upper bound: Envoy will lower the max concurrent streams allowed on a given + * connection based on upstream settings. Config dumps will reflect the configured upper bound, + * not the per-connection negotiated limits. */ - 'max_concurrent_streams'?: (_google_protobuf_UInt32Value); + 'max_concurrent_streams'?: (_google_protobuf_UInt32Value | null); /** * `Initial stream-level flow-control window * `_ size. Valid values range from 65535 @@ -66,12 +72,12 @@ export interface Http2ProtocolOptions { * HTTP/2 codec buffers. Once the buffer reaches this pointer, watermark callbacks will fire to * stop the flow of data to the codec buffers. */ - 'initial_stream_window_size'?: (_google_protobuf_UInt32Value); + 'initial_stream_window_size'?: (_google_protobuf_UInt32Value | null); /** * Similar to *initial_stream_window_size*, but for connection-level flow-control * window. Currently, this has the same minimum/maximum/default as *initial_stream_window_size*. */ - 'initial_connection_window_size'?: (_google_protobuf_UInt32Value); + 'initial_connection_window_size'?: (_google_protobuf_UInt32Value | null); /** * Allows proxying Websocket and other upgrades over H2 connect. */ @@ -81,7 +87,7 @@ export interface Http2ProtocolOptions { * Still under implementation. DO NOT USE. * * Allows metadata. See [metadata - * docs](https://github.com/envoyproxy/envoy/blob/master/source/docs/h2_metadata.md) for more + * docs](https://github.com/envoyproxy/envoy/blob/main/source/docs/h2_metadata.md) for more * information. */ 'allow_metadata'?: (boolean); @@ -90,18 +96,20 @@ export interface Http2ProtocolOptions { * be written into the socket). Exceeding this limit triggers flood mitigation and connection is * terminated. The ``http2.outbound_flood`` stat tracks the number of terminated connections due * to flood mitigation. The default limit is 10000. - * [#comment:TODO: implement same limits for upstream outbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_outbound_frames'?: (_google_protobuf_UInt32Value); + 'max_outbound_frames'?: (_google_protobuf_UInt32Value | null); /** * Limit the number of pending outbound downstream frames of types PING, SETTINGS and RST_STREAM, * preventing high memory utilization when receiving continuous stream of these frames. Exceeding * this limit triggers flood mitigation and connection is terminated. The * ``http2.outbound_control_flood`` stat tracks the number of terminated connections due to flood * mitigation. The default limit is 1000. - * [#comment:TODO: implement same limits for upstream outbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_outbound_control_frames'?: (_google_protobuf_UInt32Value); + 'max_outbound_control_frames'?: (_google_protobuf_UInt32Value | null); /** * Limit the number of consecutive inbound frames of types HEADERS, CONTINUATION and DATA with an * empty payload and no end stream flag. Those frames have no legitimate use and are abusive, but @@ -109,41 +117,57 @@ export interface Http2ProtocolOptions { * stat tracks the number of connections terminated due to flood mitigation. * Setting this to 0 will terminate connection upon receiving first frame with an empty payload * and no end stream flag. The default limit is 1. - * [#comment:TODO: implement same limits for upstream inbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_consecutive_inbound_frames_with_empty_payload'?: (_google_protobuf_UInt32Value); + 'max_consecutive_inbound_frames_with_empty_payload'?: (_google_protobuf_UInt32Value | null); /** * Limit the number of inbound PRIORITY frames allowed per each opened stream. If the number * of PRIORITY frames received over the lifetime of connection exceeds the value calculated * using this formula:: * - * max_inbound_priority_frames_per_stream * (1 + inbound_streams) + * max_inbound_priority_frames_per_stream * (1 + opened_streams) * - * the connection is terminated. The ``http2.inbound_priority_frames_flood`` stat tracks + * the connection is terminated. For downstream connections the `opened_streams` is incremented when + * Envoy receives complete response headers from the upstream server. For upstream connection the + * `opened_streams` is incremented when Envoy send the HEADERS frame for a new stream. The + * ``http2.inbound_priority_frames_flood`` stat tracks * the number of connections terminated due to flood mitigation. The default limit is 100. - * [#comment:TODO: implement same limits for upstream inbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_inbound_priority_frames_per_stream'?: (_google_protobuf_UInt32Value); + 'max_inbound_priority_frames_per_stream'?: (_google_protobuf_UInt32Value | null); /** * Limit the number of inbound WINDOW_UPDATE frames allowed per DATA frame sent. If the number * of WINDOW_UPDATE frames received over the lifetime of connection exceeds the value calculated * using this formula:: * - * 1 + 2 * (inbound_streams + + * 5 + 2 * (opened_streams + * max_inbound_window_update_frames_per_data_frame_sent * outbound_data_frames) * - * the connection is terminated. The ``http2.inbound_priority_frames_flood`` stat tracks - * the number of connections terminated due to flood mitigation. The default limit is 10. + * the connection is terminated. For downstream connections the `opened_streams` is incremented when + * Envoy receives complete response headers from the upstream server. For upstream connections the + * `opened_streams` is incremented when Envoy sends the HEADERS frame for a new stream. The + * ``http2.inbound_priority_frames_flood`` stat tracks the number of connections terminated due to + * flood mitigation. The default max_inbound_window_update_frames_per_data_frame_sent value is 10. * Setting this to 1 should be enough to support HTTP/2 implementations with basic flow control, * but more complex implementations that try to estimate available bandwidth require at least 2. - * [#comment:TODO: implement same limits for upstream inbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_inbound_window_update_frames_per_data_frame_sent'?: (_google_protobuf_UInt32Value); + 'max_inbound_window_update_frames_per_data_frame_sent'?: (_google_protobuf_UInt32Value | null); /** * Allows invalid HTTP messaging and headers. When this option is disabled (default), then * the whole HTTP/2 connection is terminated upon receiving invalid HEADERS frame. However, * when this option is enabled, only the offending stream is terminated. * + * This is overridden by HCM :ref:`stream_error_on_invalid_http_messaging + * ` + * iff present. + * + * This is deprecated in favor of :ref:`override_stream_error_on_invalid_http_message + * ` + * * See `RFC7540, sec. 8.1 `_ for details. */ 'stream_error_on_invalid_http_messaging'?: (boolean); @@ -175,11 +199,27 @@ export interface Http2ProtocolOptions { * `_ for * standardized identifiers. */ - 'custom_settings_parameters'?: (_envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter)[]; + 'custom_settings_parameters'?: (_envoy_config_core_v3_Http2ProtocolOptions_SettingsParameter)[]; + /** + * Allows invalid HTTP messaging and headers. When this option is disabled (default), then + * the whole HTTP/2 connection is terminated upon receiving invalid HEADERS frame. However, + * when this option is enabled, only the offending stream is terminated. + * + * This overrides any HCM :ref:`stream_error_on_invalid_http_messaging + * ` + * + * See `RFC7540, sec. 8.1 `_ for details. + */ + 'override_stream_error_on_invalid_http_message'?: (_google_protobuf_BoolValue | null); + /** + * Send HTTP/2 PING frames to verify that the connection is still healthy. If the remote peer + * does not respond within the configured timeout, the connection will be aborted. + */ + 'connection_keepalive'?: (_envoy_config_core_v3_KeepaliveSettings | null); } /** - * [#next-free-field: 14] + * [#next-free-field: 16] */ export interface Http2ProtocolOptions__Output { /** @@ -188,7 +228,7 @@ export interface Http2ProtocolOptions__Output { * range from 0 to 4294967295 (2^32 - 1) and defaults to 4096. 0 effectively disables header * compression. */ - 'hpack_table_size'?: (_google_protobuf_UInt32Value__Output); + 'hpack_table_size': (_google_protobuf_UInt32Value__Output | null); /** * `Maximum concurrent streams `_ * allowed for peer on one HTTP/2 connection. Valid values range from 1 to 2147483647 (2^31 - 1) @@ -197,8 +237,12 @@ export interface Http2ProtocolOptions__Output { * For upstream connections, this also limits how many streams Envoy will initiate concurrently * on a single connection. If the limit is reached, Envoy may queue requests or establish * additional connections (as allowed per circuit breaker limits). + * + * This acts as an upper bound: Envoy will lower the max concurrent streams allowed on a given + * connection based on upstream settings. Config dumps will reflect the configured upper bound, + * not the per-connection negotiated limits. */ - 'max_concurrent_streams'?: (_google_protobuf_UInt32Value__Output); + 'max_concurrent_streams': (_google_protobuf_UInt32Value__Output | null); /** * `Initial stream-level flow-control window * `_ size. Valid values range from 65535 @@ -212,12 +256,12 @@ export interface Http2ProtocolOptions__Output { * HTTP/2 codec buffers. Once the buffer reaches this pointer, watermark callbacks will fire to * stop the flow of data to the codec buffers. */ - 'initial_stream_window_size'?: (_google_protobuf_UInt32Value__Output); + 'initial_stream_window_size': (_google_protobuf_UInt32Value__Output | null); /** * Similar to *initial_stream_window_size*, but for connection-level flow-control * window. Currently, this has the same minimum/maximum/default as *initial_stream_window_size*. */ - 'initial_connection_window_size'?: (_google_protobuf_UInt32Value__Output); + 'initial_connection_window_size': (_google_protobuf_UInt32Value__Output | null); /** * Allows proxying Websocket and other upgrades over H2 connect. */ @@ -227,7 +271,7 @@ export interface Http2ProtocolOptions__Output { * Still under implementation. DO NOT USE. * * Allows metadata. See [metadata - * docs](https://github.com/envoyproxy/envoy/blob/master/source/docs/h2_metadata.md) for more + * docs](https://github.com/envoyproxy/envoy/blob/main/source/docs/h2_metadata.md) for more * information. */ 'allow_metadata': (boolean); @@ -236,18 +280,20 @@ export interface Http2ProtocolOptions__Output { * be written into the socket). Exceeding this limit triggers flood mitigation and connection is * terminated. The ``http2.outbound_flood`` stat tracks the number of terminated connections due * to flood mitigation. The default limit is 10000. - * [#comment:TODO: implement same limits for upstream outbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_outbound_frames'?: (_google_protobuf_UInt32Value__Output); + 'max_outbound_frames': (_google_protobuf_UInt32Value__Output | null); /** * Limit the number of pending outbound downstream frames of types PING, SETTINGS and RST_STREAM, * preventing high memory utilization when receiving continuous stream of these frames. Exceeding * this limit triggers flood mitigation and connection is terminated. The * ``http2.outbound_control_flood`` stat tracks the number of terminated connections due to flood * mitigation. The default limit is 1000. - * [#comment:TODO: implement same limits for upstream outbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_outbound_control_frames'?: (_google_protobuf_UInt32Value__Output); + 'max_outbound_control_frames': (_google_protobuf_UInt32Value__Output | null); /** * Limit the number of consecutive inbound frames of types HEADERS, CONTINUATION and DATA with an * empty payload and no end stream flag. Those frames have no legitimate use and are abusive, but @@ -255,41 +301,57 @@ export interface Http2ProtocolOptions__Output { * stat tracks the number of connections terminated due to flood mitigation. * Setting this to 0 will terminate connection upon receiving first frame with an empty payload * and no end stream flag. The default limit is 1. - * [#comment:TODO: implement same limits for upstream inbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_consecutive_inbound_frames_with_empty_payload'?: (_google_protobuf_UInt32Value__Output); + 'max_consecutive_inbound_frames_with_empty_payload': (_google_protobuf_UInt32Value__Output | null); /** * Limit the number of inbound PRIORITY frames allowed per each opened stream. If the number * of PRIORITY frames received over the lifetime of connection exceeds the value calculated * using this formula:: * - * max_inbound_priority_frames_per_stream * (1 + inbound_streams) + * max_inbound_priority_frames_per_stream * (1 + opened_streams) * - * the connection is terminated. The ``http2.inbound_priority_frames_flood`` stat tracks + * the connection is terminated. For downstream connections the `opened_streams` is incremented when + * Envoy receives complete response headers from the upstream server. For upstream connection the + * `opened_streams` is incremented when Envoy send the HEADERS frame for a new stream. The + * ``http2.inbound_priority_frames_flood`` stat tracks * the number of connections terminated due to flood mitigation. The default limit is 100. - * [#comment:TODO: implement same limits for upstream inbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_inbound_priority_frames_per_stream'?: (_google_protobuf_UInt32Value__Output); + 'max_inbound_priority_frames_per_stream': (_google_protobuf_UInt32Value__Output | null); /** * Limit the number of inbound WINDOW_UPDATE frames allowed per DATA frame sent. If the number * of WINDOW_UPDATE frames received over the lifetime of connection exceeds the value calculated * using this formula:: * - * 1 + 2 * (inbound_streams + + * 5 + 2 * (opened_streams + * max_inbound_window_update_frames_per_data_frame_sent * outbound_data_frames) * - * the connection is terminated. The ``http2.inbound_priority_frames_flood`` stat tracks - * the number of connections terminated due to flood mitigation. The default limit is 10. + * the connection is terminated. For downstream connections the `opened_streams` is incremented when + * Envoy receives complete response headers from the upstream server. For upstream connections the + * `opened_streams` is incremented when Envoy sends the HEADERS frame for a new stream. The + * ``http2.inbound_priority_frames_flood`` stat tracks the number of connections terminated due to + * flood mitigation. The default max_inbound_window_update_frames_per_data_frame_sent value is 10. * Setting this to 1 should be enough to support HTTP/2 implementations with basic flow control, * but more complex implementations that try to estimate available bandwidth require at least 2. - * [#comment:TODO: implement same limits for upstream inbound frames as well.] + * NOTE: flood and abuse mitigation for upstream connections is presently enabled by the + * `envoy.reloadable_features.upstream_http2_flood_checks` flag. */ - 'max_inbound_window_update_frames_per_data_frame_sent'?: (_google_protobuf_UInt32Value__Output); + 'max_inbound_window_update_frames_per_data_frame_sent': (_google_protobuf_UInt32Value__Output | null); /** * Allows invalid HTTP messaging and headers. When this option is disabled (default), then * the whole HTTP/2 connection is terminated upon receiving invalid HEADERS frame. However, * when this option is enabled, only the offending stream is terminated. * + * This is overridden by HCM :ref:`stream_error_on_invalid_http_messaging + * ` + * iff present. + * + * This is deprecated in favor of :ref:`override_stream_error_on_invalid_http_message + * ` + * * See `RFC7540, sec. 8.1 `_ for details. */ 'stream_error_on_invalid_http_messaging': (boolean); @@ -321,5 +383,21 @@ export interface Http2ProtocolOptions__Output { * `_ for * standardized identifiers. */ - 'custom_settings_parameters': (_envoy_api_v2_core_Http2ProtocolOptions_SettingsParameter__Output)[]; + 'custom_settings_parameters': (_envoy_config_core_v3_Http2ProtocolOptions_SettingsParameter__Output)[]; + /** + * Allows invalid HTTP messaging and headers. When this option is disabled (default), then + * the whole HTTP/2 connection is terminated upon receiving invalid HEADERS frame. However, + * when this option is enabled, only the offending stream is terminated. + * + * This overrides any HCM :ref:`stream_error_on_invalid_http_messaging + * ` + * + * See `RFC7540, sec. 8.1 `_ for details. + */ + 'override_stream_error_on_invalid_http_message': (_google_protobuf_BoolValue__Output | null); + /** + * Send HTTP/2 PING frames to verify that the connection is still healthy. If the remote peer + * does not respond within the configured timeout, the connection will be aborted. + */ + 'connection_keepalive': (_envoy_config_core_v3_KeepaliveSettings__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http3ProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http3ProtocolOptions.ts new file mode 100644 index 000000000..51b31b8e7 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Http3ProtocolOptions.ts @@ -0,0 +1,56 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + +import type { QuicProtocolOptions as _envoy_config_core_v3_QuicProtocolOptions, QuicProtocolOptions__Output as _envoy_config_core_v3_QuicProtocolOptions__Output } from '../../../../envoy/config/core/v3/QuicProtocolOptions'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; + +/** + * A message which allows using HTTP/3. + * [#next-free-field: 6] + */ +export interface Http3ProtocolOptions { + 'quic_protocol_options'?: (_envoy_config_core_v3_QuicProtocolOptions | null); + /** + * Allows invalid HTTP messaging and headers. When this option is disabled (default), then + * the whole HTTP/3 connection is terminated upon receiving invalid HEADERS frame. However, + * when this option is enabled, only the offending stream is terminated. + * + * If set, this overrides any HCM :ref:`stream_error_on_invalid_http_messaging + * `. + */ + 'override_stream_error_on_invalid_http_message'?: (_google_protobuf_BoolValue | null); + /** + * Allows proxying Websocket and other upgrades over HTTP/3 CONNECT using + * the header mechanisms from the `HTTP/2 extended connect RFC + * `_ + * and settings `proposed for HTTP/3 + * `_ + * Note that HTTP/3 CONNECT is not yet an RFC. + */ + 'allow_extended_connect'?: (boolean); +} + +/** + * A message which allows using HTTP/3. + * [#next-free-field: 6] + */ +export interface Http3ProtocolOptions__Output { + 'quic_protocol_options': (_envoy_config_core_v3_QuicProtocolOptions__Output | null); + /** + * Allows invalid HTTP messaging and headers. When this option is disabled (default), then + * the whole HTTP/3 connection is terminated upon receiving invalid HEADERS frame. However, + * when this option is enabled, only the offending stream is terminated. + * + * If set, this overrides any HCM :ref:`stream_error_on_invalid_http_messaging + * `. + */ + 'override_stream_error_on_invalid_http_message': (_google_protobuf_BoolValue__Output | null); + /** + * Allows proxying Websocket and other upgrades over HTTP/3 CONNECT using + * the header mechanisms from the `HTTP/2 extended connect RFC + * `_ + * and settings `proposed for HTTP/3 + * `_ + * Note that HTTP/3 CONNECT is not yet an RFC. + */ + 'allow_extended_connect': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HttpProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HttpProtocolOptions.ts similarity index 55% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/HttpProtocolOptions.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/HttpProtocolOptions.ts index 219fdb0c7..34a4053dd 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HttpProtocolOptions.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HttpProtocolOptions.ts @@ -1,9 +1,9 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/protocol.proto +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -// Original file: deps/envoy-api/envoy/api/v2/core/protocol.proto +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto /** * Action to take when Envoy receives client request with header names containing underscore @@ -12,7 +12,7 @@ import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output a * as a security measure due to systems that treat '_' and '-' as interchangeable. Envoy by default allows client request headers with underscore * characters. */ -export enum _envoy_api_v2_core_HttpProtocolOptions_HeadersWithUnderscoresAction { +export enum _envoy_config_core_v3_HttpProtocolOptions_HeadersWithUnderscoresAction { /** * Allow headers with underscores. This is the default behavior. */ @@ -32,7 +32,7 @@ export enum _envoy_api_v2_core_HttpProtocolOptions_HeadersWithUnderscoresAction } /** - * [#next-free-field: 6] + * [#next-free-field: 7] */ export interface HttpProtocolOptions { /** @@ -41,45 +41,57 @@ export interface HttpProtocolOptions { * idle timeout is reached the connection will be closed. If the connection is an HTTP/2 * downstream connection a drain sequence will occur prior to closing the connection, see * :ref:`drain_timeout - * `. + * `. * Note that request based timeouts mean that HTTP/2 PINGs will not keep the connection alive. * If not specified, this defaults to 1 hour. To disable idle timeouts explicitly set this to 0. * * .. warning:: * Disabling this timeout has a highly likelihood of yielding connection leaks due to lost TCP * FIN packets, etc. + * + * If the :ref:`overload action ` "envoy.overload_actions.reduce_timeouts" + * is configured, this timeout is scaled for downstream connections according to the value for + * :ref:`HTTP_DOWNSTREAM_CONNECTION_IDLE `. */ - 'idle_timeout'?: (_google_protobuf_Duration); + 'idle_timeout'?: (_google_protobuf_Duration | null); /** * The maximum number of headers. If unconfigured, the default * maximum number of request headers allowed is 100. Requests that exceed this limit will receive * a 431 response for HTTP/1.x and cause a stream reset for HTTP/2. */ - 'max_headers_count'?: (_google_protobuf_UInt32Value); + 'max_headers_count'?: (_google_protobuf_UInt32Value | null); /** * The maximum duration of a connection. The duration is defined as a period since a connection * was established. If not set, there is no max duration. When max_connection_duration is reached - * the connection will be closed. Drain sequence will occur prior to closing the connection if - * if's applicable. See :ref:`drain_timeout - * `. - * Note: not implemented for upstream connections. + * and if there are no active streams, the connection will be closed. If there are any active streams, + * the drain sequence will kick-in, and the connection will be force-closed after the drain period. + * See :ref:`drain_timeout + * `. + * Note: This feature is not yet implemented for the upstream connections. */ - 'max_connection_duration'?: (_google_protobuf_Duration); + 'max_connection_duration'?: (_google_protobuf_Duration | null); /** * Total duration to keep alive an HTTP request/response stream. If the time limit is reached the stream will be * reset independent of any other timeouts. If not specified, this value is not set. */ - 'max_stream_duration'?: (_google_protobuf_Duration); + 'max_stream_duration'?: (_google_protobuf_Duration | null); /** * Action to take when a client request with a header name containing underscore characters is received. * If this setting is not specified, the value defaults to ALLOW. * Note: upstream responses are not affected by this setting. */ - 'headers_with_underscores_action'?: (_envoy_api_v2_core_HttpProtocolOptions_HeadersWithUnderscoresAction | keyof typeof _envoy_api_v2_core_HttpProtocolOptions_HeadersWithUnderscoresAction); + 'headers_with_underscores_action'?: (_envoy_config_core_v3_HttpProtocolOptions_HeadersWithUnderscoresAction | keyof typeof _envoy_config_core_v3_HttpProtocolOptions_HeadersWithUnderscoresAction); + /** + * Optional maximum requests for both upstream and downstream connections. + * If not specified, there is no limit. + * Setting this parameter to 1 will effectively disable keep alive. + * For HTTP/2 and HTTP/3, due to concurrent stream processing, the limit is approximate. + */ + 'max_requests_per_connection'?: (_google_protobuf_UInt32Value | null); } /** - * [#next-free-field: 6] + * [#next-free-field: 7] */ export interface HttpProtocolOptions__Output { /** @@ -88,39 +100,51 @@ export interface HttpProtocolOptions__Output { * idle timeout is reached the connection will be closed. If the connection is an HTTP/2 * downstream connection a drain sequence will occur prior to closing the connection, see * :ref:`drain_timeout - * `. + * `. * Note that request based timeouts mean that HTTP/2 PINGs will not keep the connection alive. * If not specified, this defaults to 1 hour. To disable idle timeouts explicitly set this to 0. * * .. warning:: * Disabling this timeout has a highly likelihood of yielding connection leaks due to lost TCP * FIN packets, etc. + * + * If the :ref:`overload action ` "envoy.overload_actions.reduce_timeouts" + * is configured, this timeout is scaled for downstream connections according to the value for + * :ref:`HTTP_DOWNSTREAM_CONNECTION_IDLE `. */ - 'idle_timeout'?: (_google_protobuf_Duration__Output); + 'idle_timeout': (_google_protobuf_Duration__Output | null); /** * The maximum number of headers. If unconfigured, the default * maximum number of request headers allowed is 100. Requests that exceed this limit will receive * a 431 response for HTTP/1.x and cause a stream reset for HTTP/2. */ - 'max_headers_count'?: (_google_protobuf_UInt32Value__Output); + 'max_headers_count': (_google_protobuf_UInt32Value__Output | null); /** * The maximum duration of a connection. The duration is defined as a period since a connection * was established. If not set, there is no max duration. When max_connection_duration is reached - * the connection will be closed. Drain sequence will occur prior to closing the connection if - * if's applicable. See :ref:`drain_timeout - * `. - * Note: not implemented for upstream connections. + * and if there are no active streams, the connection will be closed. If there are any active streams, + * the drain sequence will kick-in, and the connection will be force-closed after the drain period. + * See :ref:`drain_timeout + * `. + * Note: This feature is not yet implemented for the upstream connections. */ - 'max_connection_duration'?: (_google_protobuf_Duration__Output); + 'max_connection_duration': (_google_protobuf_Duration__Output | null); /** * Total duration to keep alive an HTTP request/response stream. If the time limit is reached the stream will be * reset independent of any other timeouts. If not specified, this value is not set. */ - 'max_stream_duration'?: (_google_protobuf_Duration__Output); + 'max_stream_duration': (_google_protobuf_Duration__Output | null); /** * Action to take when a client request with a header name containing underscore characters is received. * If this setting is not specified, the value defaults to ALLOW. * Note: upstream responses are not affected by this setting. */ - 'headers_with_underscores_action': (keyof typeof _envoy_api_v2_core_HttpProtocolOptions_HeadersWithUnderscoresAction); + 'headers_with_underscores_action': (keyof typeof _envoy_config_core_v3_HttpProtocolOptions_HeadersWithUnderscoresAction); + /** + * Optional maximum requests for both upstream and downstream connections. + * If not specified, there is no limit. + * Setting this parameter to 1 will effectively disable keep alive. + * For HTTP/2 and HTTP/3, due to concurrent stream processing, the limit is approximate. + */ + 'max_requests_per_connection': (_google_protobuf_UInt32Value__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HttpUri.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HttpUri.ts similarity index 92% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/HttpUri.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/HttpUri.ts index 19711dde7..0bac9ac51 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/HttpUri.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/HttpUri.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/http_uri.proto +// Original file: deps/envoy-api/envoy/config/core/v3/http_uri.proto import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; @@ -30,7 +30,7 @@ export interface HttpUri { /** * Sets the maximum duration in milliseconds that a response can take to arrive upon request. */ - 'timeout'?: (_google_protobuf_Duration); + 'timeout'?: (_google_protobuf_Duration | null); /** * Specify how `uri` is to be fetched. Today, this requires an explicit * cluster, but in the future we may support dynamic cluster creation or @@ -68,7 +68,7 @@ export interface HttpUri__Output { /** * Sets the maximum duration in milliseconds that a response can take to arrive upon request. */ - 'timeout'?: (_google_protobuf_Duration__Output); + 'timeout': (_google_protobuf_Duration__Output | null); /** * Specify how `uri` is to be fetched. Today, this requires an explicit * cluster, but in the future we may support dynamic cluster creation or diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/KeepaliveSettings.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/KeepaliveSettings.ts new file mode 100644 index 000000000..2c274c6e1 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/KeepaliveSettings.ts @@ -0,0 +1,58 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { Percent as _envoy_type_v3_Percent, Percent__Output as _envoy_type_v3_Percent__Output } from '../../../../envoy/type/v3/Percent'; + +export interface KeepaliveSettings { + /** + * Send HTTP/2 PING frames at this period, in order to test that the connection is still alive. + * If this is zero, interval PINGs will not be sent. + */ + 'interval'?: (_google_protobuf_Duration | null); + /** + * How long to wait for a response to a keepalive PING. If a response is not received within this + * time period, the connection will be aborted. + */ + 'timeout'?: (_google_protobuf_Duration | null); + /** + * A random jitter amount as a percentage of interval that will be added to each interval. + * A value of zero means there will be no jitter. + * The default value is 15%. + */ + 'interval_jitter'?: (_envoy_type_v3_Percent | null); + /** + * If the connection has been idle for this duration, send a HTTP/2 ping ahead + * of new stream creation, to quickly detect dead connections. + * If this is zero, this type of PING will not be sent. + * If an interval ping is outstanding, a second ping will not be sent as the + * interval ping will determine if the connection is dead. + */ + 'connection_idle_interval'?: (_google_protobuf_Duration | null); +} + +export interface KeepaliveSettings__Output { + /** + * Send HTTP/2 PING frames at this period, in order to test that the connection is still alive. + * If this is zero, interval PINGs will not be sent. + */ + 'interval': (_google_protobuf_Duration__Output | null); + /** + * How long to wait for a response to a keepalive PING. If a response is not received within this + * time period, the connection will be aborted. + */ + 'timeout': (_google_protobuf_Duration__Output | null); + /** + * A random jitter amount as a percentage of interval that will be added to each interval. + * A value of zero means there will be no jitter. + * The default value is 15%. + */ + 'interval_jitter': (_envoy_type_v3_Percent__Output | null); + /** + * If the connection has been idle for this duration, send a HTTP/2 ping ahead + * of new stream creation, to quickly detect dead connections. + * If this is zero, this type of PING will not be sent. + * If an interval ping is outstanding, a second ping will not be sent as the + * interval ping will determine if the connection is dead. + */ + 'connection_idle_interval': (_google_protobuf_Duration__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Locality.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Locality.ts similarity index 79% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/Locality.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/Locality.ts index 49fb232a4..b15b53832 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Locality.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Locality.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** @@ -6,13 +6,13 @@ */ export interface Locality { /** - * Region this :ref:`zone ` belongs to. + * Region this :ref:`zone ` belongs to. */ 'region'?: (string); /** * Defines the local service zone where Envoy is running. Though optional, it * should be set if discovery service routing is used and the discovery - * service exposes :ref:`zone data `, + * service exposes :ref:`zone data `, * either in this message or via :option:`--service-zone`. The meaning of zone * is context dependent, e.g. `Availability Zone (AZ) * `_ @@ -33,13 +33,13 @@ export interface Locality { */ export interface Locality__Output { /** - * Region this :ref:`zone ` belongs to. + * Region this :ref:`zone ` belongs to. */ 'region': (string); /** * Defines the local service zone where Envoy is running. Though optional, it * should be set if discovery service routing is used and the discovery - * service exposes :ref:`zone data `, + * service exposes :ref:`zone data `, * either in this message or via :option:`--service-zone`. The meaning of zone * is context dependent, e.g. `Availability Zone (AZ) * `_ diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Metadata.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Metadata.ts similarity index 62% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/Metadata.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/Metadata.ts index ca823a27c..fb603c2ba 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Metadata.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Metadata.ts @@ -1,6 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; /** * Metadata provides additional inputs to filters based on matched listeners, @@ -30,8 +31,21 @@ export interface Metadata { /** * Key is the reverse DNS filter name, e.g. com.acme.widget. The envoy.* * namespace is reserved for Envoy's built-in filters. + * If both *filter_metadata* and + * :ref:`typed_filter_metadata ` + * fields are present in the metadata with same keys, + * only *typed_filter_metadata* field will be parsed. */ 'filter_metadata'?: ({[key: string]: _google_protobuf_Struct}); + /** + * Key is the reverse DNS filter name, e.g. com.acme.widget. The envoy.* + * namespace is reserved for Envoy's built-in filters. + * The value is encoded as google.protobuf.Any. + * If both :ref:`filter_metadata ` + * and *typed_filter_metadata* fields are present in the metadata with same keys, + * only *typed_filter_metadata* field will be parsed. + */ + 'typed_filter_metadata'?: ({[key: string]: _google_protobuf_Any}); } /** @@ -62,6 +76,19 @@ export interface Metadata__Output { /** * Key is the reverse DNS filter name, e.g. com.acme.widget. The envoy.* * namespace is reserved for Envoy's built-in filters. + * If both *filter_metadata* and + * :ref:`typed_filter_metadata ` + * fields are present in the metadata with same keys, + * only *typed_filter_metadata* field will be parsed. + */ + 'filter_metadata': ({[key: string]: _google_protobuf_Struct__Output}); + /** + * Key is the reverse DNS filter name, e.g. com.acme.widget. The envoy.* + * namespace is reserved for Envoy's built-in filters. + * The value is encoded as google.protobuf.Any. + * If both :ref:`filter_metadata ` + * and *typed_filter_metadata* fields are present in the metadata with same keys, + * only *typed_filter_metadata* field will be parsed. */ - 'filter_metadata'?: ({[key: string]: _google_protobuf_Struct__Output}); + 'typed_filter_metadata': ({[key: string]: _google_protobuf_Any__Output}); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Node.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Node.ts similarity index 62% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/Node.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/Node.ts index c6ddea9d4..addd47a68 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Node.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Node.ts @@ -1,16 +1,17 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { Locality as _envoy_api_v2_core_Locality, Locality__Output as _envoy_api_v2_core_Locality__Output } from '../../../../envoy/api/v2/core/Locality'; -import type { BuildVersion as _envoy_api_v2_core_BuildVersion, BuildVersion__Output as _envoy_api_v2_core_BuildVersion__Output } from '../../../../envoy/api/v2/core/BuildVersion'; -import type { Extension as _envoy_api_v2_core_Extension, Extension__Output as _envoy_api_v2_core_Extension__Output } from '../../../../envoy/api/v2/core/Extension'; -import type { Address as _envoy_api_v2_core_Address, Address__Output as _envoy_api_v2_core_Address__Output } from '../../../../envoy/api/v2/core/Address'; +import type { Locality as _envoy_config_core_v3_Locality, Locality__Output as _envoy_config_core_v3_Locality__Output } from '../../../../envoy/config/core/v3/Locality'; +import type { BuildVersion as _envoy_config_core_v3_BuildVersion, BuildVersion__Output as _envoy_config_core_v3_BuildVersion__Output } from '../../../../envoy/config/core/v3/BuildVersion'; +import type { Extension as _envoy_config_core_v3_Extension, Extension__Output as _envoy_config_core_v3_Extension__Output } from '../../../../envoy/config/core/v3/Extension'; +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; +import type { ContextParams as _xds_core_v3_ContextParams, ContextParams__Output as _xds_core_v3_ContextParams__Output } from '../../../../xds/core/v3/ContextParams'; /** * Identifies a specific Envoy instance. The node identifier is presented to the * management server, which may use this identifier to distinguish per Envoy * configuration for serving. - * [#next-free-field: 12] + * [#next-free-field: 13] */ export interface Node { /** @@ -27,10 +28,10 @@ export interface Node { * optional, it should be set if any of the following features are used: * :ref:`statsd `, :ref:`health check cluster * verification - * `, - * :ref:`runtime override directory `, + * `, + * :ref:`runtime override directory `, * :ref:`user agent addition - * `, + * `, * :ref:`HTTP global rate limiting `, * :ref:`CDS `, and :ref:`HTTP tracing * `, either in this message or via @@ -41,18 +42,11 @@ export interface Node { * Opaque metadata extending the node identifier. Envoy will pass this * directly to the management server. */ - 'metadata'?: (_google_protobuf_Struct); + 'metadata'?: (_google_protobuf_Struct | null); /** * Locality specifying where the Envoy instance is running. */ - 'locality'?: (_envoy_api_v2_core_Locality); - /** - * This is motivated by informing a management server during canary which - * version of Envoy is being tested in a heterogeneous fleet. This will be set - * by Envoy in management server RPCs. - * This field is deprecated in favor of the user_agent_name and user_agent_version values. - */ - 'build_version'?: (string); + 'locality'?: (_envoy_config_core_v3_Locality | null); /** * Free-form string that identifies the entity requesting config. * E.g. "envoy" or "grpc" @@ -66,11 +60,11 @@ export interface Node { /** * Structured version of the entity requesting config. */ - 'user_agent_build_version'?: (_envoy_api_v2_core_BuildVersion); + 'user_agent_build_version'?: (_envoy_config_core_v3_BuildVersion | null); /** * List of extensions and their versions supported by the node. */ - 'extensions'?: (_envoy_api_v2_core_Extension)[]; + 'extensions'?: (_envoy_config_core_v3_Extension)[]; /** * Client feature support list. These are well known features described * in the Envoy API repository for a given major version of an API. Client features @@ -85,7 +79,15 @@ export interface Node { * if there is a listener bound to port 80, the list can optionally contain the * SocketAddress `(0.0.0.0,80)`. The field is optional and just a hint. */ - 'listening_addresses'?: (_envoy_api_v2_core_Address)[]; + 'listening_addresses'?: (_envoy_config_core_v3_Address)[]; + /** + * Map from xDS resource type URL to dynamic context parameters. These may vary at runtime (unlike + * other fields in this message). For example, the xDS client may have a shard identifier that + * changes during the lifetime of the xDS client. In Envoy, this would be achieved by updating the + * dynamic context on the Server::Instance's LocalInfo context provider. The shard ID dynamic + * parameter then appears in this field during future discovery requests. + */ + 'dynamic_parameters'?: ({[key: string]: _xds_core_v3_ContextParams}); 'user_agent_version_type'?: "user_agent_version"|"user_agent_build_version"; } @@ -93,7 +95,7 @@ export interface Node { * Identifies a specific Envoy instance. The node identifier is presented to the * management server, which may use this identifier to distinguish per Envoy * configuration for serving. - * [#next-free-field: 12] + * [#next-free-field: 13] */ export interface Node__Output { /** @@ -110,10 +112,10 @@ export interface Node__Output { * optional, it should be set if any of the following features are used: * :ref:`statsd `, :ref:`health check cluster * verification - * `, - * :ref:`runtime override directory `, + * `, + * :ref:`runtime override directory `, * :ref:`user agent addition - * `, + * `, * :ref:`HTTP global rate limiting `, * :ref:`CDS `, and :ref:`HTTP tracing * `, either in this message or via @@ -124,18 +126,11 @@ export interface Node__Output { * Opaque metadata extending the node identifier. Envoy will pass this * directly to the management server. */ - 'metadata'?: (_google_protobuf_Struct__Output); + 'metadata': (_google_protobuf_Struct__Output | null); /** * Locality specifying where the Envoy instance is running. */ - 'locality'?: (_envoy_api_v2_core_Locality__Output); - /** - * This is motivated by informing a management server during canary which - * version of Envoy is being tested in a heterogeneous fleet. This will be set - * by Envoy in management server RPCs. - * This field is deprecated in favor of the user_agent_name and user_agent_version values. - */ - 'build_version': (string); + 'locality': (_envoy_config_core_v3_Locality__Output | null); /** * Free-form string that identifies the entity requesting config. * E.g. "envoy" or "grpc" @@ -149,11 +144,11 @@ export interface Node__Output { /** * Structured version of the entity requesting config. */ - 'user_agent_build_version'?: (_envoy_api_v2_core_BuildVersion__Output); + 'user_agent_build_version'?: (_envoy_config_core_v3_BuildVersion__Output | null); /** * List of extensions and their versions supported by the node. */ - 'extensions': (_envoy_api_v2_core_Extension__Output)[]; + 'extensions': (_envoy_config_core_v3_Extension__Output)[]; /** * Client feature support list. These are well known features described * in the Envoy API repository for a given major version of an API. Client features @@ -168,6 +163,14 @@ export interface Node__Output { * if there is a listener bound to port 80, the list can optionally contain the * SocketAddress `(0.0.0.0,80)`. The field is optional and just a hint. */ - 'listening_addresses': (_envoy_api_v2_core_Address__Output)[]; + 'listening_addresses': (_envoy_config_core_v3_Address__Output)[]; + /** + * Map from xDS resource type URL to dynamic context parameters. These may vary at runtime (unlike + * other fields in this message). For example, the xDS client may have a shard identifier that + * changes during the lifetime of the xDS client. In Envoy, this would be achieved by updating the + * dynamic context on the Server::Instance's LocalInfo context provider. The shard ID dynamic + * parameter then appears in this field during future discovery requests. + */ + 'dynamic_parameters': ({[key: string]: _xds_core_v3_ContextParams__Output}); 'user_agent_version_type': "user_agent_version"|"user_agent_build_version"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Pipe.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Pipe.ts similarity index 92% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/Pipe.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/Pipe.ts index 9e6cbb82d..3d8fdb1c8 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/Pipe.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/Pipe.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/address.proto +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto export interface Pipe { diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ProxyProtocolConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ProxyProtocolConfig.ts new file mode 100644 index 000000000..a28de2dbe --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/ProxyProtocolConfig.ts @@ -0,0 +1,29 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/proxy_protocol.proto + + +// Original file: deps/envoy-api/envoy/config/core/v3/proxy_protocol.proto + +export enum _envoy_config_core_v3_ProxyProtocolConfig_Version { + /** + * PROXY protocol version 1. Human readable format. + */ + V1 = 0, + /** + * PROXY protocol version 2. Binary format. + */ + V2 = 1, +} + +export interface ProxyProtocolConfig { + /** + * The PROXY protocol version to use. See https://www.haproxy.org/download/2.1/doc/proxy-protocol.txt for details + */ + 'version'?: (_envoy_config_core_v3_ProxyProtocolConfig_Version | keyof typeof _envoy_config_core_v3_ProxyProtocolConfig_Version); +} + +export interface ProxyProtocolConfig__Output { + /** + * The PROXY protocol version to use. See https://www.haproxy.org/download/2.1/doc/proxy-protocol.txt for details + */ + 'version': (keyof typeof _envoy_config_core_v3_ProxyProtocolConfig_Version); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/QueryParameter.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/QueryParameter.ts new file mode 100644 index 000000000..4cf7952fb --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/QueryParameter.ts @@ -0,0 +1,30 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + + +/** + * Query parameter name/value pair. + */ +export interface QueryParameter { + /** + * The key of the query parameter. Case sensitive. + */ + 'key'?: (string); + /** + * The value of the query parameter. + */ + 'value'?: (string); +} + +/** + * Query parameter name/value pair. + */ +export interface QueryParameter__Output { + /** + * The key of the query parameter. Case sensitive. + */ + 'key': (string); + /** + * The value of the query parameter. + */ + 'value': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/QuicProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/QuicProtocolOptions.ts new file mode 100644 index 000000000..6a653b54d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/QuicProtocolOptions.ts @@ -0,0 +1,69 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; + +/** + * QUIC protocol options which apply to both downstream and upstream connections. + */ +export interface QuicProtocolOptions { + /** + * Maximum number of streams that the client can negotiate per connection. 100 + * if not specified. + */ + 'max_concurrent_streams'?: (_google_protobuf_UInt32Value | null); + /** + * `Initial stream-level flow-control receive window + * `_ size. Valid values range from + * 1 to 16777216 (2^24, maximum supported by QUICHE) and defaults to 65536 (2^16). + * + * NOTE: 16384 (2^14) is the minimum window size supported in Google QUIC. If configured smaller than it, we will use 16384 instead. + * QUICHE IETF Quic implementation supports 1 bytes window. We only support increasing the default window size now, so it's also the minimum. + * + * This field also acts as a soft limit on the number of bytes Envoy will buffer per-stream in the + * QUIC stream send and receive buffers. Once the buffer reaches this pointer, watermark callbacks will fire to + * stop the flow of data to the stream buffers. + */ + 'initial_stream_window_size'?: (_google_protobuf_UInt32Value | null); + /** + * Similar to *initial_stream_window_size*, but for connection-level + * flow-control. Valid values rage from 1 to 25165824 (24MB, maximum supported by QUICHE) and defaults to 65536 (2^16). + * window. Currently, this has the same minimum/default as *initial_stream_window_size*. + * + * NOTE: 16384 (2^14) is the minimum window size supported in Google QUIC. We only support increasing the default + * window size now, so it's also the minimum. + */ + 'initial_connection_window_size'?: (_google_protobuf_UInt32Value | null); +} + +/** + * QUIC protocol options which apply to both downstream and upstream connections. + */ +export interface QuicProtocolOptions__Output { + /** + * Maximum number of streams that the client can negotiate per connection. 100 + * if not specified. + */ + 'max_concurrent_streams': (_google_protobuf_UInt32Value__Output | null); + /** + * `Initial stream-level flow-control receive window + * `_ size. Valid values range from + * 1 to 16777216 (2^24, maximum supported by QUICHE) and defaults to 65536 (2^16). + * + * NOTE: 16384 (2^14) is the minimum window size supported in Google QUIC. If configured smaller than it, we will use 16384 instead. + * QUICHE IETF Quic implementation supports 1 bytes window. We only support increasing the default window size now, so it's also the minimum. + * + * This field also acts as a soft limit on the number of bytes Envoy will buffer per-stream in the + * QUIC stream send and receive buffers. Once the buffer reaches this pointer, watermark callbacks will fire to + * stop the flow of data to the stream buffers. + */ + 'initial_stream_window_size': (_google_protobuf_UInt32Value__Output | null); + /** + * Similar to *initial_stream_window_size*, but for connection-level + * flow-control. Valid values rage from 1 to 25165824 (24MB, maximum supported by QUICHE) and defaults to 65536 (2^16). + * window. Currently, this has the same minimum/default as *initial_stream_window_size*. + * + * NOTE: 16384 (2^14) is the minimum window size supported in Google QUIC. We only support increasing the default + * window size now, so it's also the minimum. + */ + 'initial_connection_window_size': (_google_protobuf_UInt32Value__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RateLimitSettings.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RateLimitSettings.ts similarity index 79% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RateLimitSettings.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RateLimitSettings.ts index 222c86eb4..bf002d99c 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RateLimitSettings.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RateLimitSettings.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/config_source.proto +// Original file: deps/envoy-api/envoy/config/core/v3/config_source.proto import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; import type { DoubleValue as _google_protobuf_DoubleValue, DoubleValue__Output as _google_protobuf_DoubleValue__Output } from '../../../../google/protobuf/DoubleValue'; @@ -11,12 +11,12 @@ export interface RateLimitSettings { * Maximum number of tokens to be used for rate limiting discovery request calls. If not set, a * default value of 100 will be used. */ - 'max_tokens'?: (_google_protobuf_UInt32Value); + 'max_tokens'?: (_google_protobuf_UInt32Value | null); /** * Rate at which tokens will be filled per second. If not set, a default fill rate of 10 tokens * per second will be used. */ - 'fill_rate'?: (_google_protobuf_DoubleValue); + 'fill_rate'?: (_google_protobuf_DoubleValue | null); } /** @@ -27,10 +27,10 @@ export interface RateLimitSettings__Output { * Maximum number of tokens to be used for rate limiting discovery request calls. If not set, a * default value of 100 will be used. */ - 'max_tokens'?: (_google_protobuf_UInt32Value__Output); + 'max_tokens': (_google_protobuf_UInt32Value__Output | null); /** * Rate at which tokens will be filled per second. If not set, a default fill rate of 10 tokens * per second will be used. */ - 'fill_rate'?: (_google_protobuf_DoubleValue__Output); + 'fill_rate': (_google_protobuf_DoubleValue__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RemoteDataSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RemoteDataSource.ts new file mode 100644 index 000000000..917304d97 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RemoteDataSource.ts @@ -0,0 +1,40 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + +import type { HttpUri as _envoy_config_core_v3_HttpUri, HttpUri__Output as _envoy_config_core_v3_HttpUri__Output } from '../../../../envoy/config/core/v3/HttpUri'; +import type { RetryPolicy as _envoy_config_core_v3_RetryPolicy, RetryPolicy__Output as _envoy_config_core_v3_RetryPolicy__Output } from '../../../../envoy/config/core/v3/RetryPolicy'; + +/** + * The message specifies how to fetch data from remote and how to verify it. + */ +export interface RemoteDataSource { + /** + * The HTTP URI to fetch the remote data. + */ + 'http_uri'?: (_envoy_config_core_v3_HttpUri | null); + /** + * SHA256 string for verifying data. + */ + 'sha256'?: (string); + /** + * Retry policy for fetching remote data. + */ + 'retry_policy'?: (_envoy_config_core_v3_RetryPolicy | null); +} + +/** + * The message specifies how to fetch data from remote and how to verify it. + */ +export interface RemoteDataSource__Output { + /** + * The HTTP URI to fetch the remote data. + */ + 'http_uri': (_envoy_config_core_v3_HttpUri__Output | null); + /** + * SHA256 string for verifying data. + */ + 'sha256': (string); + /** + * Retry policy for fetching remote data. + */ + 'retry_policy': (_envoy_config_core_v3_RetryPolicy__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RequestMethod.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RequestMethod.ts similarity index 75% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RequestMethod.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RequestMethod.ts index 029e9882d..9be1aa6d1 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RequestMethod.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RequestMethod.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** * HTTP request method. diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RetryPolicy.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RetryPolicy.ts similarity index 63% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RetryPolicy.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RetryPolicy.ts index 27c1096b7..6e2af23e6 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RetryPolicy.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RetryPolicy.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto -import type { BackoffStrategy as _envoy_api_v2_core_BackoffStrategy, BackoffStrategy__Output as _envoy_api_v2_core_BackoffStrategy__Output } from '../../../../envoy/api/v2/core/BackoffStrategy'; +import type { BackoffStrategy as _envoy_config_core_v3_BackoffStrategy, BackoffStrategy__Output as _envoy_config_core_v3_BackoffStrategy__Output } from '../../../../envoy/config/core/v3/BackoffStrategy'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; /** @@ -8,16 +8,16 @@ import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output a */ export interface RetryPolicy { /** - * Specifies parameters that control :ref:`retry backoff strategy `. + * Specifies parameters that control :ref:`retry backoff strategy `. * This parameter is optional, in which case the default base interval is 1000 milliseconds. The * default maximum interval is 10 times the base interval. */ - 'retry_back_off'?: (_envoy_api_v2_core_BackoffStrategy); + 'retry_back_off'?: (_envoy_config_core_v3_BackoffStrategy | null); /** * Specifies the allowed number of retries. This parameter is optional and * defaults to 1. */ - 'num_retries'?: (_google_protobuf_UInt32Value); + 'num_retries'?: (_google_protobuf_UInt32Value | null); } /** @@ -25,14 +25,14 @@ export interface RetryPolicy { */ export interface RetryPolicy__Output { /** - * Specifies parameters that control :ref:`retry backoff strategy `. + * Specifies parameters that control :ref:`retry backoff strategy `. * This parameter is optional, in which case the default base interval is 1000 milliseconds. The * default maximum interval is 10 times the base interval. */ - 'retry_back_off'?: (_envoy_api_v2_core_BackoffStrategy__Output); + 'retry_back_off': (_envoy_config_core_v3_BackoffStrategy__Output | null); /** * Specifies the allowed number of retries. This parameter is optional and * defaults to 1. */ - 'num_retries'?: (_google_protobuf_UInt32Value__Output); + 'num_retries': (_google_protobuf_UInt32Value__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RoutingPriority.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RoutingPriority.ts similarity index 89% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RoutingPriority.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RoutingPriority.ts index 5937fceb2..917d8a3df 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RoutingPriority.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RoutingPriority.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** * Envoy supports :ref:`upstream priority routing diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeDouble.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeDouble.ts similarity index 86% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeDouble.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeDouble.ts index 8d9aba3e0..a0f849ab5 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeDouble.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeDouble.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** @@ -22,7 +22,7 @@ export interface RuntimeDouble__Output { /** * Default value if runtime value is not available. */ - 'default_value': (number | string); + 'default_value': (number); /** * Runtime key to get value for comparison. This value is used if defined. */ diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeFeatureFlag.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeFeatureFlag.ts similarity index 84% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeFeatureFlag.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeFeatureFlag.ts index 47cf24097..b6df8d617 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeFeatureFlag.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeFeatureFlag.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; @@ -9,7 +9,7 @@ export interface RuntimeFeatureFlag { /** * Default value if runtime value is not available. */ - 'default_value'?: (_google_protobuf_BoolValue); + 'default_value'?: (_google_protobuf_BoolValue | null); /** * Runtime key to get value for comparison. This value is used if defined. The boolean value must * be represented via its @@ -25,7 +25,7 @@ export interface RuntimeFeatureFlag__Output { /** * Default value if runtime value is not available. */ - 'default_value'?: (_google_protobuf_BoolValue__Output); + 'default_value': (_google_protobuf_BoolValue__Output | null); /** * Runtime key to get value for comparison. This value is used if defined. The boolean value must * be represented via its diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeFractionalPercent.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeFractionalPercent.ts similarity index 72% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeFractionalPercent.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeFractionalPercent.ts index 08e29de1f..3a2073294 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeFractionalPercent.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeFractionalPercent.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto -import type { FractionalPercent as _envoy_type_FractionalPercent, FractionalPercent__Output as _envoy_type_FractionalPercent__Output } from '../../../../envoy/type/FractionalPercent'; +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../envoy/type/v3/FractionalPercent'; /** * Runtime derived FractionalPercent with defaults for when the numerator or denominator is not @@ -9,7 +9,7 @@ import type { FractionalPercent as _envoy_type_FractionalPercent, FractionalPerc * .. note:: * * Parsing of the runtime key's data is implemented such that it may be represented as a - * :ref:`FractionalPercent ` proto represented as JSON/YAML + * :ref:`FractionalPercent ` proto represented as JSON/YAML * and may also be represented as an integer with the assumption that the value is an integral * percentage out of 100. For instance, a runtime key lookup returning the value "42" would parse * as a `FractionalPercent` whose numerator is 42 and denominator is HUNDRED. @@ -18,7 +18,7 @@ export interface RuntimeFractionalPercent { /** * Default value if the runtime value's for the numerator/denominator keys are not available. */ - 'default_value'?: (_envoy_type_FractionalPercent); + 'default_value'?: (_envoy_type_v3_FractionalPercent | null); /** * Runtime key for a YAML representation of a FractionalPercent. */ @@ -32,7 +32,7 @@ export interface RuntimeFractionalPercent { * .. note:: * * Parsing of the runtime key's data is implemented such that it may be represented as a - * :ref:`FractionalPercent ` proto represented as JSON/YAML + * :ref:`FractionalPercent ` proto represented as JSON/YAML * and may also be represented as an integer with the assumption that the value is an integral * percentage out of 100. For instance, a runtime key lookup returning the value "42" would parse * as a `FractionalPercent` whose numerator is 42 and denominator is HUNDRED. @@ -41,7 +41,7 @@ export interface RuntimeFractionalPercent__Output { /** * Default value if the runtime value's for the numerator/denominator keys are not available. */ - 'default_value'?: (_envoy_type_FractionalPercent__Output); + 'default_value': (_envoy_type_v3_FractionalPercent__Output | null); /** * Runtime key for a YAML representation of a FractionalPercent. */ diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimePercent.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimePercent.ts new file mode 100644 index 000000000..1dbe6ea4a --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimePercent.ts @@ -0,0 +1,31 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + +import type { Percent as _envoy_type_v3_Percent, Percent__Output as _envoy_type_v3_Percent__Output } from '../../../../envoy/type/v3/Percent'; + +/** + * Runtime derived percentage with a default when not specified. + */ +export interface RuntimePercent { + /** + * Default value if runtime value is not available. + */ + 'default_value'?: (_envoy_type_v3_Percent | null); + /** + * Runtime key to get value for comparison. This value is used if defined. + */ + 'runtime_key'?: (string); +} + +/** + * Runtime derived percentage with a default when not specified. + */ +export interface RuntimePercent__Output { + /** + * Default value if runtime value is not available. + */ + 'default_value': (_envoy_type_v3_Percent__Output | null); + /** + * Runtime key to get value for comparison. This value is used if defined. + */ + 'runtime_key': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeUInt32.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeUInt32.ts similarity index 90% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeUInt32.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeUInt32.ts index 72e8972a4..6cc9eead6 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/RuntimeUInt32.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/RuntimeUInt32.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SchemeHeaderTransformation.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SchemeHeaderTransformation.ts new file mode 100644 index 000000000..95bb4e400 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SchemeHeaderTransformation.ts @@ -0,0 +1,24 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + + +/** + * A message to control transformations to the :scheme header + */ +export interface SchemeHeaderTransformation { + /** + * Overwrite any Scheme header with the contents of this string. + */ + 'scheme_to_overwrite'?: (string); + 'transformation'?: "scheme_to_overwrite"; +} + +/** + * A message to control transformations to the :scheme header + */ +export interface SchemeHeaderTransformation__Output { + /** + * Overwrite any Scheme header with the contents of this string. + */ + 'scheme_to_overwrite'?: (string); + 'transformation': "scheme_to_overwrite"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SelfConfigSource.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SelfConfigSource.ts new file mode 100644 index 000000000..3912fd1cf --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SelfConfigSource.ts @@ -0,0 +1,31 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/config_source.proto + +import type { ApiVersion as _envoy_config_core_v3_ApiVersion } from '../../../../envoy/config/core/v3/ApiVersion'; + +/** + * [#not-implemented-hide:] + * Self-referencing config source options. This is currently empty, but when + * set in :ref:`ConfigSource ` can be used to + * specify that other data can be obtained from the same server. + */ +export interface SelfConfigSource { + /** + * API version for xDS transport protocol. This describes the xDS gRPC/REST + * endpoint and version of [Delta]DiscoveryRequest/Response used on the wire. + */ + 'transport_api_version'?: (_envoy_config_core_v3_ApiVersion | keyof typeof _envoy_config_core_v3_ApiVersion); +} + +/** + * [#not-implemented-hide:] + * Self-referencing config source options. This is currently empty, but when + * set in :ref:`ConfigSource ` can be used to + * specify that other data can be obtained from the same server. + */ +export interface SelfConfigSource__Output { + /** + * API version for xDS transport protocol. This describes the xDS gRPC/REST + * endpoint and version of [Delta]DiscoveryRequest/Response used on the wire. + */ + 'transport_api_version': (keyof typeof _envoy_config_core_v3_ApiVersion); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/SocketAddress.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SocketAddress.ts similarity index 71% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/SocketAddress.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/SocketAddress.ts index f81c981c1..3966dc04c 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/SocketAddress.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SocketAddress.ts @@ -1,9 +1,9 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/address.proto +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto -// Original file: deps/envoy-api/envoy/api/v2/core/address.proto +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto -export enum _envoy_api_v2_core_SocketAddress_Protocol { +export enum _envoy_config_core_v3_SocketAddress_Protocol { TCP = 0, UDP = 1, } @@ -12,25 +12,25 @@ export enum _envoy_api_v2_core_SocketAddress_Protocol { * [#next-free-field: 7] */ export interface SocketAddress { - 'protocol'?: (_envoy_api_v2_core_SocketAddress_Protocol | keyof typeof _envoy_api_v2_core_SocketAddress_Protocol); + 'protocol'?: (_envoy_config_core_v3_SocketAddress_Protocol | keyof typeof _envoy_config_core_v3_SocketAddress_Protocol); /** * The address for this socket. :ref:`Listeners ` will bind * to the address. An empty address is not allowed. Specify ``0.0.0.0`` or ``::`` * to bind to any address. [#comment:TODO(zuercher) reinstate when implemented: * It is possible to distinguish a Listener address via the prefix/suffix matching - * in :ref:`FilterChainMatch `.] When used - * within an upstream :ref:`BindConfig `, the address + * in :ref:`FilterChainMatch `.] When used + * within an upstream :ref:`BindConfig `, the address * controls the source address of outbound connections. For :ref:`clusters - * `, the cluster type determines whether the + * `, the cluster type determines whether the * address must be an IP (*STATIC* or *EDS* clusters) or a hostname resolved by DNS * (*STRICT_DNS* or *LOGICAL_DNS* clusters). Address resolution can be customized - * via :ref:`resolver_name `. + * via :ref:`resolver_name `. */ 'address'?: (string); 'port_value'?: (number); /** * This is only valid if :ref:`resolver_name - * ` is specified below and the + * ` is specified below and the * named resolver is capable of named port resolution. */ 'named_port'?: (string); @@ -56,25 +56,25 @@ export interface SocketAddress { * [#next-free-field: 7] */ export interface SocketAddress__Output { - 'protocol': (keyof typeof _envoy_api_v2_core_SocketAddress_Protocol); + 'protocol': (keyof typeof _envoy_config_core_v3_SocketAddress_Protocol); /** * The address for this socket. :ref:`Listeners ` will bind * to the address. An empty address is not allowed. Specify ``0.0.0.0`` or ``::`` * to bind to any address. [#comment:TODO(zuercher) reinstate when implemented: * It is possible to distinguish a Listener address via the prefix/suffix matching - * in :ref:`FilterChainMatch `.] When used - * within an upstream :ref:`BindConfig `, the address + * in :ref:`FilterChainMatch `.] When used + * within an upstream :ref:`BindConfig `, the address * controls the source address of outbound connections. For :ref:`clusters - * `, the cluster type determines whether the + * `, the cluster type determines whether the * address must be an IP (*STATIC* or *EDS* clusters) or a hostname resolved by DNS * (*STRICT_DNS* or *LOGICAL_DNS* clusters). Address resolution can be customized - * via :ref:`resolver_name `. + * via :ref:`resolver_name `. */ 'address': (string); 'port_value'?: (number); /** * This is only valid if :ref:`resolver_name - * ` is specified below and the + * ` is specified below and the * named resolver is capable of named port resolution. */ 'named_port'?: (string); diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/SocketOption.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SocketOption.ts similarity index 85% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/SocketOption.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/SocketOption.ts index 4a32e46b4..56f13c339 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/SocketOption.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SocketOption.ts @@ -1,10 +1,10 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/socket_option.proto +// Original file: deps/envoy-api/envoy/config/core/v3/socket_option.proto import type { Long } from '@grpc/proto-loader'; -// Original file: deps/envoy-api/envoy/api/v2/core/socket_option.proto +// Original file: deps/envoy-api/envoy/config/core/v3/socket_option.proto -export enum _envoy_api_v2_core_SocketOption_SocketState { +export enum _envoy_config_core_v3_SocketOption_SocketState { /** * Socket options are applied after socket creation but before binding the socket to a port */ @@ -50,7 +50,7 @@ export interface SocketOption { * The state in which the option will be applied. When used in BindConfig * STATE_PREBIND is currently the only valid value. */ - 'state'?: (_envoy_api_v2_core_SocketOption_SocketState | keyof typeof _envoy_api_v2_core_SocketOption_SocketState); + 'state'?: (_envoy_config_core_v3_SocketOption_SocketState | keyof typeof _envoy_config_core_v3_SocketOption_SocketState); 'value'?: "int_value"|"buf_value"; } @@ -85,6 +85,6 @@ export interface SocketOption__Output { * The state in which the option will be applied. When used in BindConfig * STATE_PREBIND is currently the only valid value. */ - 'state': (keyof typeof _envoy_api_v2_core_SocketOption_SocketState); + 'state': (keyof typeof _envoy_config_core_v3_SocketOption_SocketState); 'value': "int_value"|"buf_value"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SubstitutionFormatString.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SubstitutionFormatString.ts new file mode 100644 index 000000000..a935fc1ec --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/SubstitutionFormatString.ts @@ -0,0 +1,199 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/substitution_format_string.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../envoy/config/core/v3/DataSource'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +/** + * Configuration to use multiple :ref:`command operators ` + * to generate a new string in either plain text or JSON format. + * [#next-free-field: 7] + */ +export interface SubstitutionFormatString { + /** + * Specify a format with command operators to form a text string. + * Its details is described in :ref:`format string`. + * + * For example, setting ``text_format`` like below, + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * text_format: "%LOCAL_REPLY_BODY%:%RESPONSE_CODE%:path=%REQ(:path)%\n" + * + * generates plain text similar to: + * + * .. code-block:: text + * + * upstream connect error:503:path=/foo + * + * Deprecated in favor of :ref:`text_format_source `. To migrate text format strings, use the :ref:`inline_string ` field. + */ + 'text_format'?: (string); + /** + * Specify a format with command operators to form a JSON string. + * Its details is described in :ref:`format dictionary`. + * Values are rendered as strings, numbers, or boolean values as appropriate. + * Nested JSON objects may be produced by some command operators (e.g. FILTER_STATE or DYNAMIC_METADATA). + * See the documentation for a specific command operator for details. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * json_format: + * status: "%RESPONSE_CODE%" + * message: "%LOCAL_REPLY_BODY%" + * + * The following JSON object would be created: + * + * .. code-block:: json + * + * { + * "status": 500, + * "message": "My error message" + * } + */ + 'json_format'?: (_google_protobuf_Struct | null); + /** + * If set to true, when command operators are evaluated to null, + * + * * for ``text_format``, the output of the empty operator is changed from ``-`` to an + * empty string, so that empty values are omitted entirely. + * * for ``json_format`` the keys with null values are omitted in the output structure. + */ + 'omit_empty_values'?: (boolean); + /** + * Specify a *content_type* field. + * If this field is not set then ``text/plain`` is used for *text_format* and + * ``application/json`` is used for *json_format*. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * content_type: "text/html; charset=UTF-8" + */ + 'content_type'?: (string); + /** + * Specify a format with command operators to form a text string. + * Its details is described in :ref:`format string`. + * + * For example, setting ``text_format`` like below, + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * text_format_source: + * inline_string: "%LOCAL_REPLY_BODY%:%RESPONSE_CODE%:path=%REQ(:path)%\n" + * + * generates plain text similar to: + * + * .. code-block:: text + * + * upstream connect error:503:path=/foo + */ + 'text_format_source'?: (_envoy_config_core_v3_DataSource | null); + /** + * Specifies a collection of Formatter plugins that can be called from the access log configuration. + * See the formatters extensions documentation for details. + * [#extension-category: envoy.formatter] + */ + 'formatters'?: (_envoy_config_core_v3_TypedExtensionConfig)[]; + 'format'?: "text_format"|"json_format"|"text_format_source"; +} + +/** + * Configuration to use multiple :ref:`command operators ` + * to generate a new string in either plain text or JSON format. + * [#next-free-field: 7] + */ +export interface SubstitutionFormatString__Output { + /** + * Specify a format with command operators to form a text string. + * Its details is described in :ref:`format string`. + * + * For example, setting ``text_format`` like below, + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * text_format: "%LOCAL_REPLY_BODY%:%RESPONSE_CODE%:path=%REQ(:path)%\n" + * + * generates plain text similar to: + * + * .. code-block:: text + * + * upstream connect error:503:path=/foo + * + * Deprecated in favor of :ref:`text_format_source `. To migrate text format strings, use the :ref:`inline_string ` field. + */ + 'text_format'?: (string); + /** + * Specify a format with command operators to form a JSON string. + * Its details is described in :ref:`format dictionary`. + * Values are rendered as strings, numbers, or boolean values as appropriate. + * Nested JSON objects may be produced by some command operators (e.g. FILTER_STATE or DYNAMIC_METADATA). + * See the documentation for a specific command operator for details. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * json_format: + * status: "%RESPONSE_CODE%" + * message: "%LOCAL_REPLY_BODY%" + * + * The following JSON object would be created: + * + * .. code-block:: json + * + * { + * "status": 500, + * "message": "My error message" + * } + */ + 'json_format'?: (_google_protobuf_Struct__Output | null); + /** + * If set to true, when command operators are evaluated to null, + * + * * for ``text_format``, the output of the empty operator is changed from ``-`` to an + * empty string, so that empty values are omitted entirely. + * * for ``json_format`` the keys with null values are omitted in the output structure. + */ + 'omit_empty_values': (boolean); + /** + * Specify a *content_type* field. + * If this field is not set then ``text/plain`` is used for *text_format* and + * ``application/json`` is used for *json_format*. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * content_type: "text/html; charset=UTF-8" + */ + 'content_type': (string); + /** + * Specify a format with command operators to form a text string. + * Its details is described in :ref:`format string`. + * + * For example, setting ``text_format`` like below, + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * text_format_source: + * inline_string: "%LOCAL_REPLY_BODY%:%RESPONSE_CODE%:path=%REQ(:path)%\n" + * + * generates plain text similar to: + * + * .. code-block:: text + * + * upstream connect error:503:path=/foo + */ + 'text_format_source'?: (_envoy_config_core_v3_DataSource__Output | null); + /** + * Specifies a collection of Formatter plugins that can be called from the access log configuration. + * See the formatters extensions documentation for details. + * [#extension-category: envoy.formatter] + */ + 'formatters': (_envoy_config_core_v3_TypedExtensionConfig__Output)[]; + 'format': "text_format"|"json_format"|"text_format_source"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TcpKeepalive.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TcpKeepalive.ts similarity index 75% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/TcpKeepalive.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/TcpKeepalive.ts index 394a54feb..1ad81091d 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TcpKeepalive.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TcpKeepalive.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/address.proto +// Original file: deps/envoy-api/envoy/config/core/v3/address.proto import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; @@ -8,18 +8,18 @@ export interface TcpKeepalive { * the connection is dead. Default is to use the OS level configuration (unless * overridden, Linux defaults to 9.) */ - 'keepalive_probes'?: (_google_protobuf_UInt32Value); + 'keepalive_probes'?: (_google_protobuf_UInt32Value | null); /** * The number of seconds a connection needs to be idle before keep-alive probes * start being sent. Default is to use the OS level configuration (unless * overridden, Linux defaults to 7200s (i.e., 2 hours.) */ - 'keepalive_time'?: (_google_protobuf_UInt32Value); + 'keepalive_time'?: (_google_protobuf_UInt32Value | null); /** * The number of seconds between keep-alive probes. Default is to use the OS * level configuration (unless overridden, Linux defaults to 75s.) */ - 'keepalive_interval'?: (_google_protobuf_UInt32Value); + 'keepalive_interval'?: (_google_protobuf_UInt32Value | null); } export interface TcpKeepalive__Output { @@ -28,16 +28,16 @@ export interface TcpKeepalive__Output { * the connection is dead. Default is to use the OS level configuration (unless * overridden, Linux defaults to 9.) */ - 'keepalive_probes'?: (_google_protobuf_UInt32Value__Output); + 'keepalive_probes': (_google_protobuf_UInt32Value__Output | null); /** * The number of seconds a connection needs to be idle before keep-alive probes * start being sent. Default is to use the OS level configuration (unless * overridden, Linux defaults to 7200s (i.e., 2 hours.) */ - 'keepalive_time'?: (_google_protobuf_UInt32Value__Output); + 'keepalive_time': (_google_protobuf_UInt32Value__Output | null); /** * The number of seconds between keep-alive probes. Default is to use the OS * level configuration (unless overridden, Linux defaults to 75s.) */ - 'keepalive_interval'?: (_google_protobuf_UInt32Value__Output); + 'keepalive_interval': (_google_protobuf_UInt32Value__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TcpProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TcpProtocolOptions.ts similarity index 70% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/TcpProtocolOptions.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/TcpProtocolOptions.ts index bb7afc1d1..28239f63e 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TcpProtocolOptions.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TcpProtocolOptions.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/protocol.proto +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TrafficDirection.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TrafficDirection.ts similarity index 83% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/TrafficDirection.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/TrafficDirection.ts index 41cf36523..b68323b09 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TrafficDirection.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TrafficDirection.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto /** * Identifies the direction of the traffic relative to the local Envoy. diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TransportSocket.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TransportSocket.ts similarity index 69% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/core/TransportSocket.ts rename to packages/grpc-js-xds/src/generated/envoy/config/core/v3/TransportSocket.ts index b45767eb2..ff05991ad 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/core/TransportSocket.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TransportSocket.ts @@ -1,11 +1,10 @@ -// Original file: deps/envoy-api/envoy/api/v2/core/base.proto +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; /** * Configuration for transport socket in :ref:`listeners ` and - * :ref:`clusters `. If the configuration is + * :ref:`clusters `. If the configuration is * empty, a default transport socket implementation and configuration will be * chosen based on the platform and existence of tls_context. */ @@ -15,18 +14,17 @@ export interface TransportSocket { * socket implementation. */ 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); + 'typed_config'?: (_google_protobuf_Any | null); /** * Implementation specific configuration which depends on the implementation being instantiated. * See the supported transport socket implementations for further documentation. */ - 'config_type'?: "config"|"typed_config"; + 'config_type'?: "typed_config"; } /** * Configuration for transport socket in :ref:`listeners ` and - * :ref:`clusters `. If the configuration is + * :ref:`clusters `. If the configuration is * empty, a default transport socket implementation and configuration will be * chosen based on the platform and existence of tls_context. */ @@ -36,11 +34,10 @@ export interface TransportSocket__Output { * socket implementation. */ 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); + 'typed_config'?: (_google_protobuf_Any__Output | null); /** * Implementation specific configuration which depends on the implementation being instantiated. * See the supported transport socket implementations for further documentation. */ - 'config_type': "config"|"typed_config"; + 'config_type': "typed_config"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TypedExtensionConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TypedExtensionConfig.ts new file mode 100644 index 000000000..d653f9373 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/TypedExtensionConfig.ts @@ -0,0 +1,43 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/extension.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +/** + * Message type for extension configuration. + * [#next-major-version: revisit all existing typed_config that doesn't use this wrapper.]. + */ +export interface TypedExtensionConfig { + /** + * The name of an extension. This is not used to select the extension, instead + * it serves the role of an opaque identifier. + */ + 'name'?: (string); + /** + * The typed config for the extension. The type URL will be used to identify + * the extension. In the case that the type URL is *udpa.type.v1.TypedStruct*, + * the inner type URL of *TypedStruct* will be utilized. See the + * :ref:`extension configuration overview + * ` for further details. + */ + 'typed_config'?: (_google_protobuf_Any | null); +} + +/** + * Message type for extension configuration. + * [#next-major-version: revisit all existing typed_config that doesn't use this wrapper.]. + */ +export interface TypedExtensionConfig__Output { + /** + * The name of an extension. This is not used to select the extension, instead + * it serves the role of an opaque identifier. + */ + 'name': (string); + /** + * The typed config for the extension. The type URL will be used to identify + * the extension. In the case that the type URL is *udpa.type.v1.TypedStruct*, + * the inner type URL of *TypedStruct* will be utilized. See the + * :ref:`extension configuration overview + * ` for further details. + */ + 'typed_config': (_google_protobuf_Any__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/UdpSocketConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/UdpSocketConfig.ts new file mode 100644 index 000000000..fe1b038db --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/UdpSocketConfig.ts @@ -0,0 +1,45 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/udp_socket_config.proto + +import type { UInt64Value as _google_protobuf_UInt64Value, UInt64Value__Output as _google_protobuf_UInt64Value__Output } from '../../../../google/protobuf/UInt64Value'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { Long } from '@grpc/proto-loader'; + +/** + * Generic UDP socket configuration. + */ +export interface UdpSocketConfig { + /** + * The maximum size of received UDP datagrams. Using a larger size will cause Envoy to allocate + * more memory per socket. Received datagrams above this size will be dropped. If not set + * defaults to 1500 bytes. + */ + 'max_rx_datagram_size'?: (_google_protobuf_UInt64Value | null); + /** + * Configures whether Generic Receive Offload (GRO) + * _ is preferred when reading from the + * UDP socket. The default is context dependent and is documented where UdpSocketConfig is used. + * This option affects performance but not functionality. If GRO is not supported by the operating + * system, non-GRO receive will be used. + */ + 'prefer_gro'?: (_google_protobuf_BoolValue | null); +} + +/** + * Generic UDP socket configuration. + */ +export interface UdpSocketConfig__Output { + /** + * The maximum size of received UDP datagrams. Using a larger size will cause Envoy to allocate + * more memory per socket. Received datagrams above this size will be dropped. If not set + * defaults to 1500 bytes. + */ + 'max_rx_datagram_size': (_google_protobuf_UInt64Value__Output | null); + /** + * Configures whether Generic Receive Offload (GRO) + * _ is preferred when reading from the + * UDP socket. The default is context dependent and is documented where UdpSocketConfig is used. + * This option affects performance but not functionality. If GRO is not supported by the operating + * system, non-GRO receive will be used. + */ + 'prefer_gro': (_google_protobuf_BoolValue__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/UpstreamHttpProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/UpstreamHttpProtocolOptions.ts new file mode 100644 index 000000000..c0da4159f --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/UpstreamHttpProtocolOptions.ts @@ -0,0 +1,56 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/protocol.proto + + +export interface UpstreamHttpProtocolOptions { + /** + * Set transport socket `SNI `_ for new + * upstream connections based on the downstream HTTP host/authority header or any other arbitrary + * header when :ref:`override_auto_sni_header ` + * is set, as seen by the :ref:`router filter `. + */ + 'auto_sni'?: (boolean); + /** + * Automatic validate upstream presented certificate for new upstream connections based on the + * downstream HTTP host/authority header or any other arbitrary header when :ref:`override_auto_sni_header ` + * is set, as seen by the :ref:`router filter `. + * This field is intended to be set with `auto_sni` field. + */ + 'auto_san_validation'?: (boolean); + /** + * An optional alternative to the host/authority header to be used for setting the SNI value. + * It should be a valid downstream HTTP header, as seen by the + * :ref:`router filter `. + * If unset, host/authority header will be used for populating the SNI. If the specified header + * is not found or the value is empty, host/authority header will be used instead. + * This field is intended to be set with `auto_sni` and/or `auto_san_validation` fields. + * If none of these fields are set then setting this would be a no-op. + */ + 'override_auto_sni_header'?: (string); +} + +export interface UpstreamHttpProtocolOptions__Output { + /** + * Set transport socket `SNI `_ for new + * upstream connections based on the downstream HTTP host/authority header or any other arbitrary + * header when :ref:`override_auto_sni_header ` + * is set, as seen by the :ref:`router filter `. + */ + 'auto_sni': (boolean); + /** + * Automatic validate upstream presented certificate for new upstream connections based on the + * downstream HTTP host/authority header or any other arbitrary header when :ref:`override_auto_sni_header ` + * is set, as seen by the :ref:`router filter `. + * This field is intended to be set with `auto_sni` field. + */ + 'auto_san_validation': (boolean); + /** + * An optional alternative to the host/authority header to be used for setting the SNI value. + * It should be a valid downstream HTTP header, as seen by the + * :ref:`router filter `. + * If unset, host/authority header will be used for populating the SNI. If the specified header + * is not found or the value is empty, host/authority header will be used instead. + * This field is intended to be set with `auto_sni` and/or `auto_san_validation` fields. + * If none of these fields are set then setting this would be a no-op. + */ + 'override_auto_sni_header': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/core/v3/WatchedDirectory.ts b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/WatchedDirectory.ts new file mode 100644 index 000000000..d6f0d124b --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/core/v3/WatchedDirectory.ts @@ -0,0 +1,24 @@ +// Original file: deps/envoy-api/envoy/config/core/v3/base.proto + + +/** + * A directory that is watched for changes, e.g. by inotify on Linux. Move/rename + * events inside this directory trigger the watch. + */ +export interface WatchedDirectory { + /** + * Directory path to watch. + */ + 'path'?: (string); +} + +/** + * A directory that is watched for changes, e.g. by inotify on Linux. Move/rename + * events inside this directory trigger the watch. + */ +export interface WatchedDirectory__Output { + /** + * Directory path to watch. + */ + 'path': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/ClusterLoadAssignment.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/ClusterLoadAssignment.ts similarity index 65% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/ClusterLoadAssignment.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/ClusterLoadAssignment.ts index 14598bec1..91ce2e0c8 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/ClusterLoadAssignment.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/ClusterLoadAssignment.ts @@ -1,15 +1,15 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/endpoint.proto -import type { LocalityLbEndpoints as _envoy_api_v2_endpoint_LocalityLbEndpoints, LocalityLbEndpoints__Output as _envoy_api_v2_endpoint_LocalityLbEndpoints__Output } from '../../../envoy/api/v2/endpoint/LocalityLbEndpoints'; -import type { Endpoint as _envoy_api_v2_endpoint_Endpoint, Endpoint__Output as _envoy_api_v2_endpoint_Endpoint__Output } from '../../../envoy/api/v2/endpoint/Endpoint'; -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../google/protobuf/UInt32Value'; -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; -import type { FractionalPercent as _envoy_type_FractionalPercent, FractionalPercent__Output as _envoy_type_FractionalPercent__Output } from '../../../envoy/type/FractionalPercent'; +import type { LocalityLbEndpoints as _envoy_config_endpoint_v3_LocalityLbEndpoints, LocalityLbEndpoints__Output as _envoy_config_endpoint_v3_LocalityLbEndpoints__Output } from '../../../../envoy/config/endpoint/v3/LocalityLbEndpoints'; +import type { Endpoint as _envoy_config_endpoint_v3_Endpoint, Endpoint__Output as _envoy_config_endpoint_v3_Endpoint__Output } from '../../../../envoy/config/endpoint/v3/Endpoint'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../envoy/type/v3/FractionalPercent'; /** * [#not-implemented-hide:] */ -export interface _envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload { +export interface _envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload { /** * Identifier for the policy specifying the drop. */ @@ -17,13 +17,13 @@ export interface _envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload { /** * Percentage of traffic that should be dropped for the category. */ - 'drop_percentage'?: (_envoy_type_FractionalPercent); + 'drop_percentage'?: (_envoy_type_v3_FractionalPercent | null); } /** * [#not-implemented-hide:] */ -export interface _envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload__Output { +export interface _envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload__Output { /** * Identifier for the policy specifying the drop. */ @@ -31,14 +31,14 @@ export interface _envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload__Output /** * Percentage of traffic that should be dropped for the category. */ - 'drop_percentage'?: (_envoy_type_FractionalPercent__Output); + 'drop_percentage': (_envoy_type_v3_FractionalPercent__Output | null); } /** * Load balancing policy settings. * [#next-free-field: 6] */ -export interface _envoy_api_v2_ClusterLoadAssignment_Policy { +export interface _envoy_config_endpoint_v3_ClusterLoadAssignment_Policy { /** * Action to trim the overall incoming traffic to protect the upstream * hosts. This action allows protection in case the hosts are unable to @@ -61,11 +61,11 @@ export interface _envoy_api_v2_ClusterLoadAssignment_Policy { * actual_outgoing_load = 20% // remaining after applying all categories. * [#not-implemented-hide:] */ - 'drop_overloads'?: (_envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload)[]; + 'drop_overloads'?: (_envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload)[]; /** * Priority levels and localities are considered overprovisioned with this * factor (in percentage). This means that we don't consider a priority - * level or locality unhealthy until the percentage of healthy hosts + * level or locality unhealthy until the fraction of healthy hosts * multiplied by the overprovisioning factor drops below 100. * With the default value 140(1.4), Envoy doesn't consider a priority level * or a locality unhealthy until their percentage of healthy hosts drops @@ -78,32 +78,21 @@ export interface _envoy_api_v2_ClusterLoadAssignment_Policy { * Read more at :ref:`priority levels ` and * :ref:`localities `. */ - 'overprovisioning_factor'?: (_google_protobuf_UInt32Value); + 'overprovisioning_factor'?: (_google_protobuf_UInt32Value | null); /** * The max time until which the endpoints from this assignment can be used. * If no new assignments are received before this time expires the endpoints * are considered stale and should be marked unhealthy. * Defaults to 0 which means endpoints never go stale. */ - 'endpoint_stale_after'?: (_google_protobuf_Duration); - /** - * The flag to disable overprovisioning. If it is set to true, - * :ref:`overprovisioning factor - * ` will be ignored - * and Envoy will not perform graceful failover between priority levels or - * localities as endpoints become unhealthy. Otherwise Envoy will perform - * graceful failover as :ref:`overprovisioning factor - * ` suggests. - * [#not-implemented-hide:] - */ - 'disable_overprovisioning'?: (boolean); + 'endpoint_stale_after'?: (_google_protobuf_Duration | null); } /** * Load balancing policy settings. * [#next-free-field: 6] */ -export interface _envoy_api_v2_ClusterLoadAssignment_Policy__Output { +export interface _envoy_config_endpoint_v3_ClusterLoadAssignment_Policy__Output { /** * Action to trim the overall incoming traffic to protect the upstream * hosts. This action allows protection in case the hosts are unable to @@ -126,11 +115,11 @@ export interface _envoy_api_v2_ClusterLoadAssignment_Policy__Output { * actual_outgoing_load = 20% // remaining after applying all categories. * [#not-implemented-hide:] */ - 'drop_overloads': (_envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload__Output)[]; + 'drop_overloads': (_envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload__Output)[]; /** * Priority levels and localities are considered overprovisioned with this * factor (in percentage). This means that we don't consider a priority - * level or locality unhealthy until the percentage of healthy hosts + * level or locality unhealthy until the fraction of healthy hosts * multiplied by the overprovisioning factor drops below 100. * With the default value 140(1.4), Envoy doesn't consider a priority level * or a locality unhealthy until their percentage of healthy hosts drops @@ -143,25 +132,14 @@ export interface _envoy_api_v2_ClusterLoadAssignment_Policy__Output { * Read more at :ref:`priority levels ` and * :ref:`localities `. */ - 'overprovisioning_factor'?: (_google_protobuf_UInt32Value__Output); + 'overprovisioning_factor': (_google_protobuf_UInt32Value__Output | null); /** * The max time until which the endpoints from this assignment can be used. * If no new assignments are received before this time expires the endpoints * are considered stale and should be marked unhealthy. * Defaults to 0 which means endpoints never go stale. */ - 'endpoint_stale_after'?: (_google_protobuf_Duration__Output); - /** - * The flag to disable overprovisioning. If it is set to true, - * :ref:`overprovisioning factor - * ` will be ignored - * and Envoy will not perform graceful failover between priority levels or - * localities as endpoints become unhealthy. Otherwise Envoy will perform - * graceful failover as :ref:`overprovisioning factor - * ` suggests. - * [#not-implemented-hide:] - */ - 'disable_overprovisioning': (boolean); + 'endpoint_stale_after': (_google_protobuf_Duration__Output | null); } /** @@ -179,24 +157,24 @@ export interface _envoy_api_v2_ClusterLoadAssignment_Policy__Output { export interface ClusterLoadAssignment { /** * Name of the cluster. This will be the :ref:`service_name - * ` value if specified + * ` value if specified * in the cluster :ref:`EdsClusterConfig - * `. + * `. */ 'cluster_name'?: (string); /** * List of endpoints to load balance to. */ - 'endpoints'?: (_envoy_api_v2_endpoint_LocalityLbEndpoints)[]; + 'endpoints'?: (_envoy_config_endpoint_v3_LocalityLbEndpoints)[]; /** * Load balancing policy settings. */ - 'policy'?: (_envoy_api_v2_ClusterLoadAssignment_Policy); + 'policy'?: (_envoy_config_endpoint_v3_ClusterLoadAssignment_Policy | null); /** * Map of named endpoints that can be referenced in LocalityLbEndpoints. * [#not-implemented-hide:] */ - 'named_endpoints'?: ({[key: string]: _envoy_api_v2_endpoint_Endpoint}); + 'named_endpoints'?: ({[key: string]: _envoy_config_endpoint_v3_Endpoint}); } /** @@ -214,22 +192,22 @@ export interface ClusterLoadAssignment { export interface ClusterLoadAssignment__Output { /** * Name of the cluster. This will be the :ref:`service_name - * ` value if specified + * ` value if specified * in the cluster :ref:`EdsClusterConfig - * `. + * `. */ 'cluster_name': (string); /** * List of endpoints to load balance to. */ - 'endpoints': (_envoy_api_v2_endpoint_LocalityLbEndpoints__Output)[]; + 'endpoints': (_envoy_config_endpoint_v3_LocalityLbEndpoints__Output)[]; /** * Load balancing policy settings. */ - 'policy'?: (_envoy_api_v2_ClusterLoadAssignment_Policy__Output); + 'policy': (_envoy_config_endpoint_v3_ClusterLoadAssignment_Policy__Output | null); /** * Map of named endpoints that can be referenced in LocalityLbEndpoints. * [#not-implemented-hide:] */ - 'named_endpoints'?: ({[key: string]: _envoy_api_v2_endpoint_Endpoint__Output}); + 'named_endpoints': ({[key: string]: _envoy_config_endpoint_v3_Endpoint__Output}); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/ClusterStats.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/ClusterStats.ts similarity index 73% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/ClusterStats.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/ClusterStats.ts index 4b5c30f4c..c160333b2 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/ClusterStats.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/ClusterStats.ts @@ -1,10 +1,10 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint/load_report.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/load_report.proto -import type { UpstreamLocalityStats as _envoy_api_v2_endpoint_UpstreamLocalityStats, UpstreamLocalityStats__Output as _envoy_api_v2_endpoint_UpstreamLocalityStats__Output } from '../../../../envoy/api/v2/endpoint/UpstreamLocalityStats'; +import type { UpstreamLocalityStats as _envoy_config_endpoint_v3_UpstreamLocalityStats, UpstreamLocalityStats__Output as _envoy_config_endpoint_v3_UpstreamLocalityStats__Output } from '../../../../envoy/config/endpoint/v3/UpstreamLocalityStats'; import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; import type { Long } from '@grpc/proto-loader'; -export interface _envoy_api_v2_endpoint_ClusterStats_DroppedRequests { +export interface _envoy_config_endpoint_v3_ClusterStats_DroppedRequests { /** * Identifier for the policy specifying the drop. */ @@ -15,7 +15,7 @@ export interface _envoy_api_v2_endpoint_ClusterStats_DroppedRequests { 'dropped_count'?: (number | string | Long); } -export interface _envoy_api_v2_endpoint_ClusterStats_DroppedRequests__Output { +export interface _envoy_config_endpoint_v3_ClusterStats_DroppedRequests__Output { /** * Identifier for the policy specifying the drop. */ @@ -28,8 +28,7 @@ export interface _envoy_api_v2_endpoint_ClusterStats_DroppedRequests__Output { /** * Per cluster load stats. Envoy reports these stats a management server in a - * :ref:`LoadStatsRequest` - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. + * :ref:`LoadStatsRequest` * Next ID: 7 * [#next-free-field: 7] */ @@ -41,7 +40,7 @@ export interface ClusterStats { /** * Need at least one. */ - 'upstream_locality_stats'?: (_envoy_api_v2_endpoint_UpstreamLocalityStats)[]; + 'upstream_locality_stats'?: (_envoy_config_endpoint_v3_UpstreamLocalityStats)[]; /** * Cluster-level stats such as total_successful_requests may be computed by * summing upstream_locality_stats. In addition, below there are additional @@ -57,12 +56,12 @@ export interface ClusterStats { * and the *LoadStatsResponse* message sent from the management server, this may be longer than * the requested load reporting interval in the *LoadStatsResponse*. */ - 'load_report_interval'?: (_google_protobuf_Duration); + 'load_report_interval'?: (_google_protobuf_Duration | null); /** * Information about deliberately dropped requests for each category specified * in the DropOverload policy. */ - 'dropped_requests'?: (_envoy_api_v2_endpoint_ClusterStats_DroppedRequests)[]; + 'dropped_requests'?: (_envoy_config_endpoint_v3_ClusterStats_DroppedRequests)[]; /** * The eds_cluster_config service_name of the cluster. * It's possible that two clusters send the same service_name to EDS, @@ -73,8 +72,7 @@ export interface ClusterStats { /** * Per cluster load stats. Envoy reports these stats a management server in a - * :ref:`LoadStatsRequest` - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. + * :ref:`LoadStatsRequest` * Next ID: 7 * [#next-free-field: 7] */ @@ -86,7 +84,7 @@ export interface ClusterStats__Output { /** * Need at least one. */ - 'upstream_locality_stats': (_envoy_api_v2_endpoint_UpstreamLocalityStats__Output)[]; + 'upstream_locality_stats': (_envoy_config_endpoint_v3_UpstreamLocalityStats__Output)[]; /** * Cluster-level stats such as total_successful_requests may be computed by * summing upstream_locality_stats. In addition, below there are additional @@ -102,12 +100,12 @@ export interface ClusterStats__Output { * and the *LoadStatsResponse* message sent from the management server, this may be longer than * the requested load reporting interval in the *LoadStatsResponse*. */ - 'load_report_interval'?: (_google_protobuf_Duration__Output); + 'load_report_interval': (_google_protobuf_Duration__Output | null); /** * Information about deliberately dropped requests for each category specified * in the DropOverload policy. */ - 'dropped_requests': (_envoy_api_v2_endpoint_ClusterStats_DroppedRequests__Output)[]; + 'dropped_requests': (_envoy_config_endpoint_v3_ClusterStats_DroppedRequests__Output)[]; /** * The eds_cluster_config service_name of the cluster. * It's possible that two clusters send the same service_name to EDS, diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/Endpoint.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/Endpoint.ts similarity index 69% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/Endpoint.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/Endpoint.ts index 68bef75e1..31eb09055 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/Endpoint.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/Endpoint.ts @@ -1,11 +1,11 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint/endpoint_components.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/endpoint_components.proto -import type { Address as _envoy_api_v2_core_Address, Address__Output as _envoy_api_v2_core_Address__Output } from '../../../../envoy/api/v2/core/Address'; +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; /** * The optional health check configuration. */ -export interface _envoy_api_v2_endpoint_Endpoint_HealthCheckConfig { +export interface _envoy_config_endpoint_v3_Endpoint_HealthCheckConfig { /** * Optional alternative health check port value. * @@ -17,8 +17,8 @@ export interface _envoy_api_v2_endpoint_Endpoint_HealthCheckConfig { 'port_value'?: (number); /** * By default, the host header for L7 health checks is controlled by cluster level configuration - * (see: :ref:`host ` and - * :ref:`authority `). Setting this + * (see: :ref:`host ` and + * :ref:`authority `). Setting this * to a non-empty value allows overriding the cluster level configuration for a specific * endpoint. */ @@ -28,7 +28,7 @@ export interface _envoy_api_v2_endpoint_Endpoint_HealthCheckConfig { /** * The optional health check configuration. */ -export interface _envoy_api_v2_endpoint_Endpoint_HealthCheckConfig__Output { +export interface _envoy_config_endpoint_v3_Endpoint_HealthCheckConfig__Output { /** * Optional alternative health check port value. * @@ -40,8 +40,8 @@ export interface _envoy_api_v2_endpoint_Endpoint_HealthCheckConfig__Output { 'port_value': (number); /** * By default, the host header for L7 health checks is controlled by cluster level configuration - * (see: :ref:`host ` and - * :ref:`authority `). Setting this + * (see: :ref:`host ` and + * :ref:`authority `). Setting this * to a non-empty value allows overriding the cluster level configuration for a specific * endpoint. */ @@ -59,11 +59,11 @@ export interface Endpoint { * * The form of host address depends on the given cluster type. For STATIC or EDS, * it is expected to be a direct IP address (or something resolvable by the - * specified :ref:`resolver ` + * specified :ref:`resolver ` * in the Address). For LOGICAL or STRICT DNS, it is expected to be hostname, * and will be resolved via DNS. */ - 'address'?: (_envoy_api_v2_core_Address); + 'address'?: (_envoy_config_core_v3_Address | null); /** * The optional health check configuration is used as configuration for the * health checker to contact the health checked host. @@ -73,12 +73,12 @@ export interface Endpoint { * This takes into effect only for upstream clusters with * :ref:`active health checking ` enabled. */ - 'health_check_config'?: (_envoy_api_v2_endpoint_Endpoint_HealthCheckConfig); + 'health_check_config'?: (_envoy_config_endpoint_v3_Endpoint_HealthCheckConfig | null); /** * The hostname associated with this endpoint. This hostname is not used for routing or address * resolution. If provided, it will be associated with the endpoint, and can be used for features * that require a hostname, like - * :ref:`auto_host_rewrite `. + * :ref:`auto_host_rewrite `. */ 'hostname'?: (string); } @@ -94,11 +94,11 @@ export interface Endpoint__Output { * * The form of host address depends on the given cluster type. For STATIC or EDS, * it is expected to be a direct IP address (or something resolvable by the - * specified :ref:`resolver ` + * specified :ref:`resolver ` * in the Address). For LOGICAL or STRICT DNS, it is expected to be hostname, * and will be resolved via DNS. */ - 'address'?: (_envoy_api_v2_core_Address__Output); + 'address': (_envoy_config_core_v3_Address__Output | null); /** * The optional health check configuration is used as configuration for the * health checker to contact the health checked host. @@ -108,12 +108,12 @@ export interface Endpoint__Output { * This takes into effect only for upstream clusters with * :ref:`active health checking ` enabled. */ - 'health_check_config'?: (_envoy_api_v2_endpoint_Endpoint_HealthCheckConfig__Output); + 'health_check_config': (_envoy_config_endpoint_v3_Endpoint_HealthCheckConfig__Output | null); /** * The hostname associated with this endpoint. This hostname is not used for routing or address * resolution. If provided, it will be associated with the endpoint, and can be used for features * that require a hostname, like - * :ref:`auto_host_rewrite `. + * :ref:`auto_host_rewrite `. */ 'hostname': (string); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/EndpointLoadMetricStats.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/EndpointLoadMetricStats.ts similarity index 75% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/EndpointLoadMetricStats.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/EndpointLoadMetricStats.ts index 9ed8016b7..50f63f4ca 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/EndpointLoadMetricStats.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/EndpointLoadMetricStats.ts @@ -1,10 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint/load_report.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/load_report.proto import type { Long } from '@grpc/proto-loader'; -/** - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. - */ export interface EndpointLoadMetricStats { /** * Name of the metric; may be empty. @@ -21,9 +18,6 @@ export interface EndpointLoadMetricStats { 'total_metric_value'?: (number | string); } -/** - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. - */ export interface EndpointLoadMetricStats__Output { /** * Name of the metric; may be empty. @@ -37,5 +31,5 @@ export interface EndpointLoadMetricStats__Output { * Sum of metric values across all calls that finished with this metric for * load_reporting_interval. */ - 'total_metric_value': (number | string); + 'total_metric_value': (number); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/LbEndpoint.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LbEndpoint.ts similarity index 70% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/LbEndpoint.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LbEndpoint.ts index 1f8be9305..6025ae3a7 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/LbEndpoint.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LbEndpoint.ts @@ -1,8 +1,8 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint/endpoint_components.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/endpoint_components.proto -import type { Endpoint as _envoy_api_v2_endpoint_Endpoint, Endpoint__Output as _envoy_api_v2_endpoint_Endpoint__Output } from '../../../../envoy/api/v2/endpoint/Endpoint'; -import type { HealthStatus as _envoy_api_v2_core_HealthStatus } from '../../../../envoy/api/v2/core/HealthStatus'; -import type { Metadata as _envoy_api_v2_core_Metadata, Metadata__Output as _envoy_api_v2_core_Metadata__Output } from '../../../../envoy/api/v2/core/Metadata'; +import type { Endpoint as _envoy_config_endpoint_v3_Endpoint, Endpoint__Output as _envoy_config_endpoint_v3_Endpoint__Output } from '../../../../envoy/config/endpoint/v3/Endpoint'; +import type { HealthStatus as _envoy_config_core_v3_HealthStatus } from '../../../../envoy/config/core/v3/HealthStatus'; +import type { Metadata as _envoy_config_core_v3_Metadata, Metadata__Output as _envoy_config_core_v3_Metadata__Output } from '../../../../envoy/config/core/v3/Metadata'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; /** @@ -10,21 +10,21 @@ import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output a * [#next-free-field: 6] */ export interface LbEndpoint { - 'endpoint'?: (_envoy_api_v2_endpoint_Endpoint); + 'endpoint'?: (_envoy_config_endpoint_v3_Endpoint | null); /** * Optional health status when known and supplied by EDS server. */ - 'health_status'?: (_envoy_api_v2_core_HealthStatus | keyof typeof _envoy_api_v2_core_HealthStatus); + 'health_status'?: (_envoy_config_core_v3_HealthStatus | keyof typeof _envoy_config_core_v3_HealthStatus); /** * The endpoint metadata specifies values that may be used by the load * balancer to select endpoints in a cluster for a given request. The filter * name should be specified as *envoy.lb*. An example boolean key-value pair * is *canary*, providing the optional canary status of the upstream host. * This may be matched against in a route's - * :ref:`RouteAction ` metadata_match field + * :ref:`RouteAction ` metadata_match field * to subset the endpoints considered in cluster load balancing. */ - 'metadata'?: (_envoy_api_v2_core_Metadata); + 'metadata'?: (_envoy_config_core_v3_Metadata | null); /** * The optional load balancing weight of the upstream host; at least 1. * Envoy uses the load balancing weight in some of the built in load @@ -36,7 +36,7 @@ export interface LbEndpoint { * weight in a locality. The sum of the weights of all endpoints in the * endpoint's locality must not exceed uint32_t maximal value (4294967295). */ - 'load_balancing_weight'?: (_google_protobuf_UInt32Value); + 'load_balancing_weight'?: (_google_protobuf_UInt32Value | null); /** * [#not-implemented-hide:] */ @@ -52,21 +52,21 @@ export interface LbEndpoint { * [#next-free-field: 6] */ export interface LbEndpoint__Output { - 'endpoint'?: (_envoy_api_v2_endpoint_Endpoint__Output); + 'endpoint'?: (_envoy_config_endpoint_v3_Endpoint__Output | null); /** * Optional health status when known and supplied by EDS server. */ - 'health_status': (keyof typeof _envoy_api_v2_core_HealthStatus); + 'health_status': (keyof typeof _envoy_config_core_v3_HealthStatus); /** * The endpoint metadata specifies values that may be used by the load * balancer to select endpoints in a cluster for a given request. The filter * name should be specified as *envoy.lb*. An example boolean key-value pair * is *canary*, providing the optional canary status of the upstream host. * This may be matched against in a route's - * :ref:`RouteAction ` metadata_match field + * :ref:`RouteAction ` metadata_match field * to subset the endpoints considered in cluster load balancing. */ - 'metadata'?: (_envoy_api_v2_core_Metadata__Output); + 'metadata': (_envoy_config_core_v3_Metadata__Output | null); /** * The optional load balancing weight of the upstream host; at least 1. * Envoy uses the load balancing weight in some of the built in load @@ -78,7 +78,7 @@ export interface LbEndpoint__Output { * weight in a locality. The sum of the weights of all endpoints in the * endpoint's locality must not exceed uint32_t maximal value (4294967295). */ - 'load_balancing_weight'?: (_google_protobuf_UInt32Value__Output); + 'load_balancing_weight': (_google_protobuf_UInt32Value__Output | null); /** * [#not-implemented-hide:] */ diff --git a/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LedsClusterLocalityConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LedsClusterLocalityConfig.ts new file mode 100644 index 000000000..1229d33a3 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LedsClusterLocalityConfig.ts @@ -0,0 +1,35 @@ +// Original file: deps/envoy-api/envoy/config/endpoint/v3/endpoint_components.proto + +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../envoy/config/core/v3/ConfigSource'; + +/** + * [#not-implemented-hide:] + * A configuration for a LEDS collection. + */ +export interface LedsClusterLocalityConfig { + /** + * Configuration for the source of LEDS updates for a Locality. + */ + 'leds_config'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * The xDS transport protocol glob collection resource name. + * The service is only supported in delta xDS (incremental) mode. + */ + 'leds_collection_name'?: (string); +} + +/** + * [#not-implemented-hide:] + * A configuration for a LEDS collection. + */ +export interface LedsClusterLocalityConfig__Output { + /** + * Configuration for the source of LEDS updates for a Locality. + */ + 'leds_config': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * The xDS transport protocol glob collection resource name. + * The service is only supported in delta xDS (incremental) mode. + */ + 'leds_collection_name': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/LocalityLbEndpoints.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LocalityLbEndpoints.ts similarity index 58% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/LocalityLbEndpoints.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LocalityLbEndpoints.ts index 557d97072..182e27c9c 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/LocalityLbEndpoints.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/LocalityLbEndpoints.ts @@ -1,25 +1,44 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint/endpoint_components.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/endpoint_components.proto -import type { Locality as _envoy_api_v2_core_Locality, Locality__Output as _envoy_api_v2_core_Locality__Output } from '../../../../envoy/api/v2/core/Locality'; -import type { LbEndpoint as _envoy_api_v2_endpoint_LbEndpoint, LbEndpoint__Output as _envoy_api_v2_endpoint_LbEndpoint__Output } from '../../../../envoy/api/v2/endpoint/LbEndpoint'; +import type { Locality as _envoy_config_core_v3_Locality, Locality__Output as _envoy_config_core_v3_Locality__Output } from '../../../../envoy/config/core/v3/Locality'; +import type { LbEndpoint as _envoy_config_endpoint_v3_LbEndpoint, LbEndpoint__Output as _envoy_config_endpoint_v3_LbEndpoint__Output } from '../../../../envoy/config/endpoint/v3/LbEndpoint'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { LedsClusterLocalityConfig as _envoy_config_endpoint_v3_LedsClusterLocalityConfig, LedsClusterLocalityConfig__Output as _envoy_config_endpoint_v3_LedsClusterLocalityConfig__Output } from '../../../../envoy/config/endpoint/v3/LedsClusterLocalityConfig'; + +/** + * [#not-implemented-hide:] + * A list of endpoints of a specific locality. + */ +export interface _envoy_config_endpoint_v3_LocalityLbEndpoints_LbEndpointList { + 'lb_endpoints'?: (_envoy_config_endpoint_v3_LbEndpoint)[]; +} + +/** + * [#not-implemented-hide:] + * A list of endpoints of a specific locality. + */ +export interface _envoy_config_endpoint_v3_LocalityLbEndpoints_LbEndpointList__Output { + 'lb_endpoints': (_envoy_config_endpoint_v3_LbEndpoint__Output)[]; +} /** * A group of endpoints belonging to a Locality. * One can have multiple LocalityLbEndpoints for a locality, but this is * generally only done if the different groups need to have different load * balancing weights or different priorities. - * [#next-free-field: 7] + * [#next-free-field: 9] */ export interface LocalityLbEndpoints { /** * Identifies location of where the upstream hosts run. */ - 'locality'?: (_envoy_api_v2_core_Locality); + 'locality'?: (_envoy_config_core_v3_Locality | null); /** * The group of endpoints belonging to the locality specified. + * [#comment:TODO(adisuissa): Once LEDS is implemented this field needs to be + * deprecated and replaced by *load_balancer_endpoints*.] */ - 'lb_endpoints'?: (_envoy_api_v2_endpoint_LbEndpoint)[]; + 'lb_endpoints'?: (_envoy_config_endpoint_v3_LbEndpoint)[]; /** * Optional: Per priority/region/zone/sub_zone weight; at least 1. The load * balancing weight for a locality is divided by the sum of the weights of all @@ -33,7 +52,7 @@ export interface LocalityLbEndpoints { * specified when locality weighted load balancing is enabled, the locality is * assigned no load. */ - 'load_balancing_weight'?: (_google_protobuf_UInt32Value); + 'load_balancing_weight'?: (_google_protobuf_UInt32Value | null); /** * Optional: the priority for this LocalityLbEndpoints. If unspecified this will * default to the highest priority (0). @@ -54,7 +73,21 @@ export interface LocalityLbEndpoints { * to determine where to route the requests. * [#not-implemented-hide:] */ - 'proximity'?: (_google_protobuf_UInt32Value); + 'proximity'?: (_google_protobuf_UInt32Value | null); + /** + * The group of endpoints belonging to the locality. + * [#comment:TODO(adisuissa): Once LEDS is implemented the *lb_endpoints* field + * needs to be deprecated.] + */ + 'load_balancer_endpoints'?: (_envoy_config_endpoint_v3_LocalityLbEndpoints_LbEndpointList | null); + /** + * LEDS Configuration for the current locality. + */ + 'leds_cluster_locality_config'?: (_envoy_config_endpoint_v3_LedsClusterLocalityConfig | null); + /** + * [#not-implemented-hide:] + */ + 'lb_config'?: "load_balancer_endpoints"|"leds_cluster_locality_config"; } /** @@ -62,17 +95,19 @@ export interface LocalityLbEndpoints { * One can have multiple LocalityLbEndpoints for a locality, but this is * generally only done if the different groups need to have different load * balancing weights or different priorities. - * [#next-free-field: 7] + * [#next-free-field: 9] */ export interface LocalityLbEndpoints__Output { /** * Identifies location of where the upstream hosts run. */ - 'locality'?: (_envoy_api_v2_core_Locality__Output); + 'locality': (_envoy_config_core_v3_Locality__Output | null); /** * The group of endpoints belonging to the locality specified. + * [#comment:TODO(adisuissa): Once LEDS is implemented this field needs to be + * deprecated and replaced by *load_balancer_endpoints*.] */ - 'lb_endpoints': (_envoy_api_v2_endpoint_LbEndpoint__Output)[]; + 'lb_endpoints': (_envoy_config_endpoint_v3_LbEndpoint__Output)[]; /** * Optional: Per priority/region/zone/sub_zone weight; at least 1. The load * balancing weight for a locality is divided by the sum of the weights of all @@ -86,7 +121,7 @@ export interface LocalityLbEndpoints__Output { * specified when locality weighted load balancing is enabled, the locality is * assigned no load. */ - 'load_balancing_weight'?: (_google_protobuf_UInt32Value__Output); + 'load_balancing_weight': (_google_protobuf_UInt32Value__Output | null); /** * Optional: the priority for this LocalityLbEndpoints. If unspecified this will * default to the highest priority (0). @@ -107,5 +142,19 @@ export interface LocalityLbEndpoints__Output { * to determine where to route the requests. * [#not-implemented-hide:] */ - 'proximity'?: (_google_protobuf_UInt32Value__Output); + 'proximity': (_google_protobuf_UInt32Value__Output | null); + /** + * The group of endpoints belonging to the locality. + * [#comment:TODO(adisuissa): Once LEDS is implemented the *lb_endpoints* field + * needs to be deprecated.] + */ + 'load_balancer_endpoints'?: (_envoy_config_endpoint_v3_LocalityLbEndpoints_LbEndpointList__Output | null); + /** + * LEDS Configuration for the current locality. + */ + 'leds_cluster_locality_config'?: (_envoy_config_endpoint_v3_LedsClusterLocalityConfig__Output | null); + /** + * [#not-implemented-hide:] + */ + 'lb_config': "load_balancer_endpoints"|"leds_cluster_locality_config"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/UpstreamEndpointStats.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/UpstreamEndpointStats.ts similarity index 75% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/UpstreamEndpointStats.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/UpstreamEndpointStats.ts index 5b5c62b32..ab06afb39 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/UpstreamEndpointStats.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/UpstreamEndpointStats.ts @@ -1,19 +1,18 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint/load_report.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/load_report.proto -import type { Address as _envoy_api_v2_core_Address, Address__Output as _envoy_api_v2_core_Address__Output } from '../../../../envoy/api/v2/core/Address'; -import type { EndpointLoadMetricStats as _envoy_api_v2_endpoint_EndpointLoadMetricStats, EndpointLoadMetricStats__Output as _envoy_api_v2_endpoint_EndpointLoadMetricStats__Output } from '../../../../envoy/api/v2/endpoint/EndpointLoadMetricStats'; +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; +import type { EndpointLoadMetricStats as _envoy_config_endpoint_v3_EndpointLoadMetricStats, EndpointLoadMetricStats__Output as _envoy_config_endpoint_v3_EndpointLoadMetricStats__Output } from '../../../../envoy/config/endpoint/v3/EndpointLoadMetricStats'; import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; import type { Long } from '@grpc/proto-loader'; /** - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. * [#next-free-field: 8] */ export interface UpstreamEndpointStats { /** * Upstream host address. */ - 'address'?: (_envoy_api_v2_core_Address); + 'address'?: (_envoy_config_core_v3_Address | null); /** * The total number of requests successfully completed by the endpoints in the * locality. These include non-5xx responses for HTTP, where errors @@ -41,12 +40,12 @@ export interface UpstreamEndpointStats { /** * Stats for multi-dimensional load balancing. */ - 'load_metric_stats'?: (_envoy_api_v2_endpoint_EndpointLoadMetricStats)[]; + 'load_metric_stats'?: (_envoy_config_endpoint_v3_EndpointLoadMetricStats)[]; /** * Opaque and implementation dependent metadata of the * endpoint. Envoy will pass this directly to the management server. */ - 'metadata'?: (_google_protobuf_Struct); + 'metadata'?: (_google_protobuf_Struct | null); /** * The total number of requests that were issued to this endpoint * since the last report. A single TCP connection, HTTP or gRPC @@ -56,14 +55,13 @@ export interface UpstreamEndpointStats { } /** - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. * [#next-free-field: 8] */ export interface UpstreamEndpointStats__Output { /** * Upstream host address. */ - 'address'?: (_envoy_api_v2_core_Address__Output); + 'address': (_envoy_config_core_v3_Address__Output | null); /** * The total number of requests successfully completed by the endpoints in the * locality. These include non-5xx responses for HTTP, where errors @@ -91,12 +89,12 @@ export interface UpstreamEndpointStats__Output { /** * Stats for multi-dimensional load balancing. */ - 'load_metric_stats': (_envoy_api_v2_endpoint_EndpointLoadMetricStats__Output)[]; + 'load_metric_stats': (_envoy_config_endpoint_v3_EndpointLoadMetricStats__Output)[]; /** * Opaque and implementation dependent metadata of the * endpoint. Envoy will pass this directly to the management server. */ - 'metadata'?: (_google_protobuf_Struct__Output); + 'metadata': (_google_protobuf_Struct__Output | null); /** * The total number of requests that were issued to this endpoint * since the last report. A single TCP connection, HTTP or gRPC diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/UpstreamLocalityStats.ts b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/UpstreamLocalityStats.ts similarity index 57% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/UpstreamLocalityStats.ts rename to packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/UpstreamLocalityStats.ts index a1b20897e..fbfb05ed6 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/endpoint/UpstreamLocalityStats.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/endpoint/v3/UpstreamLocalityStats.ts @@ -1,16 +1,14 @@ -// Original file: deps/envoy-api/envoy/api/v2/endpoint/load_report.proto +// Original file: deps/envoy-api/envoy/config/endpoint/v3/load_report.proto -import type { Locality as _envoy_api_v2_core_Locality, Locality__Output as _envoy_api_v2_core_Locality__Output } from '../../../../envoy/api/v2/core/Locality'; -import type { EndpointLoadMetricStats as _envoy_api_v2_endpoint_EndpointLoadMetricStats, EndpointLoadMetricStats__Output as _envoy_api_v2_endpoint_EndpointLoadMetricStats__Output } from '../../../../envoy/api/v2/endpoint/EndpointLoadMetricStats'; -import type { UpstreamEndpointStats as _envoy_api_v2_endpoint_UpstreamEndpointStats, UpstreamEndpointStats__Output as _envoy_api_v2_endpoint_UpstreamEndpointStats__Output } from '../../../../envoy/api/v2/endpoint/UpstreamEndpointStats'; +import type { Locality as _envoy_config_core_v3_Locality, Locality__Output as _envoy_config_core_v3_Locality__Output } from '../../../../envoy/config/core/v3/Locality'; +import type { EndpointLoadMetricStats as _envoy_config_endpoint_v3_EndpointLoadMetricStats, EndpointLoadMetricStats__Output as _envoy_config_endpoint_v3_EndpointLoadMetricStats__Output } from '../../../../envoy/config/endpoint/v3/EndpointLoadMetricStats'; +import type { UpstreamEndpointStats as _envoy_config_endpoint_v3_UpstreamEndpointStats, UpstreamEndpointStats__Output as _envoy_config_endpoint_v3_UpstreamEndpointStats__Output } from '../../../../envoy/config/endpoint/v3/UpstreamEndpointStats'; import type { Long } from '@grpc/proto-loader'; /** - * These are stats Envoy reports to GLB every so often. Report frequency is - * defined by - * :ref:`LoadStatsResponse.load_reporting_interval`. + * These are stats Envoy reports to the management server at a frequency defined by + * :ref:`LoadStatsResponse.load_reporting_interval`. * Stats per upstream region/zone and optionally per subzone. - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. * [#next-free-field: 9] */ export interface UpstreamLocalityStats { @@ -18,7 +16,7 @@ export interface UpstreamLocalityStats { * Name of zone, region and optionally endpoint group these metrics were * collected from. Zone and region names could be empty if unknown. */ - 'locality'?: (_envoy_api_v2_core_Locality); + 'locality'?: (_envoy_config_core_v3_Locality | null); /** * The total number of requests successfully completed by the endpoints in the * locality. @@ -36,7 +34,7 @@ export interface UpstreamLocalityStats { /** * Stats for multi-dimensional load balancing. */ - 'load_metric_stats'?: (_envoy_api_v2_endpoint_EndpointLoadMetricStats)[]; + 'load_metric_stats'?: (_envoy_config_endpoint_v3_EndpointLoadMetricStats)[]; /** * [#not-implemented-hide:] The priority of the endpoint group these metrics * were collected from. @@ -45,9 +43,9 @@ export interface UpstreamLocalityStats { /** * Endpoint granularity stats information for this locality. This information * is populated if the Server requests it by setting - * :ref:`LoadStatsResponse.report_endpoint_granularity`. + * :ref:`LoadStatsResponse.report_endpoint_granularity`. */ - 'upstream_endpoint_stats'?: (_envoy_api_v2_endpoint_UpstreamEndpointStats)[]; + 'upstream_endpoint_stats'?: (_envoy_config_endpoint_v3_UpstreamEndpointStats)[]; /** * The total number of requests that were issued by this Envoy since * the last report. This information is aggregated over all the @@ -57,11 +55,9 @@ export interface UpstreamLocalityStats { } /** - * These are stats Envoy reports to GLB every so often. Report frequency is - * defined by - * :ref:`LoadStatsResponse.load_reporting_interval`. + * These are stats Envoy reports to the management server at a frequency defined by + * :ref:`LoadStatsResponse.load_reporting_interval`. * Stats per upstream region/zone and optionally per subzone. - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. * [#next-free-field: 9] */ export interface UpstreamLocalityStats__Output { @@ -69,7 +65,7 @@ export interface UpstreamLocalityStats__Output { * Name of zone, region and optionally endpoint group these metrics were * collected from. Zone and region names could be empty if unknown. */ - 'locality'?: (_envoy_api_v2_core_Locality__Output); + 'locality': (_envoy_config_core_v3_Locality__Output | null); /** * The total number of requests successfully completed by the endpoints in the * locality. @@ -87,7 +83,7 @@ export interface UpstreamLocalityStats__Output { /** * Stats for multi-dimensional load balancing. */ - 'load_metric_stats': (_envoy_api_v2_endpoint_EndpointLoadMetricStats__Output)[]; + 'load_metric_stats': (_envoy_config_endpoint_v3_EndpointLoadMetricStats__Output)[]; /** * [#not-implemented-hide:] The priority of the endpoint group these metrics * were collected from. @@ -96,9 +92,9 @@ export interface UpstreamLocalityStats__Output { /** * Endpoint granularity stats information for this locality. This information * is populated if the Server requests it by setting - * :ref:`LoadStatsResponse.report_endpoint_granularity`. + * :ref:`LoadStatsResponse.report_endpoint_granularity`. */ - 'upstream_endpoint_stats': (_envoy_api_v2_endpoint_UpstreamEndpointStats__Output)[]; + 'upstream_endpoint_stats': (_envoy_config_endpoint_v3_UpstreamEndpointStats__Output)[]; /** * The total number of requests that were issued by this Envoy since * the last report. This information is aggregated over all the diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AccessLog.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AccessLog.ts deleted file mode 100644 index 82e056a4b..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AccessLog.ts +++ /dev/null @@ -1,65 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -import type { AccessLogFilter as _envoy_config_filter_accesslog_v2_AccessLogFilter, AccessLogFilter__Output as _envoy_config_filter_accesslog_v2_AccessLogFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/AccessLogFilter'; -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../google/protobuf/Any'; - -export interface AccessLog { - /** - * The name of the access log implementation to instantiate. The name must - * match a statically registered access log. Current built-in loggers include: - * - * #. "envoy.access_loggers.file" - * #. "envoy.access_loggers.http_grpc" - * #. "envoy.access_loggers.tcp_grpc" - */ - 'name'?: (string); - /** - * Filter which is used to determine if the access log needs to be written. - */ - 'filter'?: (_envoy_config_filter_accesslog_v2_AccessLogFilter); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - /** - * Custom configuration that depends on the access log being instantiated. Built-in - * configurations include: - * - * #. "envoy.access_loggers.file": :ref:`FileAccessLog - * ` - * #. "envoy.access_loggers.http_grpc": :ref:`HttpGrpcAccessLogConfig - * ` - * #. "envoy.access_loggers.tcp_grpc": :ref:`TcpGrpcAccessLogConfig - * ` - */ - 'config_type'?: "config"|"typed_config"; -} - -export interface AccessLog__Output { - /** - * The name of the access log implementation to instantiate. The name must - * match a statically registered access log. Current built-in loggers include: - * - * #. "envoy.access_loggers.file" - * #. "envoy.access_loggers.http_grpc" - * #. "envoy.access_loggers.tcp_grpc" - */ - 'name': (string); - /** - * Filter which is used to determine if the access log needs to be written. - */ - 'filter'?: (_envoy_config_filter_accesslog_v2_AccessLogFilter__Output); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - /** - * Custom configuration that depends on the access log being instantiated. Built-in - * configurations include: - * - * #. "envoy.access_loggers.file": :ref:`FileAccessLog - * ` - * #. "envoy.access_loggers.http_grpc": :ref:`HttpGrpcAccessLogConfig - * ` - * #. "envoy.access_loggers.tcp_grpc": :ref:`TcpGrpcAccessLogConfig - * ` - */ - 'config_type': "config"|"typed_config"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AccessLogFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AccessLogFilter.ts deleted file mode 100644 index d75c9676c..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/AccessLogFilter.ts +++ /dev/null @@ -1,115 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -import type { StatusCodeFilter as _envoy_config_filter_accesslog_v2_StatusCodeFilter, StatusCodeFilter__Output as _envoy_config_filter_accesslog_v2_StatusCodeFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/StatusCodeFilter'; -import type { DurationFilter as _envoy_config_filter_accesslog_v2_DurationFilter, DurationFilter__Output as _envoy_config_filter_accesslog_v2_DurationFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/DurationFilter'; -import type { NotHealthCheckFilter as _envoy_config_filter_accesslog_v2_NotHealthCheckFilter, NotHealthCheckFilter__Output as _envoy_config_filter_accesslog_v2_NotHealthCheckFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/NotHealthCheckFilter'; -import type { TraceableFilter as _envoy_config_filter_accesslog_v2_TraceableFilter, TraceableFilter__Output as _envoy_config_filter_accesslog_v2_TraceableFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/TraceableFilter'; -import type { RuntimeFilter as _envoy_config_filter_accesslog_v2_RuntimeFilter, RuntimeFilter__Output as _envoy_config_filter_accesslog_v2_RuntimeFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/RuntimeFilter'; -import type { AndFilter as _envoy_config_filter_accesslog_v2_AndFilter, AndFilter__Output as _envoy_config_filter_accesslog_v2_AndFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/AndFilter'; -import type { OrFilter as _envoy_config_filter_accesslog_v2_OrFilter, OrFilter__Output as _envoy_config_filter_accesslog_v2_OrFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/OrFilter'; -import type { HeaderFilter as _envoy_config_filter_accesslog_v2_HeaderFilter, HeaderFilter__Output as _envoy_config_filter_accesslog_v2_HeaderFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/HeaderFilter'; -import type { ResponseFlagFilter as _envoy_config_filter_accesslog_v2_ResponseFlagFilter, ResponseFlagFilter__Output as _envoy_config_filter_accesslog_v2_ResponseFlagFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/ResponseFlagFilter'; -import type { GrpcStatusFilter as _envoy_config_filter_accesslog_v2_GrpcStatusFilter, GrpcStatusFilter__Output as _envoy_config_filter_accesslog_v2_GrpcStatusFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/GrpcStatusFilter'; -import type { ExtensionFilter as _envoy_config_filter_accesslog_v2_ExtensionFilter, ExtensionFilter__Output as _envoy_config_filter_accesslog_v2_ExtensionFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/ExtensionFilter'; - -/** - * [#next-free-field: 12] - */ -export interface AccessLogFilter { - /** - * Status code filter. - */ - 'status_code_filter'?: (_envoy_config_filter_accesslog_v2_StatusCodeFilter); - /** - * Duration filter. - */ - 'duration_filter'?: (_envoy_config_filter_accesslog_v2_DurationFilter); - /** - * Not health check filter. - */ - 'not_health_check_filter'?: (_envoy_config_filter_accesslog_v2_NotHealthCheckFilter); - /** - * Traceable filter. - */ - 'traceable_filter'?: (_envoy_config_filter_accesslog_v2_TraceableFilter); - /** - * Runtime filter. - */ - 'runtime_filter'?: (_envoy_config_filter_accesslog_v2_RuntimeFilter); - /** - * And filter. - */ - 'and_filter'?: (_envoy_config_filter_accesslog_v2_AndFilter); - /** - * Or filter. - */ - 'or_filter'?: (_envoy_config_filter_accesslog_v2_OrFilter); - /** - * Header filter. - */ - 'header_filter'?: (_envoy_config_filter_accesslog_v2_HeaderFilter); - /** - * Response flag filter. - */ - 'response_flag_filter'?: (_envoy_config_filter_accesslog_v2_ResponseFlagFilter); - /** - * gRPC status filter. - */ - 'grpc_status_filter'?: (_envoy_config_filter_accesslog_v2_GrpcStatusFilter); - /** - * Extension filter. - */ - 'extension_filter'?: (_envoy_config_filter_accesslog_v2_ExtensionFilter); - 'filter_specifier'?: "status_code_filter"|"duration_filter"|"not_health_check_filter"|"traceable_filter"|"runtime_filter"|"and_filter"|"or_filter"|"header_filter"|"response_flag_filter"|"grpc_status_filter"|"extension_filter"; -} - -/** - * [#next-free-field: 12] - */ -export interface AccessLogFilter__Output { - /** - * Status code filter. - */ - 'status_code_filter'?: (_envoy_config_filter_accesslog_v2_StatusCodeFilter__Output); - /** - * Duration filter. - */ - 'duration_filter'?: (_envoy_config_filter_accesslog_v2_DurationFilter__Output); - /** - * Not health check filter. - */ - 'not_health_check_filter'?: (_envoy_config_filter_accesslog_v2_NotHealthCheckFilter__Output); - /** - * Traceable filter. - */ - 'traceable_filter'?: (_envoy_config_filter_accesslog_v2_TraceableFilter__Output); - /** - * Runtime filter. - */ - 'runtime_filter'?: (_envoy_config_filter_accesslog_v2_RuntimeFilter__Output); - /** - * And filter. - */ - 'and_filter'?: (_envoy_config_filter_accesslog_v2_AndFilter__Output); - /** - * Or filter. - */ - 'or_filter'?: (_envoy_config_filter_accesslog_v2_OrFilter__Output); - /** - * Header filter. - */ - 'header_filter'?: (_envoy_config_filter_accesslog_v2_HeaderFilter__Output); - /** - * Response flag filter. - */ - 'response_flag_filter'?: (_envoy_config_filter_accesslog_v2_ResponseFlagFilter__Output); - /** - * gRPC status filter. - */ - 'grpc_status_filter'?: (_envoy_config_filter_accesslog_v2_GrpcStatusFilter__Output); - /** - * Extension filter. - */ - 'extension_filter'?: (_envoy_config_filter_accesslog_v2_ExtensionFilter__Output); - 'filter_specifier': "status_code_filter"|"duration_filter"|"not_health_check_filter"|"traceable_filter"|"runtime_filter"|"and_filter"|"or_filter"|"header_filter"|"response_flag_filter"|"grpc_status_filter"|"extension_filter"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ComparisonFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ComparisonFilter.ts deleted file mode 100644 index 8989ba603..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/ComparisonFilter.ts +++ /dev/null @@ -1,48 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -import type { RuntimeUInt32 as _envoy_api_v2_core_RuntimeUInt32, RuntimeUInt32__Output as _envoy_api_v2_core_RuntimeUInt32__Output } from '../../../../../envoy/api/v2/core/RuntimeUInt32'; - -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -export enum _envoy_config_filter_accesslog_v2_ComparisonFilter_Op { - /** - * = - */ - EQ = 0, - /** - * >= - */ - GE = 1, - /** - * <= - */ - LE = 2, -} - -/** - * Filter on an integer comparison. - */ -export interface ComparisonFilter { - /** - * Comparison operator. - */ - 'op'?: (_envoy_config_filter_accesslog_v2_ComparisonFilter_Op | keyof typeof _envoy_config_filter_accesslog_v2_ComparisonFilter_Op); - /** - * Value to compare against. - */ - 'value'?: (_envoy_api_v2_core_RuntimeUInt32); -} - -/** - * Filter on an integer comparison. - */ -export interface ComparisonFilter__Output { - /** - * Comparison operator. - */ - 'op': (keyof typeof _envoy_config_filter_accesslog_v2_ComparisonFilter_Op); - /** - * Value to compare against. - */ - 'value'?: (_envoy_api_v2_core_RuntimeUInt32__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/DurationFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/DurationFilter.ts deleted file mode 100644 index 52a37cd95..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/DurationFilter.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -import type { ComparisonFilter as _envoy_config_filter_accesslog_v2_ComparisonFilter, ComparisonFilter__Output as _envoy_config_filter_accesslog_v2_ComparisonFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/ComparisonFilter'; - -/** - * Filters on total request duration in milliseconds. - */ -export interface DurationFilter { - /** - * Comparison. - */ - 'comparison'?: (_envoy_config_filter_accesslog_v2_ComparisonFilter); -} - -/** - * Filters on total request duration in milliseconds. - */ -export interface DurationFilter__Output { - /** - * Comparison. - */ - 'comparison'?: (_envoy_config_filter_accesslog_v2_ComparisonFilter__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/HeaderFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/HeaderFilter.ts deleted file mode 100644 index d40610617..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/HeaderFilter.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -import type { HeaderMatcher as _envoy_api_v2_route_HeaderMatcher, HeaderMatcher__Output as _envoy_api_v2_route_HeaderMatcher__Output } from '../../../../../envoy/api/v2/route/HeaderMatcher'; - -/** - * Filters requests based on the presence or value of a request header. - */ -export interface HeaderFilter { - /** - * Only requests with a header which matches the specified HeaderMatcher will pass the filter - * check. - */ - 'header'?: (_envoy_api_v2_route_HeaderMatcher); -} - -/** - * Filters requests based on the presence or value of a request header. - */ -export interface HeaderFilter__Output { - /** - * Only requests with a header which matches the specified HeaderMatcher will pass the filter - * check. - */ - 'header'?: (_envoy_api_v2_route_HeaderMatcher__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/RuntimeFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/RuntimeFilter.ts deleted file mode 100644 index 100ce050b..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/RuntimeFilter.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -import type { FractionalPercent as _envoy_type_FractionalPercent, FractionalPercent__Output as _envoy_type_FractionalPercent__Output } from '../../../../../envoy/type/FractionalPercent'; - -/** - * Filters for random sampling of requests. - */ -export interface RuntimeFilter { - /** - * Runtime key to get an optional overridden numerator for use in the *percent_sampled* field. - * If found in runtime, this value will replace the default numerator. - */ - 'runtime_key'?: (string); - /** - * The default sampling percentage. If not specified, defaults to 0% with denominator of 100. - */ - 'percent_sampled'?: (_envoy_type_FractionalPercent); - /** - * By default, sampling pivots on the header - * :ref:`x-request-id` being present. If - * :ref:`x-request-id` is present, the filter will - * consistently sample across multiple hosts based on the runtime key value and the value - * extracted from :ref:`x-request-id`. If it is - * missing, or *use_independent_randomness* is set to true, the filter will randomly sample based - * on the runtime key value alone. *use_independent_randomness* can be used for logging kill - * switches within complex nested :ref:`AndFilter - * ` and :ref:`OrFilter - * ` blocks that are easier to reason about - * from a probability perspective (i.e., setting to true will cause the filter to behave like - * an independent random variable when composed within logical operator filters). - */ - 'use_independent_randomness'?: (boolean); -} - -/** - * Filters for random sampling of requests. - */ -export interface RuntimeFilter__Output { - /** - * Runtime key to get an optional overridden numerator for use in the *percent_sampled* field. - * If found in runtime, this value will replace the default numerator. - */ - 'runtime_key': (string); - /** - * The default sampling percentage. If not specified, defaults to 0% with denominator of 100. - */ - 'percent_sampled'?: (_envoy_type_FractionalPercent__Output); - /** - * By default, sampling pivots on the header - * :ref:`x-request-id` being present. If - * :ref:`x-request-id` is present, the filter will - * consistently sample across multiple hosts based on the runtime key value and the value - * extracted from :ref:`x-request-id`. If it is - * missing, or *use_independent_randomness* is set to true, the filter will randomly sample based - * on the runtime key value alone. *use_independent_randomness* can be used for logging kill - * switches within complex nested :ref:`AndFilter - * ` and :ref:`OrFilter - * ` blocks that are easier to reason about - * from a probability perspective (i.e., setting to true will cause the filter to behave like - * an independent random variable when composed within logical operator filters). - */ - 'use_independent_randomness': (boolean); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/StatusCodeFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/StatusCodeFilter.ts deleted file mode 100644 index d60a80a14..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/accesslog/v2/StatusCodeFilter.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/accesslog/v2/accesslog.proto - -import type { ComparisonFilter as _envoy_config_filter_accesslog_v2_ComparisonFilter, ComparisonFilter__Output as _envoy_config_filter_accesslog_v2_ComparisonFilter__Output } from '../../../../../envoy/config/filter/accesslog/v2/ComparisonFilter'; - -/** - * Filters on HTTP response/status code. - */ -export interface StatusCodeFilter { - /** - * Comparison. - */ - 'comparison'?: (_envoy_config_filter_accesslog_v2_ComparisonFilter); -} - -/** - * Filters on HTTP response/status code. - */ -export interface StatusCodeFilter__Output { - /** - * Comparison. - */ - 'comparison'?: (_envoy_config_filter_accesslog_v2_ComparisonFilter__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager.ts deleted file mode 100644 index 1838f89a7..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager.ts +++ /dev/null @@ -1,1039 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -import type { Rds as _envoy_config_filter_network_http_connection_manager_v2_Rds, Rds__Output as _envoy_config_filter_network_http_connection_manager_v2_Rds__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/Rds'; -import type { RouteConfiguration as _envoy_api_v2_RouteConfiguration, RouteConfiguration__Output as _envoy_api_v2_RouteConfiguration__Output } from '../../../../../../envoy/api/v2/RouteConfiguration'; -import type { HttpFilter as _envoy_config_filter_network_http_connection_manager_v2_HttpFilter, HttpFilter__Output as _envoy_config_filter_network_http_connection_manager_v2_HttpFilter__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/HttpFilter'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../../../google/protobuf/BoolValue'; -import type { Http1ProtocolOptions as _envoy_api_v2_core_Http1ProtocolOptions, Http1ProtocolOptions__Output as _envoy_api_v2_core_Http1ProtocolOptions__Output } from '../../../../../../envoy/api/v2/core/Http1ProtocolOptions'; -import type { Http2ProtocolOptions as _envoy_api_v2_core_Http2ProtocolOptions, Http2ProtocolOptions__Output as _envoy_api_v2_core_Http2ProtocolOptions__Output } from '../../../../../../envoy/api/v2/core/Http2ProtocolOptions'; -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../../../google/protobuf/Duration'; -import type { AccessLog as _envoy_config_filter_accesslog_v2_AccessLog, AccessLog__Output as _envoy_config_filter_accesslog_v2_AccessLog__Output } from '../../../../../../envoy/config/filter/accesslog/v2/AccessLog'; -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../../../google/protobuf/UInt32Value'; -import type { ScopedRoutes as _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes, ScopedRoutes__Output as _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes'; -import type { HttpProtocolOptions as _envoy_api_v2_core_HttpProtocolOptions, HttpProtocolOptions__Output as _envoy_api_v2_core_HttpProtocolOptions__Output } from '../../../../../../envoy/api/v2/core/HttpProtocolOptions'; -import type { RequestIDExtension as _envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension, RequestIDExtension__Output as _envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension'; -import type { Percent as _envoy_type_Percent, Percent__Output as _envoy_type_Percent__Output } from '../../../../../../envoy/type/Percent'; -import type { CustomTag as _envoy_type_tracing_v2_CustomTag, CustomTag__Output as _envoy_type_tracing_v2_CustomTag__Output } from '../../../../../../envoy/type/tracing/v2/CustomTag'; -import type { _envoy_config_trace_v2_Tracing_Http, _envoy_config_trace_v2_Tracing_Http__Output } from '../../../../../../envoy/config/trace/v2/Tracing'; - -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType { - /** - * For every new connection, the connection manager will determine which - * codec to use. This mode supports both ALPN for TLS listeners as well as - * protocol inference for plaintext listeners. If ALPN data is available, it - * is preferred, otherwise protocol inference is used. In almost all cases, - * this is the right option to choose for this setting. - */ - AUTO = 0, - /** - * The connection manager will assume that the client is speaking HTTP/1.1. - */ - HTTP1 = 1, - /** - * The connection manager will assume that the client is speaking HTTP/2 - * (Envoy does not require HTTP/2 to take place over TLS or to use ALPN. - * Prior knowledge is allowed). - */ - HTTP2 = 2, - /** - * [#not-implemented-hide:] QUIC implementation is not production ready yet. Use this enum with - * caution to prevent accidental execution of QUIC code. I.e. `!= HTTP2` is no longer sufficient - * to distinguish HTTP1 and HTTP2 traffic. - */ - HTTP3 = 3, -} - -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -/** - * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP - * header. - */ -export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails { - /** - * Do not send the XFCC header to the next hop. This is the default value. - */ - SANITIZE = 0, - /** - * When the client connection is mTLS (Mutual TLS), forward the XFCC header - * in the request. - */ - FORWARD_ONLY = 1, - /** - * When the client connection is mTLS, append the client certificate - * information to the request’s XFCC header and forward it. - */ - APPEND_FORWARD = 2, - /** - * When the client connection is mTLS, reset the XFCC header with the client - * certificate information and send it to the next hop. - */ - SANITIZE_SET = 3, - /** - * Always forward the XFCC header in the request, regardless of whether the - * client connection is mTLS. - */ - ALWAYS_FORWARD_ONLY = 4, -} - -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig { - /** - * Whether unix socket addresses should be considered internal. - */ - 'unix_sockets'?: (boolean); -} - -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig__Output { - /** - * Whether unix socket addresses should be considered internal. - */ - 'unix_sockets': (boolean); -} - -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName { - /** - * The HTTP listener is used for ingress/incoming requests. - */ - INGRESS = 0, - /** - * The HTTP listener is used for egress/outgoing requests. - */ - EGRESS = 1, -} - -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -export enum _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation { - /** - * Overwrite any Server header with the contents of server_name. - */ - OVERWRITE = 0, - /** - * If no Server header is present, append Server server_name - * If a Server header is present, pass it through. - */ - APPEND_IF_ABSENT = 1, - /** - * Pass through the value of the server header, and do not append a header - * if none is present. - */ - PASS_THROUGH = 2, -} - -/** - * [#next-free-field: 7] - */ -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails { - /** - * Whether to forward the subject of the client cert. Defaults to false. - */ - 'subject'?: (_google_protobuf_BoolValue); - /** - * Whether to forward the entire client cert in URL encoded PEM format. This will appear in the - * XFCC header comma separated from other values with the value Cert="PEM". - * Defaults to false. - */ - 'cert'?: (boolean); - /** - * Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM - * format. This will appear in the XFCC header comma separated from other values with the value - * Chain="PEM". - * Defaults to false. - */ - 'chain'?: (boolean); - /** - * Whether to forward the DNS type Subject Alternative Names of the client cert. - * Defaults to false. - */ - 'dns'?: (boolean); - /** - * Whether to forward the URI type Subject Alternative Name of the client cert. Defaults to - * false. - */ - 'uri'?: (boolean); -} - -/** - * [#next-free-field: 7] - */ -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails__Output { - /** - * Whether to forward the subject of the client cert. Defaults to false. - */ - 'subject'?: (_google_protobuf_BoolValue__Output); - /** - * Whether to forward the entire client cert in URL encoded PEM format. This will appear in the - * XFCC header comma separated from other values with the value Cert="PEM". - * Defaults to false. - */ - 'cert': (boolean); - /** - * Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM - * format. This will appear in the XFCC header comma separated from other values with the value - * Chain="PEM". - * Defaults to false. - */ - 'chain': (boolean); - /** - * Whether to forward the DNS type Subject Alternative Names of the client cert. - * Defaults to false. - */ - 'dns': (boolean); - /** - * Whether to forward the URI type Subject Alternative Name of the client cert. Defaults to - * false. - */ - 'uri': (boolean); -} - -/** - * [#next-free-field: 10] - */ -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing { - /** - * The span name will be derived from this field. If - * :ref:`traffic_direction ` is - * specified on the parent listener, then it is used instead of this field. - * - * .. attention:: - * This field has been deprecated in favor of `traffic_direction`. - */ - 'operation_name'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName); - /** - * A list of header names used to create tags for the active span. The header name is used to - * populate the tag name, and the header value is used to populate the tag value. The tag is - * created if the specified header name is present in the request's headers. - * - * .. attention:: - * This field has been deprecated in favor of :ref:`custom_tags - * `. - */ - 'request_headers_for_tags'?: (string)[]; - /** - * Target percentage of requests managed by this HTTP connection manager that will be force - * traced if the :ref:`x-client-trace-id ` - * header is set. This field is a direct analog for the runtime variable - * 'tracing.client_sampling' in the :ref:`HTTP Connection Manager - * `. - * Default: 100% - */ - 'client_sampling'?: (_envoy_type_Percent); - /** - * Target percentage of requests managed by this HTTP connection manager that will be randomly - * selected for trace generation, if not requested by the client or not forced. This field is - * a direct analog for the runtime variable 'tracing.random_sampling' in the - * :ref:`HTTP Connection Manager `. - * Default: 100% - */ - 'random_sampling'?: (_envoy_type_Percent); - /** - * Target percentage of requests managed by this HTTP connection manager that will be traced - * after all other sampling checks have been applied (client-directed, force tracing, random - * sampling). This field functions as an upper limit on the total configured sampling rate. For - * instance, setting client_sampling to 100% but overall_sampling to 1% will result in only 1% - * of client requests with the appropriate headers to be force traced. This field is a direct - * analog for the runtime variable 'tracing.global_enabled' in the - * :ref:`HTTP Connection Manager `. - * Default: 100% - */ - 'overall_sampling'?: (_envoy_type_Percent); - /** - * Whether to annotate spans with additional data. If true, spans will include logs for stream - * events. - */ - 'verbose'?: (boolean); - /** - * Maximum length of the request path to extract and include in the HttpUrl tag. Used to - * truncate lengthy request paths to meet the needs of a tracing backend. - * Default: 256 - */ - 'max_path_tag_length'?: (_google_protobuf_UInt32Value); - /** - * A list of custom tags with unique tag name to create tags for the active span. - */ - 'custom_tags'?: (_envoy_type_tracing_v2_CustomTag)[]; - /** - * Configuration for an external tracing provider. - * If not specified, no tracing will be performed. - * - * .. attention:: - * Please be aware that *envoy.tracers.opencensus* provider can only be configured once - * in Envoy lifetime. - * Any attempts to reconfigure it or to use different configurations for different HCM filters - * will be rejected. - * Such a constraint is inherent to OpenCensus itself. It cannot be overcome without changes - * on OpenCensus side. - */ - 'provider'?: (_envoy_config_trace_v2_Tracing_Http); -} - -/** - * [#next-free-field: 10] - */ -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing__Output { - /** - * The span name will be derived from this field. If - * :ref:`traffic_direction ` is - * specified on the parent listener, then it is used instead of this field. - * - * .. attention:: - * This field has been deprecated in favor of `traffic_direction`. - */ - 'operation_name': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing_OperationName); - /** - * A list of header names used to create tags for the active span. The header name is used to - * populate the tag name, and the header value is used to populate the tag value. The tag is - * created if the specified header name is present in the request's headers. - * - * .. attention:: - * This field has been deprecated in favor of :ref:`custom_tags - * `. - */ - 'request_headers_for_tags': (string)[]; - /** - * Target percentage of requests managed by this HTTP connection manager that will be force - * traced if the :ref:`x-client-trace-id ` - * header is set. This field is a direct analog for the runtime variable - * 'tracing.client_sampling' in the :ref:`HTTP Connection Manager - * `. - * Default: 100% - */ - 'client_sampling'?: (_envoy_type_Percent__Output); - /** - * Target percentage of requests managed by this HTTP connection manager that will be randomly - * selected for trace generation, if not requested by the client or not forced. This field is - * a direct analog for the runtime variable 'tracing.random_sampling' in the - * :ref:`HTTP Connection Manager `. - * Default: 100% - */ - 'random_sampling'?: (_envoy_type_Percent__Output); - /** - * Target percentage of requests managed by this HTTP connection manager that will be traced - * after all other sampling checks have been applied (client-directed, force tracing, random - * sampling). This field functions as an upper limit on the total configured sampling rate. For - * instance, setting client_sampling to 100% but overall_sampling to 1% will result in only 1% - * of client requests with the appropriate headers to be force traced. This field is a direct - * analog for the runtime variable 'tracing.global_enabled' in the - * :ref:`HTTP Connection Manager `. - * Default: 100% - */ - 'overall_sampling'?: (_envoy_type_Percent__Output); - /** - * Whether to annotate spans with additional data. If true, spans will include logs for stream - * events. - */ - 'verbose': (boolean); - /** - * Maximum length of the request path to extract and include in the HttpUrl tag. Used to - * truncate lengthy request paths to meet the needs of a tracing backend. - * Default: 256 - */ - 'max_path_tag_length'?: (_google_protobuf_UInt32Value__Output); - /** - * A list of custom tags with unique tag name to create tags for the active span. - */ - 'custom_tags': (_envoy_type_tracing_v2_CustomTag__Output)[]; - /** - * Configuration for an external tracing provider. - * If not specified, no tracing will be performed. - * - * .. attention:: - * Please be aware that *envoy.tracers.opencensus* provider can only be configured once - * in Envoy lifetime. - * Any attempts to reconfigure it or to use different configurations for different HCM filters - * will be rejected. - * Such a constraint is inherent to OpenCensus itself. It cannot be overcome without changes - * on OpenCensus side. - */ - 'provider'?: (_envoy_config_trace_v2_Tracing_Http__Output); -} - -/** - * The configuration for HTTP upgrades. - * For each upgrade type desired, an UpgradeConfig must be added. - * - * .. warning:: - * - * The current implementation of upgrade headers does not handle - * multi-valued upgrade headers. Support for multi-valued headers may be - * added in the future if needed. - * - * .. warning:: - * The current implementation of upgrade headers does not work with HTTP/2 - * upstreams. - */ -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig { - /** - * The case-insensitive name of this upgrade, e.g. "websocket". - * For each upgrade type present in upgrade_configs, requests with - * Upgrade: [upgrade_type] - * will be proxied upstream. - */ - 'upgrade_type'?: (string); - /** - * If present, this represents the filter chain which will be created for - * this type of upgrade. If no filters are present, the filter chain for - * HTTP connections will be used for this upgrade type. - */ - 'filters'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter)[]; - /** - * Determines if upgrades are enabled or disabled by default. Defaults to true. - * This can be overridden on a per-route basis with :ref:`cluster - * ` as documented in the - * :ref:`upgrade documentation `. - */ - 'enabled'?: (_google_protobuf_BoolValue); -} - -/** - * The configuration for HTTP upgrades. - * For each upgrade type desired, an UpgradeConfig must be added. - * - * .. warning:: - * - * The current implementation of upgrade headers does not handle - * multi-valued upgrade headers. Support for multi-valued headers may be - * added in the future if needed. - * - * .. warning:: - * The current implementation of upgrade headers does not work with HTTP/2 - * upstreams. - */ -export interface _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig__Output { - /** - * The case-insensitive name of this upgrade, e.g. "websocket". - * For each upgrade type present in upgrade_configs, requests with - * Upgrade: [upgrade_type] - * will be proxied upstream. - */ - 'upgrade_type': (string); - /** - * If present, this represents the filter chain which will be created for - * this type of upgrade. If no filters are present, the filter chain for - * HTTP connections will be used for this upgrade type. - */ - 'filters': (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter__Output)[]; - /** - * Determines if upgrades are enabled or disabled by default. Defaults to true. - * This can be overridden on a per-route basis with :ref:`cluster - * ` as documented in the - * :ref:`upgrade documentation `. - */ - 'enabled'?: (_google_protobuf_BoolValue__Output); -} - -/** - * [#next-free-field: 37] - */ -export interface HttpConnectionManager { - /** - * Supplies the type of codec that the connection manager should use. - */ - 'codec_type'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType); - /** - * The human readable prefix to use when emitting statistics for the - * connection manager. See the :ref:`statistics documentation ` for - * more information. - */ - 'stat_prefix'?: (string); - /** - * The connection manager’s route table will be dynamically loaded via the RDS API. - */ - 'rds'?: (_envoy_config_filter_network_http_connection_manager_v2_Rds); - /** - * The route table for the connection manager is static and is specified in this property. - */ - 'route_config'?: (_envoy_api_v2_RouteConfiguration); - /** - * A list of individual HTTP filters that make up the filter chain for - * requests made to the connection manager. :ref:`Order matters ` - * as the filters are processed sequentially as request events happen. - */ - 'http_filters'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter)[]; - /** - * Whether the connection manager manipulates the :ref:`config_http_conn_man_headers_user-agent` - * and :ref:`config_http_conn_man_headers_downstream-service-cluster` headers. See the linked - * documentation for more information. Defaults to false. - */ - 'add_user_agent'?: (_google_protobuf_BoolValue); - /** - * Presence of the object defines whether the connection manager - * emits :ref:`tracing ` data to the :ref:`configured tracing provider - * `. - */ - 'tracing'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing); - /** - * Additional HTTP/1 settings that are passed to the HTTP/1 codec. - */ - 'http_protocol_options'?: (_envoy_api_v2_core_Http1ProtocolOptions); - /** - * Additional HTTP/2 settings that are passed directly to the HTTP/2 codec. - */ - 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions); - /** - * An optional override that the connection manager will write to the server - * header in responses. If not set, the default is *envoy*. - */ - 'server_name'?: (string); - /** - * The idle timeout for connections managed by the connection manager. The - * idle timeout is defined as the period in which there are no active - * requests. If not set, there is no idle timeout. When the idle timeout is - * reached the connection will be closed. If the connection is an HTTP/2 - * connection a drain sequence will occur prior to closing the connection. - * This field is deprecated. Use :ref:`idle_timeout - * ` - * instead. - */ - 'idle_timeout'?: (_google_protobuf_Duration); - /** - * The time that Envoy will wait between sending an HTTP/2 “shutdown - * notification” (GOAWAY frame with max stream ID) and a final GOAWAY frame. - * This is used so that Envoy provides a grace period for new streams that - * race with the final GOAWAY frame. During this grace period, Envoy will - * continue to accept new streams. After the grace period, a final GOAWAY - * frame is sent and Envoy will start refusing new streams. Draining occurs - * both when a connection hits the idle timeout or during general server - * draining. The default grace period is 5000 milliseconds (5 seconds) if this - * option is not specified. - */ - 'drain_timeout'?: (_google_protobuf_Duration); - /** - * Configuration for :ref:`HTTP access logs ` - * emitted by the connection manager. - */ - 'access_log'?: (_envoy_config_filter_accesslog_v2_AccessLog)[]; - /** - * If set to true, the connection manager will use the real remote address - * of the client connection when determining internal versus external origin and manipulating - * various headers. If set to false or absent, the connection manager will use the - * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. See the documentation for - * :ref:`config_http_conn_man_headers_x-forwarded-for`, - * :ref:`config_http_conn_man_headers_x-envoy-internal`, and - * :ref:`config_http_conn_man_headers_x-envoy-external-address` for more information. - */ - 'use_remote_address'?: (_google_protobuf_BoolValue); - /** - * Whether the connection manager will generate the :ref:`x-request-id - * ` header if it does not exist. This defaults to - * true. Generating a random UUID4 is expensive so in high throughput scenarios where this feature - * is not desired it can be disabled. - */ - 'generate_request_id'?: (_google_protobuf_BoolValue); - /** - * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP - * header. - */ - 'forward_client_cert_details'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails); - /** - * This field is valid only when :ref:`forward_client_cert_details - * ` - * is APPEND_FORWARD or SANITIZE_SET and the client connection is mTLS. It specifies the fields in - * the client certificate to be forwarded. Note that in the - * :ref:`config_http_conn_man_headers_x-forwarded-client-cert` header, *Hash* is always set, and - * *By* is always set when the client certificate presents the URI type Subject Alternative Name - * value. - */ - 'set_current_client_cert_details'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails); - /** - * If proxy_100_continue is true, Envoy will proxy incoming "Expect: - * 100-continue" headers upstream, and forward "100 Continue" responses - * downstream. If this is false or not set, Envoy will instead strip the - * "Expect: 100-continue" header, and send a "100 Continue" response itself. - */ - 'proxy_100_continue'?: (boolean); - /** - * The number of additional ingress proxy hops from the right side of the - * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header to trust when - * determining the origin client's IP address. The default is zero if this option - * is not specified. See the documentation for - * :ref:`config_http_conn_man_headers_x-forwarded-for` for more information. - */ - 'xff_num_trusted_hops'?: (number); - /** - * If - * :ref:`use_remote_address - * ` - * is true and represent_ipv4_remote_address_as_ipv4_mapped_ipv6 is true and the remote address is - * an IPv4 address, the address will be mapped to IPv6 before it is appended to *x-forwarded-for*. - * This is useful for testing compatibility of upstream services that parse the header value. For - * example, 50.0.0.1 is represented as ::FFFF:50.0.0.1. See `IPv4-Mapped IPv6 Addresses - * `_ for details. This will also affect the - * :ref:`config_http_conn_man_headers_x-envoy-external-address` header. See - * :ref:`http_connection_manager.represent_ipv4_remote_address_as_ipv4_mapped_ipv6 - * ` for runtime - * control. - * [#not-implemented-hide:] - */ - 'represent_ipv4_remote_address_as_ipv4_mapped_ipv6'?: (boolean); - /** - * If set, Envoy will not append the remote address to the - * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. This may be used in - * conjunction with HTTP filters that explicitly manipulate XFF after the HTTP connection manager - * has mutated the request headers. While :ref:`use_remote_address - * ` - * will also suppress XFF addition, it has consequences for logging and other - * Envoy uses of the remote address, so *skip_xff_append* should be used - * when only an elision of XFF addition is intended. - */ - 'skip_xff_append'?: (boolean); - /** - * Via header value to append to request and response headers. If this is - * empty, no via header will be appended. - */ - 'via'?: (string); - 'upgrade_configs'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig)[]; - /** - * The stream idle timeout for connections managed by the connection manager. - * If not specified, this defaults to 5 minutes. The default value was selected - * so as not to interfere with any smaller configured timeouts that may have - * existed in configurations prior to the introduction of this feature, while - * introducing robustness to TCP connections that terminate without a FIN. - * - * This idle timeout applies to new streams and is overridable by the - * :ref:`route-level idle_timeout - * `. Even on a stream in - * which the override applies, prior to receipt of the initial request - * headers, the :ref:`stream_idle_timeout - * ` - * applies. Each time an encode/decode event for headers or data is processed - * for the stream, the timer will be reset. If the timeout fires, the stream - * is terminated with a 408 Request Timeout error code if no upstream response - * header has been received, otherwise a stream reset occurs. - * - * Note that it is possible to idle timeout even if the wire traffic for a stream is non-idle, due - * to the granularity of events presented to the connection manager. For example, while receiving - * very large request headers, it may be the case that there is traffic regularly arriving on the - * wire while the connection manage is only able to observe the end-of-headers event, hence the - * stream may still idle timeout. - * - * A value of 0 will completely disable the connection manager stream idle - * timeout, although per-route idle timeout overrides will continue to apply. - */ - 'stream_idle_timeout'?: (_google_protobuf_Duration); - /** - * Configures what network addresses are considered internal for stats and header sanitation - * purposes. If unspecified, only RFC1918 IP addresses will be considered internal. - * See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more - * information about internal/external addresses. - */ - 'internal_address_config'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig); - /** - * The delayed close timeout is for downstream connections managed by the HTTP connection manager. - * It is defined as a grace period after connection close processing has been locally initiated - * during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy - * from the downstream connection) prior to Envoy closing the socket associated with that - * connection. - * NOTE: This timeout is enforced even when the socket associated with the downstream connection - * is pending a flush of the write buffer. However, any progress made writing data to the socket - * will restart the timer associated with this timeout. This means that the total grace period for - * a socket in this state will be - * +. - * - * Delaying Envoy's connection close and giving the peer the opportunity to initiate the close - * sequence mitigates a race condition that exists when downstream clients do not drain/process - * data in a connection's receive buffer after a remote close has been detected via a socket - * write(). This race leads to such clients failing to process the response code sent by Envoy, - * which could result in erroneous downstream processing. - * - * If the timeout triggers, Envoy will close the connection's socket. - * - * The default timeout is 1000 ms if this option is not specified. - * - * .. NOTE:: - * To be useful in avoiding the race condition described above, this timeout must be set - * to *at least* +<100ms to account for - * a reasonable "worst" case processing time for a full iteration of Envoy's event loop>. - * - * .. WARNING:: - * A value of 0 will completely disable delayed close processing. When disabled, the downstream - * connection's socket will be closed immediately after the write flush is completed or will - * never close if the write flush does not complete. - */ - 'delayed_close_timeout'?: (_google_protobuf_Duration); - /** - * The amount of time that Envoy will wait for the entire request to be received. - * The timer is activated when the request is initiated, and is disarmed when the last byte of the - * request is sent upstream (i.e. all decoding filters have processed the request), OR when the - * response is initiated. If not specified or set to 0, this timeout is disabled. - */ - 'request_timeout'?: (_google_protobuf_Duration); - /** - * The maximum request headers size for incoming connections. - * If unconfigured, the default max request headers allowed is 60 KiB. - * Requests that exceed this limit will receive a 431 response. - * The max configurable limit is 96 KiB, based on current implementation - * constraints. - */ - 'max_request_headers_kb'?: (_google_protobuf_UInt32Value); - /** - * Should paths be normalized according to RFC 3986 before any processing of - * requests by HTTP filters or routing? This affects the upstream *:path* header - * as well. For paths that fail this check, Envoy will respond with 400 to - * paths that are malformed. This defaults to false currently but will default - * true in the future. When not specified, this value may be overridden by the - * runtime variable - * :ref:`http_connection_manager.normalize_path`. - * See `Normalization and Comparison ` - * for details of normalization. - * Note that Envoy does not perform - * `case normalization ` - */ - 'normalize_path'?: (_google_protobuf_BoolValue); - /** - * A route table will be dynamically assigned to each request based on request attributes - * (e.g., the value of a header). The "routing scopes" (i.e., route tables) and "scope keys" are - * specified in this message. - */ - 'scoped_routes'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes); - /** - * Whether the connection manager will keep the :ref:`x-request-id - * ` header if passed for a request that is edge - * (Edge request is the request from external clients to front Envoy) and not reset it, which - * is the current Envoy behaviour. This defaults to false. - */ - 'preserve_external_request_id'?: (boolean); - /** - * Determines if adjacent slashes in the path are merged into one before any processing of - * requests by HTTP filters or routing. This affects the upstream *:path* header as well. Without - * setting this option, incoming requests with path `//dir///file` will not match against route - * with `prefix` match set to `/dir`. Defaults to `false`. Note that slash merging is not part of - * `HTTP spec ` and is provided for convenience. - */ - 'merge_slashes'?: (boolean); - /** - * Defines the action to be applied to the Server header on the response path. - * By default, Envoy will overwrite the header with the value specified in - * server_name. - */ - 'server_header_transformation'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation | keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation); - /** - * Additional settings for HTTP requests handled by the connection manager. These will be - * applicable to both HTTP1 and HTTP2 requests. - */ - 'common_http_protocol_options'?: (_envoy_api_v2_core_HttpProtocolOptions); - /** - * The configuration of the request ID extension. This includes operations such as - * generation, validation, and associated tracing operations. - * - * If not set, Envoy uses the default UUID-based behavior: - * - * 1. Request ID is propagated using *x-request-id* header. - * - * 2. Request ID is a universally unique identifier (UUID). - * - * 3. Tracing decision (sampled, forced, etc) is set in 14th byte of the UUID. - */ - 'request_id_extension'?: (_envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension); - 'route_specifier'?: "rds"|"route_config"|"scoped_routes"; -} - -/** - * [#next-free-field: 37] - */ -export interface HttpConnectionManager__Output { - /** - * Supplies the type of codec that the connection manager should use. - */ - 'codec_type': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_CodecType); - /** - * The human readable prefix to use when emitting statistics for the - * connection manager. See the :ref:`statistics documentation ` for - * more information. - */ - 'stat_prefix': (string); - /** - * The connection manager’s route table will be dynamically loaded via the RDS API. - */ - 'rds'?: (_envoy_config_filter_network_http_connection_manager_v2_Rds__Output); - /** - * The route table for the connection manager is static and is specified in this property. - */ - 'route_config'?: (_envoy_api_v2_RouteConfiguration__Output); - /** - * A list of individual HTTP filters that make up the filter chain for - * requests made to the connection manager. :ref:`Order matters ` - * as the filters are processed sequentially as request events happen. - */ - 'http_filters': (_envoy_config_filter_network_http_connection_manager_v2_HttpFilter__Output)[]; - /** - * Whether the connection manager manipulates the :ref:`config_http_conn_man_headers_user-agent` - * and :ref:`config_http_conn_man_headers_downstream-service-cluster` headers. See the linked - * documentation for more information. Defaults to false. - */ - 'add_user_agent'?: (_google_protobuf_BoolValue__Output); - /** - * Presence of the object defines whether the connection manager - * emits :ref:`tracing ` data to the :ref:`configured tracing provider - * `. - */ - 'tracing'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_Tracing__Output); - /** - * Additional HTTP/1 settings that are passed to the HTTP/1 codec. - */ - 'http_protocol_options'?: (_envoy_api_v2_core_Http1ProtocolOptions__Output); - /** - * Additional HTTP/2 settings that are passed directly to the HTTP/2 codec. - */ - 'http2_protocol_options'?: (_envoy_api_v2_core_Http2ProtocolOptions__Output); - /** - * An optional override that the connection manager will write to the server - * header in responses. If not set, the default is *envoy*. - */ - 'server_name': (string); - /** - * The idle timeout for connections managed by the connection manager. The - * idle timeout is defined as the period in which there are no active - * requests. If not set, there is no idle timeout. When the idle timeout is - * reached the connection will be closed. If the connection is an HTTP/2 - * connection a drain sequence will occur prior to closing the connection. - * This field is deprecated. Use :ref:`idle_timeout - * ` - * instead. - */ - 'idle_timeout'?: (_google_protobuf_Duration__Output); - /** - * The time that Envoy will wait between sending an HTTP/2 “shutdown - * notification” (GOAWAY frame with max stream ID) and a final GOAWAY frame. - * This is used so that Envoy provides a grace period for new streams that - * race with the final GOAWAY frame. During this grace period, Envoy will - * continue to accept new streams. After the grace period, a final GOAWAY - * frame is sent and Envoy will start refusing new streams. Draining occurs - * both when a connection hits the idle timeout or during general server - * draining. The default grace period is 5000 milliseconds (5 seconds) if this - * option is not specified. - */ - 'drain_timeout'?: (_google_protobuf_Duration__Output); - /** - * Configuration for :ref:`HTTP access logs ` - * emitted by the connection manager. - */ - 'access_log': (_envoy_config_filter_accesslog_v2_AccessLog__Output)[]; - /** - * If set to true, the connection manager will use the real remote address - * of the client connection when determining internal versus external origin and manipulating - * various headers. If set to false or absent, the connection manager will use the - * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. See the documentation for - * :ref:`config_http_conn_man_headers_x-forwarded-for`, - * :ref:`config_http_conn_man_headers_x-envoy-internal`, and - * :ref:`config_http_conn_man_headers_x-envoy-external-address` for more information. - */ - 'use_remote_address'?: (_google_protobuf_BoolValue__Output); - /** - * Whether the connection manager will generate the :ref:`x-request-id - * ` header if it does not exist. This defaults to - * true. Generating a random UUID4 is expensive so in high throughput scenarios where this feature - * is not desired it can be disabled. - */ - 'generate_request_id'?: (_google_protobuf_BoolValue__Output); - /** - * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP - * header. - */ - 'forward_client_cert_details': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ForwardClientCertDetails); - /** - * This field is valid only when :ref:`forward_client_cert_details - * ` - * is APPEND_FORWARD or SANITIZE_SET and the client connection is mTLS. It specifies the fields in - * the client certificate to be forwarded. Note that in the - * :ref:`config_http_conn_man_headers_x-forwarded-client-cert` header, *Hash* is always set, and - * *By* is always set when the client certificate presents the URI type Subject Alternative Name - * value. - */ - 'set_current_client_cert_details'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_SetCurrentClientCertDetails__Output); - /** - * If proxy_100_continue is true, Envoy will proxy incoming "Expect: - * 100-continue" headers upstream, and forward "100 Continue" responses - * downstream. If this is false or not set, Envoy will instead strip the - * "Expect: 100-continue" header, and send a "100 Continue" response itself. - */ - 'proxy_100_continue': (boolean); - /** - * The number of additional ingress proxy hops from the right side of the - * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header to trust when - * determining the origin client's IP address. The default is zero if this option - * is not specified. See the documentation for - * :ref:`config_http_conn_man_headers_x-forwarded-for` for more information. - */ - 'xff_num_trusted_hops': (number); - /** - * If - * :ref:`use_remote_address - * ` - * is true and represent_ipv4_remote_address_as_ipv4_mapped_ipv6 is true and the remote address is - * an IPv4 address, the address will be mapped to IPv6 before it is appended to *x-forwarded-for*. - * This is useful for testing compatibility of upstream services that parse the header value. For - * example, 50.0.0.1 is represented as ::FFFF:50.0.0.1. See `IPv4-Mapped IPv6 Addresses - * `_ for details. This will also affect the - * :ref:`config_http_conn_man_headers_x-envoy-external-address` header. See - * :ref:`http_connection_manager.represent_ipv4_remote_address_as_ipv4_mapped_ipv6 - * ` for runtime - * control. - * [#not-implemented-hide:] - */ - 'represent_ipv4_remote_address_as_ipv4_mapped_ipv6': (boolean); - /** - * If set, Envoy will not append the remote address to the - * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. This may be used in - * conjunction with HTTP filters that explicitly manipulate XFF after the HTTP connection manager - * has mutated the request headers. While :ref:`use_remote_address - * ` - * will also suppress XFF addition, it has consequences for logging and other - * Envoy uses of the remote address, so *skip_xff_append* should be used - * when only an elision of XFF addition is intended. - */ - 'skip_xff_append': (boolean); - /** - * Via header value to append to request and response headers. If this is - * empty, no via header will be appended. - */ - 'via': (string); - 'upgrade_configs': (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_UpgradeConfig__Output)[]; - /** - * The stream idle timeout for connections managed by the connection manager. - * If not specified, this defaults to 5 minutes. The default value was selected - * so as not to interfere with any smaller configured timeouts that may have - * existed in configurations prior to the introduction of this feature, while - * introducing robustness to TCP connections that terminate without a FIN. - * - * This idle timeout applies to new streams and is overridable by the - * :ref:`route-level idle_timeout - * `. Even on a stream in - * which the override applies, prior to receipt of the initial request - * headers, the :ref:`stream_idle_timeout - * ` - * applies. Each time an encode/decode event for headers or data is processed - * for the stream, the timer will be reset. If the timeout fires, the stream - * is terminated with a 408 Request Timeout error code if no upstream response - * header has been received, otherwise a stream reset occurs. - * - * Note that it is possible to idle timeout even if the wire traffic for a stream is non-idle, due - * to the granularity of events presented to the connection manager. For example, while receiving - * very large request headers, it may be the case that there is traffic regularly arriving on the - * wire while the connection manage is only able to observe the end-of-headers event, hence the - * stream may still idle timeout. - * - * A value of 0 will completely disable the connection manager stream idle - * timeout, although per-route idle timeout overrides will continue to apply. - */ - 'stream_idle_timeout'?: (_google_protobuf_Duration__Output); - /** - * Configures what network addresses are considered internal for stats and header sanitation - * purposes. If unspecified, only RFC1918 IP addresses will be considered internal. - * See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more - * information about internal/external addresses. - */ - 'internal_address_config'?: (_envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_InternalAddressConfig__Output); - /** - * The delayed close timeout is for downstream connections managed by the HTTP connection manager. - * It is defined as a grace period after connection close processing has been locally initiated - * during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy - * from the downstream connection) prior to Envoy closing the socket associated with that - * connection. - * NOTE: This timeout is enforced even when the socket associated with the downstream connection - * is pending a flush of the write buffer. However, any progress made writing data to the socket - * will restart the timer associated with this timeout. This means that the total grace period for - * a socket in this state will be - * +. - * - * Delaying Envoy's connection close and giving the peer the opportunity to initiate the close - * sequence mitigates a race condition that exists when downstream clients do not drain/process - * data in a connection's receive buffer after a remote close has been detected via a socket - * write(). This race leads to such clients failing to process the response code sent by Envoy, - * which could result in erroneous downstream processing. - * - * If the timeout triggers, Envoy will close the connection's socket. - * - * The default timeout is 1000 ms if this option is not specified. - * - * .. NOTE:: - * To be useful in avoiding the race condition described above, this timeout must be set - * to *at least* +<100ms to account for - * a reasonable "worst" case processing time for a full iteration of Envoy's event loop>. - * - * .. WARNING:: - * A value of 0 will completely disable delayed close processing. When disabled, the downstream - * connection's socket will be closed immediately after the write flush is completed or will - * never close if the write flush does not complete. - */ - 'delayed_close_timeout'?: (_google_protobuf_Duration__Output); - /** - * The amount of time that Envoy will wait for the entire request to be received. - * The timer is activated when the request is initiated, and is disarmed when the last byte of the - * request is sent upstream (i.e. all decoding filters have processed the request), OR when the - * response is initiated. If not specified or set to 0, this timeout is disabled. - */ - 'request_timeout'?: (_google_protobuf_Duration__Output); - /** - * The maximum request headers size for incoming connections. - * If unconfigured, the default max request headers allowed is 60 KiB. - * Requests that exceed this limit will receive a 431 response. - * The max configurable limit is 96 KiB, based on current implementation - * constraints. - */ - 'max_request_headers_kb'?: (_google_protobuf_UInt32Value__Output); - /** - * Should paths be normalized according to RFC 3986 before any processing of - * requests by HTTP filters or routing? This affects the upstream *:path* header - * as well. For paths that fail this check, Envoy will respond with 400 to - * paths that are malformed. This defaults to false currently but will default - * true in the future. When not specified, this value may be overridden by the - * runtime variable - * :ref:`http_connection_manager.normalize_path`. - * See `Normalization and Comparison ` - * for details of normalization. - * Note that Envoy does not perform - * `case normalization ` - */ - 'normalize_path'?: (_google_protobuf_BoolValue__Output); - /** - * A route table will be dynamically assigned to each request based on request attributes - * (e.g., the value of a header). The "routing scopes" (i.e., route tables) and "scope keys" are - * specified in this message. - */ - 'scoped_routes'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes__Output); - /** - * Whether the connection manager will keep the :ref:`x-request-id - * ` header if passed for a request that is edge - * (Edge request is the request from external clients to front Envoy) and not reset it, which - * is the current Envoy behaviour. This defaults to false. - */ - 'preserve_external_request_id': (boolean); - /** - * Determines if adjacent slashes in the path are merged into one before any processing of - * requests by HTTP filters or routing. This affects the upstream *:path* header as well. Without - * setting this option, incoming requests with path `//dir///file` will not match against route - * with `prefix` match set to `/dir`. Defaults to `false`. Note that slash merging is not part of - * `HTTP spec ` and is provided for convenience. - */ - 'merge_slashes': (boolean); - /** - * Defines the action to be applied to the Server header on the response path. - * By default, Envoy will overwrite the header with the value specified in - * server_name. - */ - 'server_header_transformation': (keyof typeof _envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_ServerHeaderTransformation); - /** - * Additional settings for HTTP requests handled by the connection manager. These will be - * applicable to both HTTP1 and HTTP2 requests. - */ - 'common_http_protocol_options'?: (_envoy_api_v2_core_HttpProtocolOptions__Output); - /** - * The configuration of the request ID extension. This includes operations such as - * generation, validation, and associated tracing operations. - * - * If not set, Envoy uses the default UUID-based behavior: - * - * 1. Request ID is propagated using *x-request-id* header. - * - * 2. Request ID is a universally unique identifier (UUID). - * - * 3. Tracing decision (sampled, forced, etc) is set in 14th byte of the UUID. - */ - 'request_id_extension'?: (_envoy_config_filter_network_http_connection_manager_v2_RequestIDExtension__Output); - 'route_specifier': "rds"|"route_config"|"scoped_routes"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpFilter.ts deleted file mode 100644 index 84e4292fc..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/HttpFilter.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../../google/protobuf/Any'; - -export interface HttpFilter { - /** - * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. - */ - 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - /** - * Filter specific configuration which depends on the filter being instantiated. See the supported - * filters for further documentation. - */ - 'config_type'?: "config"|"typed_config"; -} - -export interface HttpFilter__Output { - /** - * The name of the filter to instantiate. The name must match a - * :ref:`supported filter `. - */ - 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - /** - * Filter specific configuration which depends on the filter being instantiated. See the supported - * filters for further documentation. - */ - 'config_type': "config"|"typed_config"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRds.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRds.ts deleted file mode 100644 index b3d89dffb..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRds.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -import type { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../../../../envoy/api/v2/core/ConfigSource'; - -export interface ScopedRds { - /** - * Configuration source specifier for scoped RDS. - */ - 'scoped_rds_config_source'?: (_envoy_api_v2_core_ConfigSource); -} - -export interface ScopedRds__Output { - /** - * Configuration source specifier for scoped RDS. - */ - 'scoped_rds_config_source'?: (_envoy_api_v2_core_ConfigSource__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList.ts b/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList.ts deleted file mode 100644 index a57f1725e..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto - -import type { ScopedRouteConfiguration as _envoy_api_v2_ScopedRouteConfiguration, ScopedRouteConfiguration__Output as _envoy_api_v2_ScopedRouteConfiguration__Output } from '../../../../../../envoy/api/v2/ScopedRouteConfiguration'; - -/** - * This message is used to work around the limitations with 'oneof' and repeated fields. - */ -export interface ScopedRouteConfigurationsList { - 'scoped_route_configurations'?: (_envoy_api_v2_ScopedRouteConfiguration)[]; -} - -/** - * This message is used to work around the limitations with 'oneof' and repeated fields. - */ -export interface ScopedRouteConfigurationsList__Output { - 'scoped_route_configurations': (_envoy_api_v2_ScopedRouteConfiguration__Output)[]; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ActiveRawUdpListenerConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ActiveRawUdpListenerConfig.ts similarity index 56% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ActiveRawUdpListenerConfig.ts rename to packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ActiveRawUdpListenerConfig.ts index 7bb47c26c..3cc895aa9 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ActiveRawUdpListenerConfig.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ActiveRawUdpListenerConfig.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener/udp_listener_config.proto +// Original file: deps/envoy-api/envoy/config/listener/v3/udp_listener_config.proto export interface ActiveRawUdpListenerConfig { diff --git a/packages/grpc-js-xds/src/generated/envoy/config/listener/v2/ApiListener.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ApiListener.ts similarity index 74% rename from packages/grpc-js-xds/src/generated/envoy/config/listener/v2/ApiListener.ts rename to packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ApiListener.ts index f683d3e82..5a8e7f37f 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/listener/v2/ApiListener.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ApiListener.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/config/listener/v2/api_listener.proto +// Original file: deps/envoy-api/envoy/config/listener/v3/api_listener.proto import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; @@ -10,14 +10,15 @@ export interface 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) + * envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager (HTTP) + * envoy.extensions.filters.network.http_connection_manager.v3.EnvoyMobileHttpConnectionManager (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.] */ - 'api_listener'?: (_google_protobuf_Any); + 'api_listener'?: (_google_protobuf_Any | null); } /** @@ -28,12 +29,13 @@ export interface ApiListener__Output { /** * 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) + * envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager (HTTP) + * envoy.extensions.filters.network.http_connection_manager.v3.EnvoyMobileHttpConnectionManager (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.] */ - 'api_listener'?: (_google_protobuf_Any__Output); + 'api_listener': (_google_protobuf_Any__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/Filter.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/Filter.ts new file mode 100644 index 000000000..66e903b28 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/Filter.ts @@ -0,0 +1,54 @@ +// Original file: deps/envoy-api/envoy/config/listener/v3/listener_components.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { ExtensionConfigSource as _envoy_config_core_v3_ExtensionConfigSource, ExtensionConfigSource__Output as _envoy_config_core_v3_ExtensionConfigSource__Output } from '../../../../envoy/config/core/v3/ExtensionConfigSource'; + +/** + * [#next-free-field: 6] + */ +export interface Filter { + /** + * The name of the filter to instantiate. The name must match a + * :ref:`supported filter `. + */ + 'name'?: (string); + /** + * Filter specific configuration which depends on the filter being + * instantiated. See the supported filters for further documentation. + * [#extension-category: envoy.filters.network] + */ + 'typed_config'?: (_google_protobuf_Any | null); + /** + * Configuration source specifier for an extension configuration discovery + * service. In case of a failure and without the default configuration, the + * listener closes the connections. + * [#not-implemented-hide:] + */ + 'config_discovery'?: (_envoy_config_core_v3_ExtensionConfigSource | null); + 'config_type'?: "typed_config"|"config_discovery"; +} + +/** + * [#next-free-field: 6] + */ +export interface Filter__Output { + /** + * The name of the filter to instantiate. The name must match a + * :ref:`supported filter `. + */ + 'name': (string); + /** + * Filter specific configuration which depends on the filter being + * instantiated. See the supported filters for further documentation. + * [#extension-category: envoy.filters.network] + */ + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * Configuration source specifier for an extension configuration discovery + * service. In case of a failure and without the default configuration, the + * listener closes the connections. + * [#not-implemented-hide:] + */ + 'config_discovery'?: (_envoy_config_core_v3_ExtensionConfigSource__Output | null); + 'config_type': "typed_config"|"config_discovery"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/FilterChain.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/FilterChain.ts new file mode 100644 index 000000000..e65f433c4 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/FilterChain.ts @@ -0,0 +1,172 @@ +// Original file: deps/envoy-api/envoy/config/listener/v3/listener_components.proto + +import type { FilterChainMatch as _envoy_config_listener_v3_FilterChainMatch, FilterChainMatch__Output as _envoy_config_listener_v3_FilterChainMatch__Output } from '../../../../envoy/config/listener/v3/FilterChainMatch'; +import type { Filter as _envoy_config_listener_v3_Filter, Filter__Output as _envoy_config_listener_v3_Filter__Output } from '../../../../envoy/config/listener/v3/Filter'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { Metadata as _envoy_config_core_v3_Metadata, Metadata__Output as _envoy_config_core_v3_Metadata__Output } from '../../../../envoy/config/core/v3/Metadata'; +import type { TransportSocket as _envoy_config_core_v3_TransportSocket, TransportSocket__Output as _envoy_config_core_v3_TransportSocket__Output } from '../../../../envoy/config/core/v3/TransportSocket'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; + +/** + * The configuration for on-demand filter chain. If this field is not empty in FilterChain message, + * a filter chain will be built on-demand. + * On-demand filter chains help speedup the warming up of listeners since the building and initialization of + * an on-demand filter chain will be postponed to the arrival of new connection requests that require this filter chain. + * Filter chains that are not often used can be set as on-demand. + */ +export interface _envoy_config_listener_v3_FilterChain_OnDemandConfiguration { + /** + * The timeout to wait for filter chain placeholders to complete rebuilding. + * 1. If this field is set to 0, timeout is disabled. + * 2. If not specified, a default timeout of 15s is used. + * Rebuilding will wait until dependencies are ready, have failed, or this timeout is reached. + * Upon failure or timeout, all connections related to this filter chain will be closed. + * Rebuilding will start again on the next new connection. + */ + 'rebuild_timeout'?: (_google_protobuf_Duration | null); +} + +/** + * The configuration for on-demand filter chain. If this field is not empty in FilterChain message, + * a filter chain will be built on-demand. + * On-demand filter chains help speedup the warming up of listeners since the building and initialization of + * an on-demand filter chain will be postponed to the arrival of new connection requests that require this filter chain. + * Filter chains that are not often used can be set as on-demand. + */ +export interface _envoy_config_listener_v3_FilterChain_OnDemandConfiguration__Output { + /** + * The timeout to wait for filter chain placeholders to complete rebuilding. + * 1. If this field is set to 0, timeout is disabled. + * 2. If not specified, a default timeout of 15s is used. + * Rebuilding will wait until dependencies are ready, have failed, or this timeout is reached. + * Upon failure or timeout, all connections related to this filter chain will be closed. + * Rebuilding will start again on the next new connection. + */ + 'rebuild_timeout': (_google_protobuf_Duration__Output | null); +} + +/** + * A filter chain wraps a set of match criteria, an option TLS context, a set of filters, and + * various other parameters. + * [#next-free-field: 10] + */ +export interface FilterChain { + /** + * The criteria to use when matching a connection to this filter chain. + */ + 'filter_chain_match'?: (_envoy_config_listener_v3_FilterChainMatch | null); + /** + * A list of individual network filters that make up the filter chain for + * connections established with the listener. Order matters as the filters are + * processed sequentially as connection events happen. Note: If the filter + * list is empty, the connection will close by default. + */ + 'filters'?: (_envoy_config_listener_v3_Filter)[]; + /** + * Whether the listener should expect a PROXY protocol V1 header on new + * connections. If this option is enabled, the listener will assume that that + * remote address of the connection is the one specified in the header. Some + * load balancers including the AWS ELB support this option. If the option is + * absent or set to false, Envoy will use the physical peer address of the + * connection as the remote address. + * + * This field is deprecated. Add a + * :ref:`PROXY protocol listener filter ` + * explicitly instead. + */ + 'use_proxy_proto'?: (_google_protobuf_BoolValue | null); + /** + * [#not-implemented-hide:] filter chain metadata. + */ + 'metadata'?: (_envoy_config_core_v3_Metadata | null); + /** + * Optional custom transport socket implementation to use for downstream connections. + * To setup TLS, set a transport socket with name `envoy.transport_sockets.tls` and + * :ref:`DownstreamTlsContext ` in the `typed_config`. + * If no transport socket configuration is specified, new connections + * will be set up with plaintext. + * [#extension-category: envoy.transport_sockets.downstream] + */ + 'transport_socket'?: (_envoy_config_core_v3_TransportSocket | null); + /** + * [#not-implemented-hide:] The unique name (or empty) by which this filter chain is known. If no + * name is provided, Envoy will allocate an internal UUID for the filter chain. If the filter + * chain is to be dynamically updated or removed via FCDS a unique name must be provided. + */ + 'name'?: (string); + /** + * [#not-implemented-hide:] The configuration to specify whether the filter chain will be built on-demand. + * If this field is not empty, the filter chain will be built on-demand. + * Otherwise, the filter chain will be built normally and block listener warming. + */ + 'on_demand_configuration'?: (_envoy_config_listener_v3_FilterChain_OnDemandConfiguration | null); + /** + * If present and nonzero, the amount of time to allow incoming connections to complete any + * transport socket negotiations. If this expires before the transport reports connection + * establishment, the connection is summarily closed. + */ + 'transport_socket_connect_timeout'?: (_google_protobuf_Duration | null); +} + +/** + * A filter chain wraps a set of match criteria, an option TLS context, a set of filters, and + * various other parameters. + * [#next-free-field: 10] + */ +export interface FilterChain__Output { + /** + * The criteria to use when matching a connection to this filter chain. + */ + 'filter_chain_match': (_envoy_config_listener_v3_FilterChainMatch__Output | null); + /** + * A list of individual network filters that make up the filter chain for + * connections established with the listener. Order matters as the filters are + * processed sequentially as connection events happen. Note: If the filter + * list is empty, the connection will close by default. + */ + 'filters': (_envoy_config_listener_v3_Filter__Output)[]; + /** + * Whether the listener should expect a PROXY protocol V1 header on new + * connections. If this option is enabled, the listener will assume that that + * remote address of the connection is the one specified in the header. Some + * load balancers including the AWS ELB support this option. If the option is + * absent or set to false, Envoy will use the physical peer address of the + * connection as the remote address. + * + * This field is deprecated. Add a + * :ref:`PROXY protocol listener filter ` + * explicitly instead. + */ + 'use_proxy_proto': (_google_protobuf_BoolValue__Output | null); + /** + * [#not-implemented-hide:] filter chain metadata. + */ + 'metadata': (_envoy_config_core_v3_Metadata__Output | null); + /** + * Optional custom transport socket implementation to use for downstream connections. + * To setup TLS, set a transport socket with name `envoy.transport_sockets.tls` and + * :ref:`DownstreamTlsContext ` in the `typed_config`. + * If no transport socket configuration is specified, new connections + * will be set up with plaintext. + * [#extension-category: envoy.transport_sockets.downstream] + */ + 'transport_socket': (_envoy_config_core_v3_TransportSocket__Output | null); + /** + * [#not-implemented-hide:] The unique name (or empty) by which this filter chain is known. If no + * name is provided, Envoy will allocate an internal UUID for the filter chain. If the filter + * chain is to be dynamically updated or removed via FCDS a unique name must be provided. + */ + 'name': (string); + /** + * [#not-implemented-hide:] The configuration to specify whether the filter chain will be built on-demand. + * If this field is not empty, the filter chain will be built on-demand. + * Otherwise, the filter chain will be built normally and block listener warming. + */ + 'on_demand_configuration': (_envoy_config_listener_v3_FilterChain_OnDemandConfiguration__Output | null); + /** + * If present and nonzero, the amount of time to allow incoming connections to complete any + * transport socket negotiations. If this expires before the transport reports connection + * establishment, the connection is summarily closed. + */ + 'transport_socket_connect_timeout': (_google_protobuf_Duration__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/FilterChainMatch.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/FilterChainMatch.ts similarity index 70% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/listener/FilterChainMatch.ts rename to packages/grpc-js-xds/src/generated/envoy/config/listener/v3/FilterChainMatch.ts index 881a5a961..259888217 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/FilterChainMatch.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/FilterChainMatch.ts @@ -1,11 +1,11 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener/listener_components.proto +// Original file: deps/envoy-api/envoy/config/listener/v3/listener_components.proto -import type { CidrRange as _envoy_api_v2_core_CidrRange, CidrRange__Output as _envoy_api_v2_core_CidrRange__Output } from '../../../../envoy/api/v2/core/CidrRange'; +import type { CidrRange as _envoy_config_core_v3_CidrRange, CidrRange__Output as _envoy_config_core_v3_CidrRange__Output } from '../../../../envoy/config/core/v3/CidrRange'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -// Original file: deps/envoy-api/envoy/api/v2/listener/listener_components.proto +// Original file: deps/envoy-api/envoy/config/listener/v3/listener_components.proto -export enum _envoy_api_v2_listener_FilterChainMatch_ConnectionSourceType { +export enum _envoy_config_listener_v3_FilterChainMatch_ConnectionSourceType { /** * Any connection source matches. */ @@ -13,7 +13,7 @@ export enum _envoy_api_v2_listener_FilterChainMatch_ConnectionSourceType { /** * Match a connection originating from the same host. */ - LOCAL = 1, + SAME_IP_OR_LOOPBACK = 1, /** * Match a connection originating from a different host. */ @@ -35,9 +35,12 @@ export enum _envoy_api_v2_listener_FilterChainMatch_ConnectionSourceType { * 3. Server name (e.g. SNI for TLS protocol), * 4. Transport protocol. * 5. Application protocols (e.g. ALPN for TLS protocol). - * 6. Source type (e.g. any, local or external network). - * 7. Source IP address. - * 8. Source port. + * 6. Directly connected source IP address (this will only be different from the source IP address + * when using a listener filter that overrides the source address, such as the :ref:`Proxy Protocol + * listener filter `). + * 7. Source type (e.g. any, local or external network). + * 8. Source IP address. + * 9. Source port. * * For criteria that allow ranges or wildcards, the most specific value in any * of the configured filter chains that matches the incoming connection is going @@ -45,18 +48,30 @@ export enum _envoy_api_v2_listener_FilterChainMatch_ConnectionSourceType { * ``www.example.com``, then ``*.example.com``, then ``*.com``, then any filter * chain without ``server_names`` requirements). * + * A different way to reason about the filter chain matches: + * Suppose there exists N filter chains. Prune the filter chain set using the above 8 steps. + * In each step, filter chains which most specifically matches the attributes continue to the next step. + * The listener guarantees at most 1 filter chain is left after all of the steps. + * + * Example: + * + * For destination port, filter chains specifying the destination port of incoming traffic are the + * most specific match. If none of the filter chains specifies the exact destination port, the filter + * chains which do not specify ports are the most specific match. Filter chains specifying the + * wrong port can never be the most specific match. + * * [#comment: Implemented rules are kept in the preference order, with deprecated fields * listed at the end, because that's how we want to list them in the docs. * * [#comment:TODO(PiotrSikora): Add support for configurable precedence of the rules] - * [#next-free-field: 13] + * [#next-free-field: 14] */ export interface FilterChainMatch { /** * If non-empty, an IP address and prefix length to match addresses when the * listener is bound to 0.0.0.0/:: or when use_original_dst is specified. */ - 'prefix_ranges'?: (_envoy_api_v2_core_CidrRange)[]; + 'prefix_ranges'?: (_envoy_config_core_v3_CidrRange)[]; /** * If non-empty, an IP address and suffix length to match addresses when the * listener is bound to 0.0.0.0/:: or when use_original_dst is specified. @@ -66,14 +81,14 @@ export interface FilterChainMatch { /** * [#not-implemented-hide:] */ - 'suffix_len'?: (_google_protobuf_UInt32Value); + 'suffix_len'?: (_google_protobuf_UInt32Value | null); /** * The criteria is satisfied if the source IP address of the downstream * connection is contained in at least one of the specified subnets. If the * parameter is not specified or the list is empty, the source IP address is * ignored. */ - 'source_prefix_ranges'?: (_envoy_api_v2_core_CidrRange)[]; + 'source_prefix_ranges'?: (_envoy_config_core_v3_CidrRange)[]; /** * The criteria is satisfied if the source port of the downstream connection * is contained in at least one of the specified ports. If the parameter is @@ -84,7 +99,7 @@ export interface FilterChainMatch { * Optional destination port to consider when use_original_dst is set on the * listener in determining a filter chain match. */ - 'destination_port'?: (_google_protobuf_UInt32Value); + 'destination_port'?: (_google_protobuf_UInt32Value | null); /** * If non-empty, a transport protocol to consider when determining a filter chain match. * This value will be compared against the transport protocol of a new connection, when @@ -138,7 +153,13 @@ export interface FilterChainMatch { /** * Specifies the connection source IP match type. Can be any, local or external network. */ - 'source_type'?: (_envoy_api_v2_listener_FilterChainMatch_ConnectionSourceType | keyof typeof _envoy_api_v2_listener_FilterChainMatch_ConnectionSourceType); + 'source_type'?: (_envoy_config_listener_v3_FilterChainMatch_ConnectionSourceType | keyof typeof _envoy_config_listener_v3_FilterChainMatch_ConnectionSourceType); + /** + * The criteria is satisfied if the directly connected source IP address of the downstream + * connection is contained in at least one of the specified subnets. If the parameter is not + * specified or the list is empty, the directly connected source IP address is ignored. + */ + 'direct_source_prefix_ranges'?: (_envoy_config_core_v3_CidrRange)[]; } /** @@ -156,9 +177,12 @@ export interface FilterChainMatch { * 3. Server name (e.g. SNI for TLS protocol), * 4. Transport protocol. * 5. Application protocols (e.g. ALPN for TLS protocol). - * 6. Source type (e.g. any, local or external network). - * 7. Source IP address. - * 8. Source port. + * 6. Directly connected source IP address (this will only be different from the source IP address + * when using a listener filter that overrides the source address, such as the :ref:`Proxy Protocol + * listener filter `). + * 7. Source type (e.g. any, local or external network). + * 8. Source IP address. + * 9. Source port. * * For criteria that allow ranges or wildcards, the most specific value in any * of the configured filter chains that matches the incoming connection is going @@ -166,18 +190,30 @@ export interface FilterChainMatch { * ``www.example.com``, then ``*.example.com``, then ``*.com``, then any filter * chain without ``server_names`` requirements). * + * A different way to reason about the filter chain matches: + * Suppose there exists N filter chains. Prune the filter chain set using the above 8 steps. + * In each step, filter chains which most specifically matches the attributes continue to the next step. + * The listener guarantees at most 1 filter chain is left after all of the steps. + * + * Example: + * + * For destination port, filter chains specifying the destination port of incoming traffic are the + * most specific match. If none of the filter chains specifies the exact destination port, the filter + * chains which do not specify ports are the most specific match. Filter chains specifying the + * wrong port can never be the most specific match. + * * [#comment: Implemented rules are kept in the preference order, with deprecated fields * listed at the end, because that's how we want to list them in the docs. * * [#comment:TODO(PiotrSikora): Add support for configurable precedence of the rules] - * [#next-free-field: 13] + * [#next-free-field: 14] */ export interface FilterChainMatch__Output { /** * If non-empty, an IP address and prefix length to match addresses when the * listener is bound to 0.0.0.0/:: or when use_original_dst is specified. */ - 'prefix_ranges': (_envoy_api_v2_core_CidrRange__Output)[]; + 'prefix_ranges': (_envoy_config_core_v3_CidrRange__Output)[]; /** * If non-empty, an IP address and suffix length to match addresses when the * listener is bound to 0.0.0.0/:: or when use_original_dst is specified. @@ -187,14 +223,14 @@ export interface FilterChainMatch__Output { /** * [#not-implemented-hide:] */ - 'suffix_len'?: (_google_protobuf_UInt32Value__Output); + 'suffix_len': (_google_protobuf_UInt32Value__Output | null); /** * The criteria is satisfied if the source IP address of the downstream * connection is contained in at least one of the specified subnets. If the * parameter is not specified or the list is empty, the source IP address is * ignored. */ - 'source_prefix_ranges': (_envoy_api_v2_core_CidrRange__Output)[]; + 'source_prefix_ranges': (_envoy_config_core_v3_CidrRange__Output)[]; /** * The criteria is satisfied if the source port of the downstream connection * is contained in at least one of the specified ports. If the parameter is @@ -205,7 +241,7 @@ export interface FilterChainMatch__Output { * Optional destination port to consider when use_original_dst is set on the * listener in determining a filter chain match. */ - 'destination_port'?: (_google_protobuf_UInt32Value__Output); + 'destination_port': (_google_protobuf_UInt32Value__Output | null); /** * If non-empty, a transport protocol to consider when determining a filter chain match. * This value will be compared against the transport protocol of a new connection, when @@ -259,5 +295,11 @@ export interface FilterChainMatch__Output { /** * Specifies the connection source IP match type. Can be any, local or external network. */ - 'source_type': (keyof typeof _envoy_api_v2_listener_FilterChainMatch_ConnectionSourceType); + 'source_type': (keyof typeof _envoy_config_listener_v3_FilterChainMatch_ConnectionSourceType); + /** + * The criteria is satisfied if the directly connected source IP address of the downstream + * connection is contained in at least one of the specified subnets. If the parameter is not + * specified or the list is empty, the directly connected source IP address is ignored. + */ + 'direct_source_prefix_ranges': (_envoy_config_core_v3_CidrRange__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/Listener.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/Listener.ts similarity index 51% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/Listener.ts rename to packages/grpc-js-xds/src/generated/envoy/config/listener/v3/Listener.ts index 8aed6564d..3df1006b7 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/Listener.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/Listener.ts @@ -1,81 +1,73 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener.proto +// Original file: deps/envoy-api/envoy/config/listener/v3/listener.proto -import type { Address as _envoy_api_v2_core_Address, Address__Output as _envoy_api_v2_core_Address__Output } from '../../../envoy/api/v2/core/Address'; -import type { FilterChain as _envoy_api_v2_listener_FilterChain, FilterChain__Output as _envoy_api_v2_listener_FilterChain__Output } from '../../../envoy/api/v2/listener/FilterChain'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../google/protobuf/BoolValue'; -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../google/protobuf/UInt32Value'; -import type { Metadata as _envoy_api_v2_core_Metadata, Metadata__Output as _envoy_api_v2_core_Metadata__Output } from '../../../envoy/api/v2/core/Metadata'; -import type { ListenerFilter as _envoy_api_v2_listener_ListenerFilter, ListenerFilter__Output as _envoy_api_v2_listener_ListenerFilter__Output } from '../../../envoy/api/v2/listener/ListenerFilter'; -import type { SocketOption as _envoy_api_v2_core_SocketOption, SocketOption__Output as _envoy_api_v2_core_SocketOption__Output } from '../../../envoy/api/v2/core/SocketOption'; -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; -import type { TrafficDirection as _envoy_api_v2_core_TrafficDirection } from '../../../envoy/api/v2/core/TrafficDirection'; -import type { UdpListenerConfig as _envoy_api_v2_listener_UdpListenerConfig, UdpListenerConfig__Output as _envoy_api_v2_listener_UdpListenerConfig__Output } from '../../../envoy/api/v2/listener/UdpListenerConfig'; -import type { ApiListener as _envoy_config_listener_v2_ApiListener, ApiListener__Output as _envoy_config_listener_v2_ApiListener__Output } from '../../../envoy/config/listener/v2/ApiListener'; -import type { AccessLog as _envoy_config_filter_accesslog_v2_AccessLog, AccessLog__Output as _envoy_config_filter_accesslog_v2_AccessLog__Output } from '../../../envoy/config/filter/accesslog/v2/AccessLog'; +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; +import type { FilterChain as _envoy_config_listener_v3_FilterChain, FilterChain__Output as _envoy_config_listener_v3_FilterChain__Output } from '../../../../envoy/config/listener/v3/FilterChain'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { Metadata as _envoy_config_core_v3_Metadata, Metadata__Output as _envoy_config_core_v3_Metadata__Output } from '../../../../envoy/config/core/v3/Metadata'; +import type { ListenerFilter as _envoy_config_listener_v3_ListenerFilter, ListenerFilter__Output as _envoy_config_listener_v3_ListenerFilter__Output } from '../../../../envoy/config/listener/v3/ListenerFilter'; +import type { SocketOption as _envoy_config_core_v3_SocketOption, SocketOption__Output as _envoy_config_core_v3_SocketOption__Output } from '../../../../envoy/config/core/v3/SocketOption'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { TrafficDirection as _envoy_config_core_v3_TrafficDirection } from '../../../../envoy/config/core/v3/TrafficDirection'; +import type { UdpListenerConfig as _envoy_config_listener_v3_UdpListenerConfig, UdpListenerConfig__Output as _envoy_config_listener_v3_UdpListenerConfig__Output } from '../../../../envoy/config/listener/v3/UdpListenerConfig'; +import type { ApiListener as _envoy_config_listener_v3_ApiListener, ApiListener__Output as _envoy_config_listener_v3_ApiListener__Output } from '../../../../envoy/config/listener/v3/ApiListener'; +import type { AccessLog as _envoy_config_accesslog_v3_AccessLog, AccessLog__Output as _envoy_config_accesslog_v3_AccessLog__Output } from '../../../../envoy/config/accesslog/v3/AccessLog'; /** * Configuration for listener connection balancing. */ -export interface _envoy_api_v2_Listener_ConnectionBalanceConfig { +export interface _envoy_config_listener_v3_Listener_ConnectionBalanceConfig { /** * If specified, the listener will use the exact connection balancer. */ - 'exact_balance'?: (_envoy_api_v2_Listener_ConnectionBalanceConfig_ExactBalance); + 'exact_balance'?: (_envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance | null); 'balance_type'?: "exact_balance"; } /** * Configuration for listener connection balancing. */ -export interface _envoy_api_v2_Listener_ConnectionBalanceConfig__Output { +export interface _envoy_config_listener_v3_Listener_ConnectionBalanceConfig__Output { /** * If specified, the listener will use the exact connection balancer. */ - 'exact_balance'?: (_envoy_api_v2_Listener_ConnectionBalanceConfig_ExactBalance__Output); + 'exact_balance'?: (_envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance__Output | null); 'balance_type': "exact_balance"; } /** * [#not-implemented-hide:] */ -export interface _envoy_api_v2_Listener_DeprecatedV1 { +export interface _envoy_config_listener_v3_Listener_DeprecatedV1 { /** * Whether the listener should bind to the port. A listener that doesn't * bind can only receive connections redirected from other listeners that * set use_original_dst parameter to true. Default is true. * - * This is deprecated in v2, all Listeners will bind to their port. An - * additional filter chain must be created for every original destination - * port this listener may redirect to in v2, with the original port - * specified in the FilterChainMatch destination_port field. - * - * [#comment:TODO(PiotrSikora): Remove this once verified that we no longer need it.] + * This is deprecated. Use :ref:`Listener.bind_to_port + * ` */ - 'bind_to_port'?: (_google_protobuf_BoolValue); + 'bind_to_port'?: (_google_protobuf_BoolValue | null); } /** * [#not-implemented-hide:] */ -export interface _envoy_api_v2_Listener_DeprecatedV1__Output { +export interface _envoy_config_listener_v3_Listener_DeprecatedV1__Output { /** * Whether the listener should bind to the port. A listener that doesn't * bind can only receive connections redirected from other listeners that * set use_original_dst parameter to true. Default is true. * - * This is deprecated in v2, all Listeners will bind to their port. An - * additional filter chain must be created for every original destination - * port this listener may redirect to in v2, with the original port - * specified in the FilterChainMatch destination_port field. - * - * [#comment:TODO(PiotrSikora): Remove this once verified that we no longer need it.] + * This is deprecated. Use :ref:`Listener.bind_to_port + * ` */ - 'bind_to_port'?: (_google_protobuf_BoolValue__Output); + 'bind_to_port': (_google_protobuf_BoolValue__Output | null); } -// Original file: deps/envoy-api/envoy/api/v2/listener.proto +// Original file: deps/envoy-api/envoy/config/listener/v3/listener.proto -export enum _envoy_api_v2_Listener_DrainType { +export enum _envoy_config_listener_v3_Listener_DrainType { /** * Drain in response to calling /healthcheck/fail admin endpoint (along with the health check * filter), listener removal/modification, and hot restart. @@ -97,7 +89,7 @@ export enum _envoy_api_v2_Listener_DrainType { * sacrifices accept throughput for accuracy and should be used when there are a small number of * connections that rarely cycle (e.g., service mesh gRPC egress). */ -export interface _envoy_api_v2_Listener_ConnectionBalanceConfig_ExactBalance { +export interface _envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance { } /** @@ -108,11 +100,25 @@ export interface _envoy_api_v2_Listener_ConnectionBalanceConfig_ExactBalance { * sacrifices accept throughput for accuracy and should be used when there are a small number of * connections that rarely cycle (e.g., service mesh gRPC egress). */ -export interface _envoy_api_v2_Listener_ConnectionBalanceConfig_ExactBalance__Output { +export interface _envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance__Output { +} + +/** + * Configuration for envoy internal listener. All the future internal listener features should be added here. + * [#not-implemented-hide:] + */ +export interface _envoy_config_listener_v3_Listener_InternalListenerConfig { +} + +/** + * Configuration for envoy internal listener. All the future internal listener features should be added here. + * [#not-implemented-hide:] + */ +export interface _envoy_config_listener_v3_Listener_InternalListenerConfig__Output { } /** - * [#next-free-field: 23] + * [#next-free-field: 30] */ export interface Listener { /** @@ -126,71 +132,61 @@ export interface Listener { * that is governed by the bind rules of the OS. E.g., multiple listeners can listen on port 0 on * Linux as the actual port will be allocated by the OS. */ - 'address'?: (_envoy_api_v2_core_Address); + 'address'?: (_envoy_config_core_v3_Address | null); /** * A list of filter chains to consider for this listener. The - * :ref:`FilterChain ` with the most specific - * :ref:`FilterChainMatch ` criteria is used on a + * :ref:`FilterChain ` with the most specific + * :ref:`FilterChainMatch ` criteria is used on a * connection. * * Example using SNI for filter chain selection can be found in the * :ref:`FAQ entry `. */ - 'filter_chains'?: (_envoy_api_v2_listener_FilterChain)[]; + 'filter_chains'?: (_envoy_config_listener_v3_FilterChain)[]; /** * If a connection is redirected using *iptables*, the port on which the proxy * receives it might be different from the original destination address. When this flag is set to * true, the listener hands off redirected connections to the listener associated with the * original destination address. If there is no listener associated with the original destination * address, the connection is handled by the listener that receives it. Defaults to false. - * - * .. attention:: - * - * This field is deprecated. Use :ref:`an original_dst ` - * :ref:`listener filter ` instead. - * - * Note that hand off to another listener is *NOT* performed without this flag. Once - * :ref:`FilterChainMatch ` is implemented this flag - * will be removed, as filter chain matching can be used to select a filter chain based on the - * restored destination address. */ - 'use_original_dst'?: (_google_protobuf_BoolValue); + 'use_original_dst'?: (_google_protobuf_BoolValue | null); /** * Soft limit on size of the listener’s new connection read and write buffers. * If unspecified, an implementation defined default is applied (1MiB). */ - 'per_connection_buffer_limit_bytes'?: (_google_protobuf_UInt32Value); + 'per_connection_buffer_limit_bytes'?: (_google_protobuf_UInt32Value | null); /** * Listener metadata. */ - 'metadata'?: (_envoy_api_v2_core_Metadata); + 'metadata'?: (_envoy_config_core_v3_Metadata | null); /** * [#not-implemented-hide:] */ - 'deprecated_v1'?: (_envoy_api_v2_Listener_DeprecatedV1); + 'deprecated_v1'?: (_envoy_config_listener_v3_Listener_DeprecatedV1 | null); /** * The type of draining to perform at a listener-wide level. */ - 'drain_type'?: (_envoy_api_v2_Listener_DrainType | keyof typeof _envoy_api_v2_Listener_DrainType); + 'drain_type'?: (_envoy_config_listener_v3_Listener_DrainType | keyof typeof _envoy_config_listener_v3_Listener_DrainType); /** * Listener filters have the opportunity to manipulate and augment the connection metadata that * is used in connection filter chain matching, for example. These filters are run before any in - * :ref:`filter_chains `. Order matters as the + * :ref:`filter_chains `. Order matters as the * filters are processed sequentially right after a socket has been accepted by the listener, and * before a connection is created. * UDP Listener filters can be specified when the protocol in the listener socket address in - * :ref:`protocol ` is :ref:`UDP - * `. + * :ref:`protocol ` is :ref:`UDP + * `. * UDP listeners currently support a single filter. */ - 'listener_filters'?: (_envoy_api_v2_listener_ListenerFilter)[]; + 'listener_filters'?: (_envoy_config_listener_v3_ListenerFilter)[]; /** * Whether the listener should be set as a transparent socket. * When this flag is set to true, connections can be redirected to the listener using an * *iptables* *TPROXY* target, in which case the original source and destination addresses and * ports are preserved on accepted connections. This flag should be used in combination with * :ref:`an original_dst ` :ref:`listener filter - * ` to mark the connections' local addresses as + * ` to mark the connections' local addresses as * "restored." This can be used to hand off each redirected connection to another listener * associated with the connection's destination address. Direct connections to the socket without * using *TPROXY* cannot be distinguished from connections redirected using *TPROXY* and are @@ -200,7 +196,7 @@ export interface Listener { * When this flag is not set (default), the socket is not modified, i.e. the transparent option * is neither set nor reset. */ - 'transparent'?: (_google_protobuf_BoolValue); + 'transparent'?: (_google_protobuf_BoolValue | null); /** * Whether the listener should set the *IP_FREEBIND* socket option. When this * flag is set to true, listeners can be bound to an IP address that is not @@ -209,7 +205,7 @@ export interface Listener { * (default), the socket is not modified, i.e. the option is neither enabled * nor disabled. */ - 'freebind'?: (_google_protobuf_BoolValue); + 'freebind'?: (_google_protobuf_BoolValue | null); /** * Whether the listener should accept TCP Fast Open (TFO) connections. * When this flag is set to a value greater than 0, the option TCP_FASTOPEN is enabled on @@ -226,23 +222,25 @@ export interface Listener { * On macOS, only values of 0, 1, and unset are valid; other values may result in an error. * To set the queue length on macOS, set the net.inet.tcp.fastopen_backlog kernel parameter. */ - 'tcp_fast_open_queue_length'?: (_google_protobuf_UInt32Value); + 'tcp_fast_open_queue_length'?: (_google_protobuf_UInt32Value | null); /** * Additional socket options that may not be present in Envoy source code or * precompiled binaries. */ - 'socket_options'?: (_envoy_api_v2_core_SocketOption)[]; + 'socket_options'?: (_envoy_config_core_v3_SocketOption)[]; /** * The timeout to wait for all listener filters to complete operation. If the timeout is reached, * the accepted socket is closed without a connection being created unless * `continue_on_listener_filters_timeout` is set to true. Specify 0 to disable the * timeout. If not specified, a default timeout of 15s is used. */ - 'listener_filters_timeout'?: (_google_protobuf_Duration); + 'listener_filters_timeout'?: (_google_protobuf_Duration | null); /** * Specifies the intended direction of the traffic relative to the local Envoy. + * This property is required on Windows for listeners using the original destination filter, + * see :ref:`Original Destination `. */ - 'traffic_direction'?: (_envoy_api_v2_core_TrafficDirection | keyof typeof _envoy_api_v2_core_TrafficDirection); + 'traffic_direction'?: (_envoy_config_core_v3_TrafficDirection | keyof typeof _envoy_config_core_v3_TrafficDirection); /** * Whether a connection should be created when listener filters timeout. Default is false. * @@ -255,17 +253,15 @@ export interface Listener { 'continue_on_listener_filters_timeout'?: (boolean); /** * If the protocol in the listener socket address in :ref:`protocol - * ` is :ref:`UDP - * `, this field specifies the actual udp - * listener to create, i.e. :ref:`udp_listener_name - * ` = "raw_udp_listener" for - * creating a packet-oriented UDP listener. If not present, treat it as "raw_udp_listener". + * ` is :ref:`UDP + * `, this field specifies UDP + * listener specific configuration. */ - 'udp_listener_config'?: (_envoy_api_v2_listener_UdpListenerConfig); + 'udp_listener_config'?: (_envoy_config_listener_v3_UdpListenerConfig | null); /** * Used to represent an 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. - * When this field is set, no other field except for :ref:`name` + * When this field is set, no other field except for :ref:`name` * should be set. * * .. note:: @@ -280,35 +276,102 @@ export interface Listener { * socket listener and the various types of API listener. That way, a given Listener message * can structurally only contain the fields of the relevant type.] */ - 'api_listener'?: (_envoy_config_listener_v2_ApiListener); + 'api_listener'?: (_envoy_config_listener_v3_ApiListener | null); /** * The listener's connection balancer configuration, currently only applicable to TCP listeners. * If no configuration is specified, Envoy will not attempt to balance active connections between * worker threads. + * + * In the scenario that the listener X redirects all the connections to the listeners Y1 and Y2 + * by setting :ref:`use_original_dst ` in X + * and :ref:`bind_to_port ` to false in Y1 and Y2, + * it is recommended to disable the balance config in listener X to avoid the cost of balancing, and + * enable the balance config in Y1 and Y2 to balance the connections among the workers. */ - 'connection_balance_config'?: (_envoy_api_v2_Listener_ConnectionBalanceConfig); + 'connection_balance_config'?: (_envoy_config_listener_v3_Listener_ConnectionBalanceConfig | null); /** - * When this flag is set to true, listeners set the *SO_REUSEPORT* socket option and - * create one socket for each worker thread. This makes inbound connections - * distribute among worker threads roughly evenly in cases where there are a high number - * of connections. When this flag is set to false, all worker threads share one socket. - * - * Before Linux v4.19-rc1, new TCP connections may be rejected during hot restart - * (see `3rd paragraph in 'soreuseport' commit message - * `_). - * This issue was fixed by `tcp: Avoid TCP syncookie rejected by SO_REUSEPORT socket - * `_. + * Deprecated. Use `enable_reuse_port` instead. */ 'reuse_port'?: (boolean); /** * Configuration for :ref:`access logs ` * emitted by this listener. */ - 'access_log'?: (_envoy_config_filter_accesslog_v2_AccessLog)[]; + 'access_log'?: (_envoy_config_accesslog_v3_AccessLog)[]; + /** + * The maximum length a tcp listener's pending connections queue can grow to. If no value is + * provided net.core.somaxconn will be used on Linux and 128 otherwise. + */ + 'tcp_backlog_size'?: (_google_protobuf_UInt32Value | null); + /** + * The default filter chain if none of the filter chain matches. If no default filter chain is supplied, + * the connection will be closed. The filter chain match is ignored in this field. + */ + 'default_filter_chain'?: (_envoy_config_listener_v3_FilterChain | null); + /** + * Whether the listener should bind to the port. A listener that doesn't + * bind can only receive connections redirected from other listeners that set + * :ref:`use_original_dst ` + * to true. Default is true. + */ + 'bind_to_port'?: (_google_protobuf_BoolValue | null); + /** + * Used to represent an internal listener which does not listen on OSI L4 address but can be used by the + * :ref:`envoy cluster ` to create a user space connection to. + * The internal listener acts as a tcp listener. It supports listener filters and network filter chains. + * The internal listener require :ref:`address ` has + * field `envoy_internal_address`. + * + * There are some limitations are derived from the implementation. The known limitations include + * + * * :ref:`ConnectionBalanceConfig ` is not + * allowed because both cluster connection and listener connection must be owned by the same dispatcher. + * * :ref:`tcp_backlog_size ` + * * :ref:`freebind ` + * * :ref:`transparent ` + * [#not-implemented-hide:] + */ + 'internal_listener'?: (_envoy_config_listener_v3_Listener_InternalListenerConfig | null); + /** + * Optional prefix to use on listener stats. If empty, the stats will be rooted at + * `listener.
.`. If non-empty, stats will be rooted at + * `listener..`. + */ + 'stat_prefix'?: (string); + /** + * When this flag is set to true, listeners set the *SO_REUSEPORT* socket option and + * create one socket for each worker thread. This makes inbound connections + * distribute among worker threads roughly evenly in cases where there are a high number + * of connections. When this flag is set to false, all worker threads share one socket. This field + * defaults to true. + * + * .. attention:: + * + * Although this field defaults to true, it has different behavior on different platforms. See + * the following text for more information. + * + * * On Linux, reuse_port is respected for both TCP and UDP listeners. It also works correctly + * with hot restart. + * * On macOS, reuse_port for TCP does not do what it does on Linux. Instead of load balancing, + * the last socket wins and receives all connections/packets. For TCP, reuse_port is force + * disabled and the user is warned. For UDP, it is enabled, but only one worker will receive + * packets. For QUIC/H3, SW routing will send packets to other workers. For "raw" UDP, only + * a single worker will currently receive packets. + * * On Windows, reuse_port for TCP has undefined behavior. It is force disabled and the user + * is warned similar to macOS. It is left enabled for UDP with undefined behavior currently. + */ + 'enable_reuse_port'?: (_google_protobuf_BoolValue | null); + /** + * The exclusive listener type and the corresponding config. + * TODO(lambdai): https://github.com/envoyproxy/envoy/issues/15372 + * Will create and add TcpListenerConfig. Will add UdpListenerConfig and ApiListener. + * [#not-implemented-hide:] + */ + 'listener_specifier'?: "internal_listener"; } /** - * [#next-free-field: 23] + * [#next-free-field: 30] */ export interface Listener__Output { /** @@ -322,71 +385,61 @@ export interface Listener__Output { * that is governed by the bind rules of the OS. E.g., multiple listeners can listen on port 0 on * Linux as the actual port will be allocated by the OS. */ - 'address'?: (_envoy_api_v2_core_Address__Output); + 'address': (_envoy_config_core_v3_Address__Output | null); /** * A list of filter chains to consider for this listener. The - * :ref:`FilterChain ` with the most specific - * :ref:`FilterChainMatch ` criteria is used on a + * :ref:`FilterChain ` with the most specific + * :ref:`FilterChainMatch ` criteria is used on a * connection. * * Example using SNI for filter chain selection can be found in the * :ref:`FAQ entry `. */ - 'filter_chains': (_envoy_api_v2_listener_FilterChain__Output)[]; + 'filter_chains': (_envoy_config_listener_v3_FilterChain__Output)[]; /** * If a connection is redirected using *iptables*, the port on which the proxy * receives it might be different from the original destination address. When this flag is set to * true, the listener hands off redirected connections to the listener associated with the * original destination address. If there is no listener associated with the original destination * address, the connection is handled by the listener that receives it. Defaults to false. - * - * .. attention:: - * - * This field is deprecated. Use :ref:`an original_dst ` - * :ref:`listener filter ` instead. - * - * Note that hand off to another listener is *NOT* performed without this flag. Once - * :ref:`FilterChainMatch ` is implemented this flag - * will be removed, as filter chain matching can be used to select a filter chain based on the - * restored destination address. */ - 'use_original_dst'?: (_google_protobuf_BoolValue__Output); + 'use_original_dst': (_google_protobuf_BoolValue__Output | null); /** * Soft limit on size of the listener’s new connection read and write buffers. * If unspecified, an implementation defined default is applied (1MiB). */ - 'per_connection_buffer_limit_bytes'?: (_google_protobuf_UInt32Value__Output); + 'per_connection_buffer_limit_bytes': (_google_protobuf_UInt32Value__Output | null); /** * Listener metadata. */ - 'metadata'?: (_envoy_api_v2_core_Metadata__Output); + 'metadata': (_envoy_config_core_v3_Metadata__Output | null); /** * [#not-implemented-hide:] */ - 'deprecated_v1'?: (_envoy_api_v2_Listener_DeprecatedV1__Output); + 'deprecated_v1': (_envoy_config_listener_v3_Listener_DeprecatedV1__Output | null); /** * The type of draining to perform at a listener-wide level. */ - 'drain_type': (keyof typeof _envoy_api_v2_Listener_DrainType); + 'drain_type': (keyof typeof _envoy_config_listener_v3_Listener_DrainType); /** * Listener filters have the opportunity to manipulate and augment the connection metadata that * is used in connection filter chain matching, for example. These filters are run before any in - * :ref:`filter_chains `. Order matters as the + * :ref:`filter_chains `. Order matters as the * filters are processed sequentially right after a socket has been accepted by the listener, and * before a connection is created. * UDP Listener filters can be specified when the protocol in the listener socket address in - * :ref:`protocol ` is :ref:`UDP - * `. + * :ref:`protocol ` is :ref:`UDP + * `. * UDP listeners currently support a single filter. */ - 'listener_filters': (_envoy_api_v2_listener_ListenerFilter__Output)[]; + 'listener_filters': (_envoy_config_listener_v3_ListenerFilter__Output)[]; /** * Whether the listener should be set as a transparent socket. * When this flag is set to true, connections can be redirected to the listener using an * *iptables* *TPROXY* target, in which case the original source and destination addresses and * ports are preserved on accepted connections. This flag should be used in combination with * :ref:`an original_dst ` :ref:`listener filter - * ` to mark the connections' local addresses as + * ` to mark the connections' local addresses as * "restored." This can be used to hand off each redirected connection to another listener * associated with the connection's destination address. Direct connections to the socket without * using *TPROXY* cannot be distinguished from connections redirected using *TPROXY* and are @@ -396,7 +449,7 @@ export interface Listener__Output { * When this flag is not set (default), the socket is not modified, i.e. the transparent option * is neither set nor reset. */ - 'transparent'?: (_google_protobuf_BoolValue__Output); + 'transparent': (_google_protobuf_BoolValue__Output | null); /** * Whether the listener should set the *IP_FREEBIND* socket option. When this * flag is set to true, listeners can be bound to an IP address that is not @@ -405,7 +458,7 @@ export interface Listener__Output { * (default), the socket is not modified, i.e. the option is neither enabled * nor disabled. */ - 'freebind'?: (_google_protobuf_BoolValue__Output); + 'freebind': (_google_protobuf_BoolValue__Output | null); /** * Whether the listener should accept TCP Fast Open (TFO) connections. * When this flag is set to a value greater than 0, the option TCP_FASTOPEN is enabled on @@ -422,23 +475,25 @@ export interface Listener__Output { * On macOS, only values of 0, 1, and unset are valid; other values may result in an error. * To set the queue length on macOS, set the net.inet.tcp.fastopen_backlog kernel parameter. */ - 'tcp_fast_open_queue_length'?: (_google_protobuf_UInt32Value__Output); + 'tcp_fast_open_queue_length': (_google_protobuf_UInt32Value__Output | null); /** * Additional socket options that may not be present in Envoy source code or * precompiled binaries. */ - 'socket_options': (_envoy_api_v2_core_SocketOption__Output)[]; + 'socket_options': (_envoy_config_core_v3_SocketOption__Output)[]; /** * The timeout to wait for all listener filters to complete operation. If the timeout is reached, * the accepted socket is closed without a connection being created unless * `continue_on_listener_filters_timeout` is set to true. Specify 0 to disable the * timeout. If not specified, a default timeout of 15s is used. */ - 'listener_filters_timeout'?: (_google_protobuf_Duration__Output); + 'listener_filters_timeout': (_google_protobuf_Duration__Output | null); /** * Specifies the intended direction of the traffic relative to the local Envoy. + * This property is required on Windows for listeners using the original destination filter, + * see :ref:`Original Destination `. */ - 'traffic_direction': (keyof typeof _envoy_api_v2_core_TrafficDirection); + 'traffic_direction': (keyof typeof _envoy_config_core_v3_TrafficDirection); /** * Whether a connection should be created when listener filters timeout. Default is false. * @@ -451,17 +506,15 @@ export interface Listener__Output { 'continue_on_listener_filters_timeout': (boolean); /** * If the protocol in the listener socket address in :ref:`protocol - * ` is :ref:`UDP - * `, this field specifies the actual udp - * listener to create, i.e. :ref:`udp_listener_name - * ` = "raw_udp_listener" for - * creating a packet-oriented UDP listener. If not present, treat it as "raw_udp_listener". + * ` is :ref:`UDP + * `, this field specifies UDP + * listener specific configuration. */ - 'udp_listener_config'?: (_envoy_api_v2_listener_UdpListenerConfig__Output); + 'udp_listener_config': (_envoy_config_listener_v3_UdpListenerConfig__Output | null); /** * Used to represent an 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. - * When this field is set, no other field except for :ref:`name` + * When this field is set, no other field except for :ref:`name` * should be set. * * .. note:: @@ -476,29 +529,96 @@ export interface Listener__Output { * socket listener and the various types of API listener. That way, a given Listener message * can structurally only contain the fields of the relevant type.] */ - 'api_listener'?: (_envoy_config_listener_v2_ApiListener__Output); + 'api_listener': (_envoy_config_listener_v3_ApiListener__Output | null); /** * The listener's connection balancer configuration, currently only applicable to TCP listeners. * If no configuration is specified, Envoy will not attempt to balance active connections between * worker threads. + * + * In the scenario that the listener X redirects all the connections to the listeners Y1 and Y2 + * by setting :ref:`use_original_dst ` in X + * and :ref:`bind_to_port ` to false in Y1 and Y2, + * it is recommended to disable the balance config in listener X to avoid the cost of balancing, and + * enable the balance config in Y1 and Y2 to balance the connections among the workers. */ - 'connection_balance_config'?: (_envoy_api_v2_Listener_ConnectionBalanceConfig__Output); + 'connection_balance_config': (_envoy_config_listener_v3_Listener_ConnectionBalanceConfig__Output | null); /** - * When this flag is set to true, listeners set the *SO_REUSEPORT* socket option and - * create one socket for each worker thread. This makes inbound connections - * distribute among worker threads roughly evenly in cases where there are a high number - * of connections. When this flag is set to false, all worker threads share one socket. - * - * Before Linux v4.19-rc1, new TCP connections may be rejected during hot restart - * (see `3rd paragraph in 'soreuseport' commit message - * `_). - * This issue was fixed by `tcp: Avoid TCP syncookie rejected by SO_REUSEPORT socket - * `_. + * Deprecated. Use `enable_reuse_port` instead. */ 'reuse_port': (boolean); /** * Configuration for :ref:`access logs ` * emitted by this listener. */ - 'access_log': (_envoy_config_filter_accesslog_v2_AccessLog__Output)[]; + 'access_log': (_envoy_config_accesslog_v3_AccessLog__Output)[]; + /** + * The maximum length a tcp listener's pending connections queue can grow to. If no value is + * provided net.core.somaxconn will be used on Linux and 128 otherwise. + */ + 'tcp_backlog_size': (_google_protobuf_UInt32Value__Output | null); + /** + * The default filter chain if none of the filter chain matches. If no default filter chain is supplied, + * the connection will be closed. The filter chain match is ignored in this field. + */ + 'default_filter_chain': (_envoy_config_listener_v3_FilterChain__Output | null); + /** + * Whether the listener should bind to the port. A listener that doesn't + * bind can only receive connections redirected from other listeners that set + * :ref:`use_original_dst ` + * to true. Default is true. + */ + 'bind_to_port': (_google_protobuf_BoolValue__Output | null); + /** + * Used to represent an internal listener which does not listen on OSI L4 address but can be used by the + * :ref:`envoy cluster ` to create a user space connection to. + * The internal listener acts as a tcp listener. It supports listener filters and network filter chains. + * The internal listener require :ref:`address ` has + * field `envoy_internal_address`. + * + * There are some limitations are derived from the implementation. The known limitations include + * + * * :ref:`ConnectionBalanceConfig ` is not + * allowed because both cluster connection and listener connection must be owned by the same dispatcher. + * * :ref:`tcp_backlog_size ` + * * :ref:`freebind ` + * * :ref:`transparent ` + * [#not-implemented-hide:] + */ + 'internal_listener'?: (_envoy_config_listener_v3_Listener_InternalListenerConfig__Output | null); + /** + * Optional prefix to use on listener stats. If empty, the stats will be rooted at + * `listener.
.`. If non-empty, stats will be rooted at + * `listener..`. + */ + 'stat_prefix': (string); + /** + * When this flag is set to true, listeners set the *SO_REUSEPORT* socket option and + * create one socket for each worker thread. This makes inbound connections + * distribute among worker threads roughly evenly in cases where there are a high number + * of connections. When this flag is set to false, all worker threads share one socket. This field + * defaults to true. + * + * .. attention:: + * + * Although this field defaults to true, it has different behavior on different platforms. See + * the following text for more information. + * + * * On Linux, reuse_port is respected for both TCP and UDP listeners. It also works correctly + * with hot restart. + * * On macOS, reuse_port for TCP does not do what it does on Linux. Instead of load balancing, + * the last socket wins and receives all connections/packets. For TCP, reuse_port is force + * disabled and the user is warned. For UDP, it is enabled, but only one worker will receive + * packets. For QUIC/H3, SW routing will send packets to other workers. For "raw" UDP, only + * a single worker will currently receive packets. + * * On Windows, reuse_port for TCP has undefined behavior. It is force disabled and the user + * is warned similar to macOS. It is left enabled for UDP with undefined behavior currently. + */ + 'enable_reuse_port': (_google_protobuf_BoolValue__Output | null); + /** + * The exclusive listener type and the corresponding config. + * TODO(lambdai): https://github.com/envoyproxy/envoy/issues/15372 + * Will create and add TcpListenerConfig. Will add UdpListenerConfig and ApiListener. + * [#not-implemented-hide:] + */ + 'listener_specifier': "internal_listener"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerCollection.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerCollection.ts new file mode 100644 index 000000000..590ca8ed3 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerCollection.ts @@ -0,0 +1,19 @@ +// Original file: deps/envoy-api/envoy/config/listener/v3/listener.proto + +import type { CollectionEntry as _xds_core_v3_CollectionEntry, CollectionEntry__Output as _xds_core_v3_CollectionEntry__Output } from '../../../../xds/core/v3/CollectionEntry'; + +/** + * Listener list collections. Entries are *Listener* resources or references. + * [#not-implemented-hide:] + */ +export interface ListenerCollection { + 'entries'?: (_xds_core_v3_CollectionEntry)[]; +} + +/** + * Listener list collections. Entries are *Listener* resources or references. + * [#not-implemented-hide:] + */ +export interface ListenerCollection__Output { + 'entries': (_xds_core_v3_CollectionEntry__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerFilter.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerFilter.ts new file mode 100644 index 000000000..be7242849 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerFilter.ts @@ -0,0 +1,46 @@ +// Original file: deps/envoy-api/envoy/config/listener/v3/listener_components.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { ListenerFilterChainMatchPredicate as _envoy_config_listener_v3_ListenerFilterChainMatchPredicate, ListenerFilterChainMatchPredicate__Output as _envoy_config_listener_v3_ListenerFilterChainMatchPredicate__Output } from '../../../../envoy/config/listener/v3/ListenerFilterChainMatchPredicate'; + +export interface ListenerFilter { + /** + * The name of the filter to instantiate. The name must match a + * :ref:`supported filter `. + */ + 'name'?: (string); + /** + * Filter specific configuration which depends on the filter being + * instantiated. See the supported filters for further documentation. + * [#extension-category: envoy.filters.listener,envoy.filters.udp_listener] + */ + 'typed_config'?: (_google_protobuf_Any | null); + /** + * Optional match predicate used to disable the filter. The filter is enabled when this field is empty. + * See :ref:`ListenerFilterChainMatchPredicate ` + * for further examples. + */ + 'filter_disabled'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate | null); + 'config_type'?: "typed_config"; +} + +export interface ListenerFilter__Output { + /** + * The name of the filter to instantiate. The name must match a + * :ref:`supported filter `. + */ + 'name': (string); + /** + * Filter specific configuration which depends on the filter being + * instantiated. See the supported filters for further documentation. + * [#extension-category: envoy.filters.listener,envoy.filters.udp_listener] + */ + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * Optional match predicate used to disable the filter. The filter is enabled when this field is empty. + * See :ref:`ListenerFilterChainMatchPredicate ` + * for further examples. + */ + 'filter_disabled': (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate__Output | null); + 'config_type': "typed_config"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ListenerFilterChainMatchPredicate.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerFilterChainMatchPredicate.ts similarity index 65% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ListenerFilterChainMatchPredicate.ts rename to packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerFilterChainMatchPredicate.ts index ac3ddfd2a..bb743a29d 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/listener/ListenerFilterChainMatchPredicate.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/ListenerFilterChainMatchPredicate.ts @@ -1,26 +1,26 @@ -// Original file: deps/envoy-api/envoy/api/v2/listener/listener_components.proto +// Original file: deps/envoy-api/envoy/config/listener/v3/listener_components.proto -import type { ListenerFilterChainMatchPredicate as _envoy_api_v2_listener_ListenerFilterChainMatchPredicate, ListenerFilterChainMatchPredicate__Output as _envoy_api_v2_listener_ListenerFilterChainMatchPredicate__Output } from '../../../../envoy/api/v2/listener/ListenerFilterChainMatchPredicate'; -import type { Int32Range as _envoy_type_Int32Range, Int32Range__Output as _envoy_type_Int32Range__Output } from '../../../../envoy/type/Int32Range'; +import type { ListenerFilterChainMatchPredicate as _envoy_config_listener_v3_ListenerFilterChainMatchPredicate, ListenerFilterChainMatchPredicate__Output as _envoy_config_listener_v3_ListenerFilterChainMatchPredicate__Output } from '../../../../envoy/config/listener/v3/ListenerFilterChainMatchPredicate'; +import type { Int32Range as _envoy_type_v3_Int32Range, Int32Range__Output as _envoy_type_v3_Int32Range__Output } from '../../../../envoy/type/v3/Int32Range'; /** * A set of match configurations used for logical operations. */ -export interface _envoy_api_v2_listener_ListenerFilterChainMatchPredicate_MatchSet { +export interface _envoy_config_listener_v3_ListenerFilterChainMatchPredicate_MatchSet { /** * The list of rules that make up the set. */ - 'rules'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate)[]; + 'rules'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate)[]; } /** * A set of match configurations used for logical operations. */ -export interface _envoy_api_v2_listener_ListenerFilterChainMatchPredicate_MatchSet__Output { +export interface _envoy_config_listener_v3_ListenerFilterChainMatchPredicate_MatchSet__Output { /** * The list of rules that make up the set. */ - 'rules': (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate__Output)[]; + 'rules': (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate__Output)[]; } /** @@ -45,7 +45,7 @@ export interface _envoy_api_v2_listener_ListenerFilterChainMatchPredicate_MatchS * rules: * - destination_port_range: * start: 3306 - * end: 3306 + * end: 3307 * - destination_port_range: * start: 15000 * end: 15001 @@ -57,16 +57,16 @@ export interface ListenerFilterChainMatchPredicate { * A set that describes a logical OR. If any member of the set matches, the match configuration * matches. */ - 'or_match'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate_MatchSet); + 'or_match'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate_MatchSet | null); /** * A set that describes a logical AND. If all members of the set match, the match configuration * matches. */ - 'and_match'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate_MatchSet); + 'and_match'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate_MatchSet | null); /** * A negation match. The match configuration will match if the negated match condition matches. */ - 'not_match'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate); + 'not_match'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate | null); /** * The match configuration will always match. */ @@ -75,7 +75,7 @@ export interface ListenerFilterChainMatchPredicate { * Match destination port. Particularly, the match evaluation must use the recovered local port if * the owning listener filter is after :ref:`an original_dst listener filter `. */ - 'destination_port_range'?: (_envoy_type_Int32Range); + 'destination_port_range'?: (_envoy_type_v3_Int32Range | null); 'rule'?: "or_match"|"and_match"|"not_match"|"any_match"|"destination_port_range"; } @@ -101,7 +101,7 @@ export interface ListenerFilterChainMatchPredicate { * rules: * - destination_port_range: * start: 3306 - * end: 3306 + * end: 3307 * - destination_port_range: * start: 15000 * end: 15001 @@ -113,16 +113,16 @@ export interface ListenerFilterChainMatchPredicate__Output { * A set that describes a logical OR. If any member of the set matches, the match configuration * matches. */ - 'or_match'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate_MatchSet__Output); + 'or_match'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate_MatchSet__Output | null); /** * A set that describes a logical AND. If all members of the set match, the match configuration * matches. */ - 'and_match'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate_MatchSet__Output); + 'and_match'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate_MatchSet__Output | null); /** * A negation match. The match configuration will match if the negated match condition matches. */ - 'not_match'?: (_envoy_api_v2_listener_ListenerFilterChainMatchPredicate__Output); + 'not_match'?: (_envoy_config_listener_v3_ListenerFilterChainMatchPredicate__Output | null); /** * The match configuration will always match. */ @@ -131,6 +131,6 @@ export interface ListenerFilterChainMatchPredicate__Output { * Match destination port. Particularly, the match evaluation must use the recovered local port if * the owning listener filter is after :ref:`an original_dst listener filter `. */ - 'destination_port_range'?: (_envoy_type_Int32Range__Output); + 'destination_port_range'?: (_envoy_type_v3_Int32Range__Output | null); 'rule': "or_match"|"and_match"|"not_match"|"any_match"|"destination_port_range"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/QuicProtocolOptions.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/QuicProtocolOptions.ts new file mode 100644 index 000000000..5e01a772f --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/QuicProtocolOptions.ts @@ -0,0 +1,97 @@ +// Original file: deps/envoy-api/envoy/config/listener/v3/quic_config.proto + +import type { QuicProtocolOptions as _envoy_config_core_v3_QuicProtocolOptions, QuicProtocolOptions__Output as _envoy_config_core_v3_QuicProtocolOptions__Output } from '../../../../envoy/config/core/v3/QuicProtocolOptions'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { RuntimeFeatureFlag as _envoy_config_core_v3_RuntimeFeatureFlag, RuntimeFeatureFlag__Output as _envoy_config_core_v3_RuntimeFeatureFlag__Output } from '../../../../envoy/config/core/v3/RuntimeFeatureFlag'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +/** + * Configuration specific to the UDP QUIC listener. + * [#next-free-field: 8] + */ +export interface QuicProtocolOptions { + 'quic_protocol_options'?: (_envoy_config_core_v3_QuicProtocolOptions | null); + /** + * Maximum number of milliseconds that connection will be alive when there is + * no network activity. 300000ms if not specified. + */ + 'idle_timeout'?: (_google_protobuf_Duration | null); + /** + * Connection timeout in milliseconds before the crypto handshake is finished. + * 20000ms if not specified. + */ + 'crypto_handshake_timeout'?: (_google_protobuf_Duration | null); + /** + * Runtime flag that controls whether the listener is enabled or not. If not specified, defaults + * to enabled. + */ + 'enabled'?: (_envoy_config_core_v3_RuntimeFeatureFlag | null); + /** + * A multiplier to number of connections which is used to determine how many packets to read per + * event loop. A reasonable number should allow the listener to process enough payload but not + * starve TCP and other UDP sockets and also prevent long event loop duration. + * The default value is 32. This means if there are N QUIC connections, the total number of + * packets to read in each read event will be 32 * N. + * The actual number of packets to read in total by the UDP listener is also + * bound by 6000, regardless of this field or how many connections there are. + */ + 'packets_to_read_to_connection_count_ratio'?: (_google_protobuf_UInt32Value | null); + /** + * Configure which implementation of `quic::QuicCryptoClientStreamBase` to be used for this listener. + * If not specified the :ref:`QUICHE default one configured by ` will be used. + * [#extension-category: envoy.quic.server.crypto_stream] + */ + 'crypto_stream_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + /** + * Configure which implementation of `quic::ProofSource` to be used for this listener. + * If not specified the :ref:`default one configured by ` will be used. + * [#extension-category: envoy.quic.proof_source] + */ + 'proof_source_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); +} + +/** + * Configuration specific to the UDP QUIC listener. + * [#next-free-field: 8] + */ +export interface QuicProtocolOptions__Output { + 'quic_protocol_options': (_envoy_config_core_v3_QuicProtocolOptions__Output | null); + /** + * Maximum number of milliseconds that connection will be alive when there is + * no network activity. 300000ms if not specified. + */ + 'idle_timeout': (_google_protobuf_Duration__Output | null); + /** + * Connection timeout in milliseconds before the crypto handshake is finished. + * 20000ms if not specified. + */ + 'crypto_handshake_timeout': (_google_protobuf_Duration__Output | null); + /** + * Runtime flag that controls whether the listener is enabled or not. If not specified, defaults + * to enabled. + */ + 'enabled': (_envoy_config_core_v3_RuntimeFeatureFlag__Output | null); + /** + * A multiplier to number of connections which is used to determine how many packets to read per + * event loop. A reasonable number should allow the listener to process enough payload but not + * starve TCP and other UDP sockets and also prevent long event loop duration. + * The default value is 32. This means if there are N QUIC connections, the total number of + * packets to read in each read event will be 32 * N. + * The actual number of packets to read in total by the UDP listener is also + * bound by 6000, regardless of this field or how many connections there are. + */ + 'packets_to_read_to_connection_count_ratio': (_google_protobuf_UInt32Value__Output | null); + /** + * Configure which implementation of `quic::QuicCryptoClientStreamBase` to be used for this listener. + * If not specified the :ref:`QUICHE default one configured by ` will be used. + * [#extension-category: envoy.quic.server.crypto_stream] + */ + 'crypto_stream_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + /** + * Configure which implementation of `quic::ProofSource` to be used for this listener. + * If not specified the :ref:`default one configured by ` will be used. + * [#extension-category: envoy.quic.proof_source] + */ + 'proof_source_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/UdpListenerConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/UdpListenerConfig.ts new file mode 100644 index 000000000..f4c220e20 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/listener/v3/UdpListenerConfig.ts @@ -0,0 +1,48 @@ +// Original file: deps/envoy-api/envoy/config/listener/v3/udp_listener_config.proto + +import type { UdpSocketConfig as _envoy_config_core_v3_UdpSocketConfig, UdpSocketConfig__Output as _envoy_config_core_v3_UdpSocketConfig__Output } from '../../../../envoy/config/core/v3/UdpSocketConfig'; +import type { QuicProtocolOptions as _envoy_config_listener_v3_QuicProtocolOptions, QuicProtocolOptions__Output as _envoy_config_listener_v3_QuicProtocolOptions__Output } from '../../../../envoy/config/listener/v3/QuicProtocolOptions'; + +/** + * [#next-free-field: 8] + */ +export interface UdpListenerConfig { + /** + * UDP socket configuration for the listener. The default for + * :ref:`prefer_gro ` is false for + * listener sockets. If receiving a large amount of datagrams from a small number of sources, it + * may be worthwhile to enable this option after performance testing. + */ + 'downstream_socket_config'?: (_envoy_config_core_v3_UdpSocketConfig | null); + /** + * Configuration for QUIC protocol. If empty, QUIC will not be enabled on this listener. Set + * to the default object to enable QUIC without modifying any additional options. + * + * .. warning:: + * QUIC support is currently alpha and should be used with caution. Please + * see :ref:`here ` for details. + */ + 'quic_options'?: (_envoy_config_listener_v3_QuicProtocolOptions | null); +} + +/** + * [#next-free-field: 8] + */ +export interface UdpListenerConfig__Output { + /** + * UDP socket configuration for the listener. The default for + * :ref:`prefer_gro ` is false for + * listener sockets. If receiving a large amount of datagrams from a small number of sources, it + * may be worthwhile to enable this option after performance testing. + */ + 'downstream_socket_config': (_envoy_config_core_v3_UdpSocketConfig__Output | null); + /** + * Configuration for QUIC protocol. If empty, QUIC will not be enabled on this listener. Set + * to the default object to enable QUIC without modifying any additional options. + * + * .. warning:: + * QUIC support is currently alpha and should be used with caution. Please + * see :ref:`here ` for details. + */ + 'quic_options': (_envoy_config_listener_v3_QuicProtocolOptions__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/DogStatsdSink.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/DogStatsdSink.ts new file mode 100644 index 000000000..4cf705f10 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/DogStatsdSink.ts @@ -0,0 +1,65 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; +import type { UInt64Value as _google_protobuf_UInt64Value, UInt64Value__Output as _google_protobuf_UInt64Value__Output } from '../../../../google/protobuf/UInt64Value'; +import type { Long } from '@grpc/proto-loader'; + +/** + * Stats configuration proto schema for built-in *envoy.stat_sinks.dog_statsd* sink. + * The sink emits stats with `DogStatsD `_ + * compatible tags. Tags are configurable via :ref:`StatsConfig + * `. + * [#extension: envoy.stat_sinks.dog_statsd] + */ +export interface DogStatsdSink { + /** + * The UDP address of a running DogStatsD compliant listener. If specified, + * statistics will be flushed to this address. + */ + 'address'?: (_envoy_config_core_v3_Address | null); + /** + * Optional custom metric name prefix. See :ref:`StatsdSink's prefix field + * ` for more details. + */ + 'prefix'?: (string); + /** + * Optional max datagram size to use when sending UDP messages. By default Envoy + * will emit one metric per datagram. By specifying a max-size larger than a single + * metric, Envoy will emit multiple, new-line separated metrics. The max datagram + * size should not exceed your network's MTU. + * + * Note that this value may not be respected if smaller than a single metric. + */ + 'max_bytes_per_datagram'?: (_google_protobuf_UInt64Value | null); + 'dog_statsd_specifier'?: "address"; +} + +/** + * Stats configuration proto schema for built-in *envoy.stat_sinks.dog_statsd* sink. + * The sink emits stats with `DogStatsD `_ + * compatible tags. Tags are configurable via :ref:`StatsConfig + * `. + * [#extension: envoy.stat_sinks.dog_statsd] + */ +export interface DogStatsdSink__Output { + /** + * The UDP address of a running DogStatsD compliant listener. If specified, + * statistics will be flushed to this address. + */ + 'address'?: (_envoy_config_core_v3_Address__Output | null); + /** + * Optional custom metric name prefix. See :ref:`StatsdSink's prefix field + * ` for more details. + */ + 'prefix': (string); + /** + * Optional max datagram size to use when sending UDP messages. By default Envoy + * will emit one metric per datagram. By specifying a max-size larger than a single + * metric, Envoy will emit multiple, new-line separated metrics. The max datagram + * size should not exceed your network's MTU. + * + * Note that this value may not be respected if smaller than a single metric. + */ + 'max_bytes_per_datagram': (_google_protobuf_UInt64Value__Output | null); + 'dog_statsd_specifier': "address"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/HistogramBucketSettings.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/HistogramBucketSettings.ts new file mode 100644 index 000000000..036958a49 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/HistogramBucketSettings.ts @@ -0,0 +1,35 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; + +/** + * Specifies a matcher for stats and the buckets that matching stats should use. + */ +export interface HistogramBucketSettings { + /** + * The stats that this rule applies to. The match is applied to the original stat name + * before tag-extraction, for example `cluster.exampleclustername.upstream_cx_length_ms`. + */ + 'match'?: (_envoy_type_matcher_v3_StringMatcher | null); + /** + * Each value is the upper bound of a bucket. Each bucket must be greater than 0 and unique. + * The order of the buckets does not matter. + */ + 'buckets'?: (number | string)[]; +} + +/** + * Specifies a matcher for stats and the buckets that matching stats should use. + */ +export interface HistogramBucketSettings__Output { + /** + * The stats that this rule applies to. The match is applied to the original stat name + * before tag-extraction, for example `cluster.exampleclustername.upstream_cx_length_ms`. + */ + 'match': (_envoy_type_matcher_v3_StringMatcher__Output | null); + /** + * Each value is the upper bound of a bucket. Each bucket must be greater than 0 and unique. + * The order of the buckets does not matter. + */ + 'buckets': (number)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/HystrixSink.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/HystrixSink.ts new file mode 100644 index 000000000..b8fb2ed8e --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/HystrixSink.ts @@ -0,0 +1,61 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + +import type { Long } from '@grpc/proto-loader'; + +/** + * Stats configuration proto schema for built-in *envoy.stat_sinks.hystrix* sink. + * The sink emits stats in `text/event-stream + * `_ + * formatted stream for use by `Hystrix dashboard + * `_. + * + * Note that only a single HystrixSink should be configured. + * + * Streaming is started through an admin endpoint :http:get:`/hystrix_event_stream`. + * [#extension: envoy.stat_sinks.hystrix] + */ +export interface HystrixSink { + /** + * The number of buckets the rolling statistical window is divided into. + * + * Each time the sink is flushed, all relevant Envoy statistics are sampled and + * added to the rolling window (removing the oldest samples in the window + * in the process). The sink then outputs the aggregate statistics across the + * current rolling window to the event stream(s). + * + * rolling_window(ms) = stats_flush_interval(ms) * num_of_buckets + * + * More detailed explanation can be found in `Hystrix wiki + * `_. + */ + 'num_buckets'?: (number | string | Long); +} + +/** + * Stats configuration proto schema for built-in *envoy.stat_sinks.hystrix* sink. + * The sink emits stats in `text/event-stream + * `_ + * formatted stream for use by `Hystrix dashboard + * `_. + * + * Note that only a single HystrixSink should be configured. + * + * Streaming is started through an admin endpoint :http:get:`/hystrix_event_stream`. + * [#extension: envoy.stat_sinks.hystrix] + */ +export interface HystrixSink__Output { + /** + * The number of buckets the rolling statistical window is divided into. + * + * Each time the sink is flushed, all relevant Envoy statistics are sampled and + * added to the rolling window (removing the oldest samples in the window + * in the process). The sink then outputs the aggregate statistics across the + * current rolling window to the event stream(s). + * + * rolling_window(ms) = stats_flush_interval(ms) * num_of_buckets + * + * More detailed explanation can be found in `Hystrix wiki + * `_. + */ + 'num_buckets': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsConfig.ts new file mode 100644 index 000000000..df5d7c7e4 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsConfig.ts @@ -0,0 +1,148 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + +import type { TagSpecifier as _envoy_config_metrics_v3_TagSpecifier, TagSpecifier__Output as _envoy_config_metrics_v3_TagSpecifier__Output } from '../../../../envoy/config/metrics/v3/TagSpecifier'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { StatsMatcher as _envoy_config_metrics_v3_StatsMatcher, StatsMatcher__Output as _envoy_config_metrics_v3_StatsMatcher__Output } from '../../../../envoy/config/metrics/v3/StatsMatcher'; +import type { HistogramBucketSettings as _envoy_config_metrics_v3_HistogramBucketSettings, HistogramBucketSettings__Output as _envoy_config_metrics_v3_HistogramBucketSettings__Output } from '../../../../envoy/config/metrics/v3/HistogramBucketSettings'; + +/** + * Statistics configuration such as tagging. + */ +export interface StatsConfig { + /** + * Each stat name is iteratively processed through these tag specifiers. + * When a tag is matched, the first capture group is removed from the name so + * later :ref:`TagSpecifiers ` cannot match that + * same portion of the match. + */ + 'stats_tags'?: (_envoy_config_metrics_v3_TagSpecifier)[]; + /** + * Use all default tag regexes specified in Envoy. These can be combined with + * custom tags specified in :ref:`stats_tags + * `. They will be processed before + * the custom tags. + * + * .. note:: + * + * If any default tags are specified twice, the config will be considered + * invalid. + * + * See :repo:`well_known_names.h ` for a list of the + * default tags in Envoy. + * + * If not provided, the value is assumed to be true. + */ + 'use_all_default_tags'?: (_google_protobuf_BoolValue | null); + /** + * Inclusion/exclusion matcher for stat name creation. If not provided, all stats are instantiated + * as normal. Preventing the instantiation of certain families of stats can improve memory + * performance for Envoys running especially large configs. + * + * .. warning:: + * Excluding stats may affect Envoy's behavior in undocumented ways. See + * `issue #8771 `_ for more information. + * If any unexpected behavior changes are observed, please open a new issue immediately. + */ + 'stats_matcher'?: (_envoy_config_metrics_v3_StatsMatcher | null); + /** + * Defines rules for setting the histogram buckets. Rules are evaluated in order, and the first + * match is applied. If no match is found (or if no rules are set), the following default buckets + * are used: + * + * .. code-block:: json + * + * [ + * 0.5, + * 1, + * 5, + * 10, + * 25, + * 50, + * 100, + * 250, + * 500, + * 1000, + * 2500, + * 5000, + * 10000, + * 30000, + * 60000, + * 300000, + * 600000, + * 1800000, + * 3600000 + * ] + */ + 'histogram_bucket_settings'?: (_envoy_config_metrics_v3_HistogramBucketSettings)[]; +} + +/** + * Statistics configuration such as tagging. + */ +export interface StatsConfig__Output { + /** + * Each stat name is iteratively processed through these tag specifiers. + * When a tag is matched, the first capture group is removed from the name so + * later :ref:`TagSpecifiers ` cannot match that + * same portion of the match. + */ + 'stats_tags': (_envoy_config_metrics_v3_TagSpecifier__Output)[]; + /** + * Use all default tag regexes specified in Envoy. These can be combined with + * custom tags specified in :ref:`stats_tags + * `. They will be processed before + * the custom tags. + * + * .. note:: + * + * If any default tags are specified twice, the config will be considered + * invalid. + * + * See :repo:`well_known_names.h ` for a list of the + * default tags in Envoy. + * + * If not provided, the value is assumed to be true. + */ + 'use_all_default_tags': (_google_protobuf_BoolValue__Output | null); + /** + * Inclusion/exclusion matcher for stat name creation. If not provided, all stats are instantiated + * as normal. Preventing the instantiation of certain families of stats can improve memory + * performance for Envoys running especially large configs. + * + * .. warning:: + * Excluding stats may affect Envoy's behavior in undocumented ways. See + * `issue #8771 `_ for more information. + * If any unexpected behavior changes are observed, please open a new issue immediately. + */ + 'stats_matcher': (_envoy_config_metrics_v3_StatsMatcher__Output | null); + /** + * Defines rules for setting the histogram buckets. Rules are evaluated in order, and the first + * match is applied. If no match is found (or if no rules are set), the following default buckets + * are used: + * + * .. code-block:: json + * + * [ + * 0.5, + * 1, + * 5, + * 10, + * 25, + * 50, + * 100, + * 250, + * 500, + * 1000, + * 2500, + * 5000, + * 10000, + * 30000, + * 60000, + * 300000, + * 600000, + * 1800000, + * 3600000 + * ] + */ + 'histogram_bucket_settings': (_envoy_config_metrics_v3_HistogramBucketSettings__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsMatcher.ts new file mode 100644 index 000000000..9df9e9529 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsMatcher.ts @@ -0,0 +1,47 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + +import type { ListStringMatcher as _envoy_type_matcher_v3_ListStringMatcher, ListStringMatcher__Output as _envoy_type_matcher_v3_ListStringMatcher__Output } from '../../../../envoy/type/matcher/v3/ListStringMatcher'; + +/** + * Configuration for disabling stat instantiation. + */ +export interface StatsMatcher { + /** + * If `reject_all` is true, then all stats are disabled. If `reject_all` is false, then all + * stats are enabled. + */ + 'reject_all'?: (boolean); + /** + * Exclusive match. All stats are enabled except for those matching one of the supplied + * StringMatcher protos. + */ + 'exclusion_list'?: (_envoy_type_matcher_v3_ListStringMatcher | null); + /** + * Inclusive match. No stats are enabled except for those matching one of the supplied + * StringMatcher protos. + */ + 'inclusion_list'?: (_envoy_type_matcher_v3_ListStringMatcher | null); + 'stats_matcher'?: "reject_all"|"exclusion_list"|"inclusion_list"; +} + +/** + * Configuration for disabling stat instantiation. + */ +export interface StatsMatcher__Output { + /** + * If `reject_all` is true, then all stats are disabled. If `reject_all` is false, then all + * stats are enabled. + */ + 'reject_all'?: (boolean); + /** + * Exclusive match. All stats are enabled except for those matching one of the supplied + * StringMatcher protos. + */ + 'exclusion_list'?: (_envoy_type_matcher_v3_ListStringMatcher__Output | null); + /** + * Inclusive match. No stats are enabled except for those matching one of the supplied + * StringMatcher protos. + */ + 'inclusion_list'?: (_envoy_type_matcher_v3_ListStringMatcher__Output | null); + 'stats_matcher': "reject_all"|"exclusion_list"|"inclusion_list"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsSink.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsSink.ts new file mode 100644 index 000000000..3eb8926fa --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsSink.ts @@ -0,0 +1,43 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +/** + * Configuration for pluggable stats sinks. + */ +export interface StatsSink { + /** + * The name of the stats sink to instantiate. The name must match a supported + * stats sink. + * See the :ref:`extensions listed in typed_config below ` for the default list of available stats sink. + * Sinks optionally support tagged/multiple dimensional metrics. + */ + 'name'?: (string); + 'typed_config'?: (_google_protobuf_Any | null); + /** + * Stats sink specific configuration which depends on the sink being instantiated. See + * :ref:`StatsdSink ` for an example. + * [#extension-category: envoy.stats_sinks] + */ + 'config_type'?: "typed_config"; +} + +/** + * Configuration for pluggable stats sinks. + */ +export interface StatsSink__Output { + /** + * The name of the stats sink to instantiate. The name must match a supported + * stats sink. + * See the :ref:`extensions listed in typed_config below ` for the default list of available stats sink. + * Sinks optionally support tagged/multiple dimensional metrics. + */ + 'name': (string); + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * Stats sink specific configuration which depends on the sink being instantiated. See + * :ref:`StatsdSink ` for an example. + * [#extension-category: envoy.stats_sinks] + */ + 'config_type': "typed_config"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsdSink.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsdSink.ts new file mode 100644 index 000000000..69d978920 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/StatsdSink.ts @@ -0,0 +1,103 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + +import type { Address as _envoy_config_core_v3_Address, Address__Output as _envoy_config_core_v3_Address__Output } from '../../../../envoy/config/core/v3/Address'; + +/** + * Stats configuration proto schema for built-in *envoy.stat_sinks.statsd* sink. This sink does not support + * tagged metrics. + * [#extension: envoy.stat_sinks.statsd] + */ +export interface StatsdSink { + /** + * The UDP address of a running `statsd `_ + * compliant listener. If specified, statistics will be flushed to this + * address. + */ + 'address'?: (_envoy_config_core_v3_Address | null); + /** + * The name of a cluster that is running a TCP `statsd + * `_ compliant listener. If specified, + * Envoy will connect to this cluster to flush statistics. + */ + 'tcp_cluster_name'?: (string); + /** + * Optional custom prefix for StatsdSink. If + * specified, this will override the default prefix. + * For example: + * + * .. code-block:: json + * + * { + * "prefix" : "envoy-prod" + * } + * + * will change emitted stats to + * + * .. code-block:: cpp + * + * envoy-prod.test_counter:1|c + * envoy-prod.test_timer:5|ms + * + * Note that the default prefix, "envoy", will be used if a prefix is not + * specified. + * + * Stats with default prefix: + * + * .. code-block:: cpp + * + * envoy.test_counter:1|c + * envoy.test_timer:5|ms + */ + 'prefix'?: (string); + 'statsd_specifier'?: "address"|"tcp_cluster_name"; +} + +/** + * Stats configuration proto schema for built-in *envoy.stat_sinks.statsd* sink. This sink does not support + * tagged metrics. + * [#extension: envoy.stat_sinks.statsd] + */ +export interface StatsdSink__Output { + /** + * The UDP address of a running `statsd `_ + * compliant listener. If specified, statistics will be flushed to this + * address. + */ + 'address'?: (_envoy_config_core_v3_Address__Output | null); + /** + * The name of a cluster that is running a TCP `statsd + * `_ compliant listener. If specified, + * Envoy will connect to this cluster to flush statistics. + */ + 'tcp_cluster_name'?: (string); + /** + * Optional custom prefix for StatsdSink. If + * specified, this will override the default prefix. + * For example: + * + * .. code-block:: json + * + * { + * "prefix" : "envoy-prod" + * } + * + * will change emitted stats to + * + * .. code-block:: cpp + * + * envoy-prod.test_counter:1|c + * envoy-prod.test_timer:5|ms + * + * Note that the default prefix, "envoy", will be used if a prefix is not + * specified. + * + * Stats with default prefix: + * + * .. code-block:: cpp + * + * envoy.test_counter:1|c + * envoy.test_timer:5|ms + */ + 'prefix': (string); + 'statsd_specifier': "address"|"tcp_cluster_name"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/TagSpecifier.ts b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/TagSpecifier.ts new file mode 100644 index 000000000..9b0bb2467 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/metrics/v3/TagSpecifier.ts @@ -0,0 +1,174 @@ +// Original file: deps/envoy-api/envoy/config/metrics/v3/stats.proto + + +/** + * Designates a tag name and value pair. The value may be either a fixed value + * or a regex providing the value via capture groups. The specified tag will be + * unconditionally set if a fixed value, otherwise it will only be set if one + * or more capture groups in the regex match. + */ +export interface TagSpecifier { + /** + * Attaches an identifier to the tag values to identify the tag being in the + * sink. Envoy has a set of default names and regexes to extract dynamic + * portions of existing stats, which can be found in :repo:`well_known_names.h + * ` in the Envoy repository. If a :ref:`tag_name + * ` is provided in the config and + * neither :ref:`regex ` or + * :ref:`fixed_value ` were specified, + * Envoy will attempt to find that name in its set of defaults and use the accompanying regex. + * + * .. note:: + * + * It is invalid to specify the same tag name twice in a config. + */ + 'tag_name'?: (string); + /** + * Designates a tag to strip from the tag extracted name and provide as a named + * tag value for all statistics. This will only occur if any part of the name + * matches the regex provided with one or more capture groups. + * + * The first capture group identifies the portion of the name to remove. The + * second capture group (which will normally be nested inside the first) will + * designate the value of the tag for the statistic. If no second capture + * group is provided, the first will also be used to set the value of the tag. + * All other capture groups will be ignored. + * + * Example 1. a stat name ``cluster.foo_cluster.upstream_rq_timeout`` and + * one tag specifier: + * + * .. code-block:: json + * + * { + * "tag_name": "envoy.cluster_name", + * "regex": "^cluster\\.((.+?)\\.)" + * } + * + * Note that the regex will remove ``foo_cluster.`` making the tag extracted + * name ``cluster.upstream_rq_timeout`` and the tag value for + * ``envoy.cluster_name`` will be ``foo_cluster`` (note: there will be no + * ``.`` character because of the second capture group). + * + * Example 2. a stat name + * ``http.connection_manager_1.user_agent.ios.downstream_cx_total`` and two + * tag specifiers: + * + * .. code-block:: json + * + * [ + * { + * "tag_name": "envoy.http_user_agent", + * "regex": "^http(?=\\.).*?\\.user_agent\\.((.+?)\\.)\\w+?$" + * }, + * { + * "tag_name": "envoy.http_conn_manager_prefix", + * "regex": "^http\\.((.*?)\\.)" + * } + * ] + * + * The two regexes of the specifiers will be processed in the definition order. + * + * The first regex will remove ``ios.``, leaving the tag extracted name + * ``http.connection_manager_1.user_agent.downstream_cx_total``. The tag + * ``envoy.http_user_agent`` will be added with tag value ``ios``. + * + * The second regex will remove ``connection_manager_1.`` from the tag + * extracted name produced by the first regex + * ``http.connection_manager_1.user_agent.downstream_cx_total``, leaving + * ``http.user_agent.downstream_cx_total`` as the tag extracted name. The tag + * ``envoy.http_conn_manager_prefix`` will be added with the tag value + * ``connection_manager_1``. + */ + 'regex'?: (string); + /** + * Specifies a fixed tag value for the ``tag_name``. + */ + 'fixed_value'?: (string); + 'tag_value'?: "regex"|"fixed_value"; +} + +/** + * Designates a tag name and value pair. The value may be either a fixed value + * or a regex providing the value via capture groups. The specified tag will be + * unconditionally set if a fixed value, otherwise it will only be set if one + * or more capture groups in the regex match. + */ +export interface TagSpecifier__Output { + /** + * Attaches an identifier to the tag values to identify the tag being in the + * sink. Envoy has a set of default names and regexes to extract dynamic + * portions of existing stats, which can be found in :repo:`well_known_names.h + * ` in the Envoy repository. If a :ref:`tag_name + * ` is provided in the config and + * neither :ref:`regex ` or + * :ref:`fixed_value ` were specified, + * Envoy will attempt to find that name in its set of defaults and use the accompanying regex. + * + * .. note:: + * + * It is invalid to specify the same tag name twice in a config. + */ + 'tag_name': (string); + /** + * Designates a tag to strip from the tag extracted name and provide as a named + * tag value for all statistics. This will only occur if any part of the name + * matches the regex provided with one or more capture groups. + * + * The first capture group identifies the portion of the name to remove. The + * second capture group (which will normally be nested inside the first) will + * designate the value of the tag for the statistic. If no second capture + * group is provided, the first will also be used to set the value of the tag. + * All other capture groups will be ignored. + * + * Example 1. a stat name ``cluster.foo_cluster.upstream_rq_timeout`` and + * one tag specifier: + * + * .. code-block:: json + * + * { + * "tag_name": "envoy.cluster_name", + * "regex": "^cluster\\.((.+?)\\.)" + * } + * + * Note that the regex will remove ``foo_cluster.`` making the tag extracted + * name ``cluster.upstream_rq_timeout`` and the tag value for + * ``envoy.cluster_name`` will be ``foo_cluster`` (note: there will be no + * ``.`` character because of the second capture group). + * + * Example 2. a stat name + * ``http.connection_manager_1.user_agent.ios.downstream_cx_total`` and two + * tag specifiers: + * + * .. code-block:: json + * + * [ + * { + * "tag_name": "envoy.http_user_agent", + * "regex": "^http(?=\\.).*?\\.user_agent\\.((.+?)\\.)\\w+?$" + * }, + * { + * "tag_name": "envoy.http_conn_manager_prefix", + * "regex": "^http\\.((.*?)\\.)" + * } + * ] + * + * The two regexes of the specifiers will be processed in the definition order. + * + * The first regex will remove ``ios.``, leaving the tag extracted name + * ``http.connection_manager_1.user_agent.downstream_cx_total``. The tag + * ``envoy.http_user_agent`` will be added with tag value ``ios``. + * + * The second regex will remove ``connection_manager_1.`` from the tag + * extracted name produced by the first regex + * ``http.connection_manager_1.user_agent.downstream_cx_total``, leaving + * ``http.user_agent.downstream_cx_total`` as the tag extracted name. The tag + * ``envoy.http_conn_manager_prefix`` will be added with the tag value + * ``connection_manager_1``. + */ + 'regex'?: (string); + /** + * Specifies a fixed tag value for the ``tag_name``. + */ + 'fixed_value'?: (string); + 'tag_value': "regex"|"fixed_value"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/BufferFactoryConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/BufferFactoryConfig.ts new file mode 100644 index 000000000..b3fbe1459 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/BufferFactoryConfig.ts @@ -0,0 +1,50 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + + +/** + * Configuration for which accounts the WatermarkBuffer Factories should + * track. + */ +export interface BufferFactoryConfig { + /** + * The minimum power of two at which Envoy starts tracking an account. + * + * Envoy has 8 power of two buckets starting with the provided exponent below. + * Concretely the 1st bucket contains accounts for streams that use + * [2^minimum_account_to_track_power_of_two, + * 2^(minimum_account_to_track_power_of_two + 1)) bytes. + * With the 8th bucket tracking accounts + * >= 128 * 2^minimum_account_to_track_power_of_two. + * + * The maximum value is 56, since we're using uint64_t for bytes counting, + * and that's the last value that would use the 8 buckets. In practice, + * we don't expect the proxy to be holding 2^56 bytes. + * + * If omitted, Envoy should not do any tracking. + */ + 'minimum_account_to_track_power_of_two'?: (number); +} + +/** + * Configuration for which accounts the WatermarkBuffer Factories should + * track. + */ +export interface BufferFactoryConfig__Output { + /** + * The minimum power of two at which Envoy starts tracking an account. + * + * Envoy has 8 power of two buckets starting with the provided exponent below. + * Concretely the 1st bucket contains accounts for streams that use + * [2^minimum_account_to_track_power_of_two, + * 2^(minimum_account_to_track_power_of_two + 1)) bytes. + * With the 8th bucket tracking accounts + * >= 128 * 2^minimum_account_to_track_power_of_two. + * + * The maximum value is 56, since we're using uint64_t for bytes counting, + * and that's the last value that would use the 8 buckets. In practice, + * we don't expect the proxy to be holding 2^56 bytes. + * + * If omitted, Envoy should not do any tracking. + */ + 'minimum_account_to_track_power_of_two': (number); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/OverloadAction.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/OverloadAction.ts new file mode 100644 index 000000000..84f4db34b --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/OverloadAction.ts @@ -0,0 +1,42 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + +import type { Trigger as _envoy_config_overload_v3_Trigger, Trigger__Output as _envoy_config_overload_v3_Trigger__Output } from '../../../../envoy/config/overload/v3/Trigger'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +export interface OverloadAction { + /** + * The name of the overload action. This is just a well-known string that listeners can + * use for registering callbacks. Custom overload actions should be named using reverse + * DNS to ensure uniqueness. + */ + 'name'?: (string); + /** + * A set of triggers for this action. The state of the action is the maximum + * state of all triggers, which can be scaling between 0 and 1 or saturated. Listeners + * are notified when the overload action changes state. + */ + 'triggers'?: (_envoy_config_overload_v3_Trigger)[]; + /** + * Configuration for the action being instantiated. + */ + 'typed_config'?: (_google_protobuf_Any | null); +} + +export interface OverloadAction__Output { + /** + * The name of the overload action. This is just a well-known string that listeners can + * use for registering callbacks. Custom overload actions should be named using reverse + * DNS to ensure uniqueness. + */ + 'name': (string); + /** + * A set of triggers for this action. The state of the action is the maximum + * state of all triggers, which can be scaling between 0 and 1 or saturated. Listeners + * are notified when the overload action changes state. + */ + 'triggers': (_envoy_config_overload_v3_Trigger__Output)[]; + /** + * Configuration for the action being instantiated. + */ + 'typed_config': (_google_protobuf_Any__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/OverloadManager.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/OverloadManager.ts new file mode 100644 index 000000000..e7f75b8e9 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/OverloadManager.ts @@ -0,0 +1,44 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { ResourceMonitor as _envoy_config_overload_v3_ResourceMonitor, ResourceMonitor__Output as _envoy_config_overload_v3_ResourceMonitor__Output } from '../../../../envoy/config/overload/v3/ResourceMonitor'; +import type { OverloadAction as _envoy_config_overload_v3_OverloadAction, OverloadAction__Output as _envoy_config_overload_v3_OverloadAction__Output } from '../../../../envoy/config/overload/v3/OverloadAction'; +import type { BufferFactoryConfig as _envoy_config_overload_v3_BufferFactoryConfig, BufferFactoryConfig__Output as _envoy_config_overload_v3_BufferFactoryConfig__Output } from '../../../../envoy/config/overload/v3/BufferFactoryConfig'; + +export interface OverloadManager { + /** + * The interval for refreshing resource usage. + */ + 'refresh_interval'?: (_google_protobuf_Duration | null); + /** + * The set of resources to monitor. + */ + 'resource_monitors'?: (_envoy_config_overload_v3_ResourceMonitor)[]; + /** + * The set of overload actions. + */ + 'actions'?: (_envoy_config_overload_v3_OverloadAction)[]; + /** + * Configuration for buffer factory. + */ + 'buffer_factory_config'?: (_envoy_config_overload_v3_BufferFactoryConfig | null); +} + +export interface OverloadManager__Output { + /** + * The interval for refreshing resource usage. + */ + 'refresh_interval': (_google_protobuf_Duration__Output | null); + /** + * The set of resources to monitor. + */ + 'resource_monitors': (_envoy_config_overload_v3_ResourceMonitor__Output)[]; + /** + * The set of overload actions. + */ + 'actions': (_envoy_config_overload_v3_OverloadAction__Output)[]; + /** + * Configuration for buffer factory. + */ + 'buffer_factory_config': (_envoy_config_overload_v3_BufferFactoryConfig__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ResourceMonitor.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ResourceMonitor.ts new file mode 100644 index 000000000..02fde2411 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ResourceMonitor.ts @@ -0,0 +1,33 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +export interface ResourceMonitor { + /** + * The name of the resource monitor to instantiate. Must match a registered + * resource monitor type. + * See the :ref:`extensions listed in typed_config below ` for the default list of available resource monitor. + */ + 'name'?: (string); + 'typed_config'?: (_google_protobuf_Any | null); + /** + * Configuration for the resource monitor being instantiated. + * [#extension-category: envoy.resource_monitors] + */ + 'config_type'?: "typed_config"; +} + +export interface ResourceMonitor__Output { + /** + * The name of the resource monitor to instantiate. Must match a registered + * resource monitor type. + * See the :ref:`extensions listed in typed_config below ` for the default list of available resource monitor. + */ + 'name': (string); + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * Configuration for the resource monitor being instantiated. + * [#extension-category: envoy.resource_monitors] + */ + 'config_type': "typed_config"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ScaleTimersOverloadActionConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ScaleTimersOverloadActionConfig.ts new file mode 100644 index 000000000..bb48fe3f6 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ScaleTimersOverloadActionConfig.ts @@ -0,0 +1,89 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { Percent as _envoy_type_v3_Percent, Percent__Output as _envoy_type_v3_Percent__Output } from '../../../../envoy/type/v3/Percent'; + +export interface _envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer { + /** + * The type of timer this minimum applies to. + */ + 'timer'?: (_envoy_config_overload_v3_ScaleTimersOverloadActionConfig_TimerType | keyof typeof _envoy_config_overload_v3_ScaleTimersOverloadActionConfig_TimerType); + /** + * Sets the minimum duration as an absolute value. + */ + 'min_timeout'?: (_google_protobuf_Duration | null); + /** + * Sets the minimum duration as a percentage of the maximum value. + */ + 'min_scale'?: (_envoy_type_v3_Percent | null); + 'overload_adjust'?: "min_timeout"|"min_scale"; +} + +export interface _envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer__Output { + /** + * The type of timer this minimum applies to. + */ + 'timer': (keyof typeof _envoy_config_overload_v3_ScaleTimersOverloadActionConfig_TimerType); + /** + * Sets the minimum duration as an absolute value. + */ + 'min_timeout'?: (_google_protobuf_Duration__Output | null); + /** + * Sets the minimum duration as a percentage of the maximum value. + */ + 'min_scale'?: (_envoy_type_v3_Percent__Output | null); + 'overload_adjust': "min_timeout"|"min_scale"; +} + +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + +export enum _envoy_config_overload_v3_ScaleTimersOverloadActionConfig_TimerType { + /** + * Unsupported value; users must explicitly specify the timer they want scaled. + */ + UNSPECIFIED = 0, + /** + * Adjusts the idle timer for downstream HTTP connections that takes effect when there are no active streams. + * This affects the value of :ref:`HttpConnectionManager.common_http_protocol_options.idle_timeout + * ` + */ + HTTP_DOWNSTREAM_CONNECTION_IDLE = 1, + /** + * Adjusts the idle timer for HTTP streams initiated by downstream clients. + * This affects the value of :ref:`RouteAction.idle_timeout ` and + * :ref:`HttpConnectionManager.stream_idle_timeout + * ` + */ + HTTP_DOWNSTREAM_STREAM_IDLE = 2, + /** + * Adjusts the timer for how long downstream clients have to finish transport-level negotiations + * before the connection is closed. + * This affects the value of + * :ref:`FilterChain.transport_socket_connect_timeout `. + */ + TRANSPORT_SOCKET_CONNECT = 3, +} + +/** + * Typed configuration for the "envoy.overload_actions.reduce_timeouts" action. See + * :ref:`the docs ` for an example of how to configure + * the action with different timeouts and minimum values. + */ +export interface ScaleTimersOverloadActionConfig { + /** + * A set of timer scaling rules to be applied. + */ + 'timer_scale_factors'?: (_envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer)[]; +} + +/** + * Typed configuration for the "envoy.overload_actions.reduce_timeouts" action. See + * :ref:`the docs ` for an example of how to configure + * the action with different timeouts and minimum values. + */ +export interface ScaleTimersOverloadActionConfig__Output { + /** + * A set of timer scaling rules to be applied. + */ + 'timer_scale_factors': (_envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ScaledTrigger.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ScaledTrigger.ts new file mode 100644 index 000000000..8c6574f56 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ScaledTrigger.ts @@ -0,0 +1,28 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + + +export interface ScaledTrigger { + /** + * If the resource pressure is greater than this value, the trigger will be in the + * :ref:`scaling ` state with value + * `(pressure - scaling_threshold) / (saturation_threshold - scaling_threshold)`. + */ + 'scaling_threshold'?: (number | string); + /** + * If the resource pressure is greater than this value, the trigger will enter saturation. + */ + 'saturation_threshold'?: (number | string); +} + +export interface ScaledTrigger__Output { + /** + * If the resource pressure is greater than this value, the trigger will be in the + * :ref:`scaling ` state with value + * `(pressure - scaling_threshold) / (saturation_threshold - scaling_threshold)`. + */ + 'scaling_threshold': (number); + /** + * If the resource pressure is greater than this value, the trigger will enter saturation. + */ + 'saturation_threshold': (number); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ThresholdTrigger.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ThresholdTrigger.ts new file mode 100644 index 000000000..b02ddd47d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/ThresholdTrigger.ts @@ -0,0 +1,18 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + + +export interface ThresholdTrigger { + /** + * If the resource pressure is greater than or equal to this value, the trigger + * will enter saturation. + */ + 'value'?: (number | string); +} + +export interface ThresholdTrigger__Output { + /** + * If the resource pressure is greater than or equal to this value, the trigger + * will enter saturation. + */ + 'value': (number); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/Trigger.ts b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/Trigger.ts new file mode 100644 index 000000000..38f360ee7 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/overload/v3/Trigger.ts @@ -0,0 +1,24 @@ +// Original file: deps/envoy-api/envoy/config/overload/v3/overload.proto + +import type { ThresholdTrigger as _envoy_config_overload_v3_ThresholdTrigger, ThresholdTrigger__Output as _envoy_config_overload_v3_ThresholdTrigger__Output } from '../../../../envoy/config/overload/v3/ThresholdTrigger'; +import type { ScaledTrigger as _envoy_config_overload_v3_ScaledTrigger, ScaledTrigger__Output as _envoy_config_overload_v3_ScaledTrigger__Output } from '../../../../envoy/config/overload/v3/ScaledTrigger'; + +export interface Trigger { + /** + * The name of the resource this is a trigger for. + */ + 'name'?: (string); + 'threshold'?: (_envoy_config_overload_v3_ThresholdTrigger | null); + 'scaled'?: (_envoy_config_overload_v3_ScaledTrigger | null); + 'trigger_oneof'?: "threshold"|"scaled"; +} + +export interface Trigger__Output { + /** + * The name of the resource this is a trigger for. + */ + 'name': (string); + 'threshold'?: (_envoy_config_overload_v3_ThresholdTrigger__Output | null); + 'scaled'?: (_envoy_config_overload_v3_ScaledTrigger__Output | null); + 'trigger_oneof': "threshold"|"scaled"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/ClusterSpecifierPlugin.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/ClusterSpecifierPlugin.ts new file mode 100644 index 000000000..14724412a --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/ClusterSpecifierPlugin.ts @@ -0,0 +1,23 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route.proto + +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +/** + * Configuration for a cluster specifier plugin. + */ +export interface ClusterSpecifierPlugin { + /** + * The name of the plugin and its opaque configuration. + */ + 'extension'?: (_envoy_config_core_v3_TypedExtensionConfig | null); +} + +/** + * Configuration for a cluster specifier plugin. + */ +export interface ClusterSpecifierPlugin__Output { + /** + * The name of the plugin and its opaque configuration. + */ + 'extension': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/CorsPolicy.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/CorsPolicy.ts new file mode 100644 index 000000000..40634448a --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/CorsPolicy.ts @@ -0,0 +1,113 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { RuntimeFractionalPercent as _envoy_config_core_v3_RuntimeFractionalPercent, RuntimeFractionalPercent__Output as _envoy_config_core_v3_RuntimeFractionalPercent__Output } from '../../../../envoy/config/core/v3/RuntimeFractionalPercent'; +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; + +/** + * [#next-free-field: 12] + */ +export interface CorsPolicy { + /** + * Specifies the content for the *access-control-allow-methods* header. + */ + 'allow_methods'?: (string); + /** + * Specifies the content for the *access-control-allow-headers* header. + */ + 'allow_headers'?: (string); + /** + * Specifies the content for the *access-control-expose-headers* header. + */ + 'expose_headers'?: (string); + /** + * Specifies the content for the *access-control-max-age* header. + */ + 'max_age'?: (string); + /** + * Specifies whether the resource allows credentials. + */ + 'allow_credentials'?: (_google_protobuf_BoolValue | null); + /** + * Specifies the % of requests for which the CORS filter is enabled. + * + * If neither ``enabled``, ``filter_enabled``, nor ``shadow_enabled`` are specified, the CORS + * filter will be enabled for 100% of the requests. + * + * If :ref:`runtime_key ` is + * specified, Envoy will lookup the runtime key to get the percentage of requests to filter. + */ + 'filter_enabled'?: (_envoy_config_core_v3_RuntimeFractionalPercent | null); + /** + * Specifies the % of requests for which the CORS policies will be evaluated and tracked, but not + * enforced. + * + * This field is intended to be used when ``filter_enabled`` and ``enabled`` are off. One of those + * fields have to explicitly disable the filter in order for this setting to take effect. + * + * If :ref:`runtime_key ` is specified, + * Envoy will lookup the runtime key to get the percentage of requests for which it will evaluate + * and track the request's *Origin* to determine if it's valid but will not enforce any policies. + */ + 'shadow_enabled'?: (_envoy_config_core_v3_RuntimeFractionalPercent | null); + /** + * Specifies string patterns that match allowed origins. An origin is allowed if any of the + * string matchers match. + */ + 'allow_origin_string_match'?: (_envoy_type_matcher_v3_StringMatcher)[]; + 'enabled_specifier'?: "filter_enabled"; +} + +/** + * [#next-free-field: 12] + */ +export interface CorsPolicy__Output { + /** + * Specifies the content for the *access-control-allow-methods* header. + */ + 'allow_methods': (string); + /** + * Specifies the content for the *access-control-allow-headers* header. + */ + 'allow_headers': (string); + /** + * Specifies the content for the *access-control-expose-headers* header. + */ + 'expose_headers': (string); + /** + * Specifies the content for the *access-control-max-age* header. + */ + 'max_age': (string); + /** + * Specifies whether the resource allows credentials. + */ + 'allow_credentials': (_google_protobuf_BoolValue__Output | null); + /** + * Specifies the % of requests for which the CORS filter is enabled. + * + * If neither ``enabled``, ``filter_enabled``, nor ``shadow_enabled`` are specified, the CORS + * filter will be enabled for 100% of the requests. + * + * If :ref:`runtime_key ` is + * specified, Envoy will lookup the runtime key to get the percentage of requests to filter. + */ + 'filter_enabled'?: (_envoy_config_core_v3_RuntimeFractionalPercent__Output | null); + /** + * Specifies the % of requests for which the CORS policies will be evaluated and tracked, but not + * enforced. + * + * This field is intended to be used when ``filter_enabled`` and ``enabled`` are off. One of those + * fields have to explicitly disable the filter in order for this setting to take effect. + * + * If :ref:`runtime_key ` is specified, + * Envoy will lookup the runtime key to get the percentage of requests for which it will evaluate + * and track the request's *Origin* to determine if it's valid but will not enforce any policies. + */ + 'shadow_enabled': (_envoy_config_core_v3_RuntimeFractionalPercent__Output | null); + /** + * Specifies string patterns that match allowed origins. An origin is allowed if any of the + * string matchers match. + */ + 'allow_origin_string_match': (_envoy_type_matcher_v3_StringMatcher__Output)[]; + 'enabled_specifier': "filter_enabled"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/Decorator.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Decorator.ts similarity index 87% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/Decorator.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/Decorator.ts index 68c91327d..fa8bef1d8 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/Decorator.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Decorator.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; @@ -17,7 +17,7 @@ export interface Decorator { /** * Whether the decorated details should be propagated to the other party. The default is true. */ - 'propagate'?: (_google_protobuf_BoolValue); + 'propagate'?: (_google_protobuf_BoolValue | null); } export interface Decorator__Output { @@ -35,5 +35,5 @@ export interface Decorator__Output { /** * Whether the decorated details should be propagated to the other party. The default is true. */ - 'propagate'?: (_google_protobuf_BoolValue__Output); + 'propagate': (_google_protobuf_BoolValue__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/DirectResponseAction.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/DirectResponseAction.ts similarity index 51% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/DirectResponseAction.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/DirectResponseAction.ts index 83777f9e3..794ae510a 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/DirectResponseAction.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/DirectResponseAction.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -import type { DataSource as _envoy_api_v2_core_DataSource, DataSource__Output as _envoy_api_v2_core_DataSource__Output } from '../../../../envoy/api/v2/core/DataSource'; +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../envoy/config/core/v3/DataSource'; export interface DirectResponseAction { /** @@ -14,10 +14,10 @@ export interface DirectResponseAction { * .. note:: * * Headers can be specified using *response_headers_to_add* in the enclosing - * :ref:`envoy_api_msg_route.Route`, :ref:`envoy_api_msg_RouteConfiguration` or - * :ref:`envoy_api_msg_route.VirtualHost`. + * :ref:`envoy_v3_api_msg_config.route.v3.Route`, :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration` or + * :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost`. */ - 'body'?: (_envoy_api_v2_core_DataSource); + 'body'?: (_envoy_config_core_v3_DataSource | null); } export interface DirectResponseAction__Output { @@ -32,8 +32,8 @@ export interface DirectResponseAction__Output { * .. note:: * * Headers can be specified using *response_headers_to_add* in the enclosing - * :ref:`envoy_api_msg_route.Route`, :ref:`envoy_api_msg_RouteConfiguration` or - * :ref:`envoy_api_msg_route.VirtualHost`. + * :ref:`envoy_v3_api_msg_config.route.v3.Route`, :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration` or + * :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost`. */ - 'body'?: (_envoy_api_v2_core_DataSource__Output); + 'body': (_envoy_config_core_v3_DataSource__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/FilterAction.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/FilterAction.ts similarity index 62% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/FilterAction.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/FilterAction.ts index a41f3f417..2765c0799 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/FilterAction.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/FilterAction.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; @@ -6,12 +6,12 @@ import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__ * A filter-defined action type. */ export interface FilterAction { - 'action'?: (_google_protobuf_Any); + 'action'?: (_google_protobuf_Any | null); } /** * A filter-defined action type. */ export interface FilterAction__Output { - 'action'?: (_google_protobuf_Any__Output); + 'action': (_google_protobuf_Any__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/FilterConfig.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/FilterConfig.ts new file mode 100644 index 000000000..2c960419c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/FilterConfig.ts @@ -0,0 +1,47 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +/** + * A simple wrapper for an HTTP filter config. This is intended to be used as a wrapper for the + * map value in + * :ref:`VirtualHost.typed_per_filter_config`, + * :ref:`Route.typed_per_filter_config`, + * or :ref:`WeightedCluster.ClusterWeight.typed_per_filter_config` + * to add additional flags to the filter. + * [#not-implemented-hide:] + */ +export interface FilterConfig { + /** + * The filter config. + */ + 'config'?: (_google_protobuf_Any | null); + /** + * If true, the filter is optional, meaning that if the client does + * not support the specified filter, it may ignore the map entry rather + * than rejecting the config. + */ + 'is_optional'?: (boolean); +} + +/** + * A simple wrapper for an HTTP filter config. This is intended to be used as a wrapper for the + * map value in + * :ref:`VirtualHost.typed_per_filter_config`, + * :ref:`Route.typed_per_filter_config`, + * or :ref:`WeightedCluster.ClusterWeight.typed_per_filter_config` + * to add additional flags to the filter. + * [#not-implemented-hide:] + */ +export interface FilterConfig__Output { + /** + * The filter config. + */ + 'config': (_google_protobuf_Any__Output | null); + /** + * If true, the filter is optional, meaning that if the client does + * not support the specified filter, it may ignore the map entry rather + * than rejecting the config. + */ + 'is_optional': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/HeaderMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/HeaderMatcher.ts similarity index 59% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/HeaderMatcher.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/HeaderMatcher.ts index 347849901..bde8f28cd 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/HeaderMatcher.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/HeaderMatcher.ts @@ -1,7 +1,8 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -import type { Int64Range as _envoy_type_Int64Range, Int64Range__Output as _envoy_type_Int64Range__Output } from '../../../../envoy/type/Int64Range'; -import type { RegexMatcher as _envoy_type_matcher_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_RegexMatcher__Output } from '../../../../envoy/type/matcher/RegexMatcher'; +import type { Int64Range as _envoy_type_v3_Int64Range, Int64Range__Output as _envoy_type_v3_Int64Range__Output } from '../../../../envoy/type/v3/Int64Range'; +import type { RegexMatcher as _envoy_type_matcher_v3_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_v3_RegexMatcher__Output } from '../../../../envoy/type/matcher/v3/RegexMatcher'; +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; import type { Long } from '@grpc/proto-loader'; /** @@ -24,12 +25,12 @@ import type { Long } from '@grpc/proto-loader'; * * .. attention:: * In the absence of any header match specifier, match will default to :ref:`present_match - * `. i.e, a request that has the :ref:`name - * ` header will match, regardless of the header's + * `. i.e, a request that has the :ref:`name + * ` header will match, regardless of the header's * value. * * [#next-major-version: HeaderMatcher should be refactored to use StringMatcher.] - * [#next-free-field: 12] + * [#next-free-field: 14] */ export interface HeaderMatcher { /** @@ -38,25 +39,9 @@ export interface HeaderMatcher { 'name'?: (string); /** * If specified, header match will be performed based on the value of the header. + * This field is deprecated. Please use :ref:`string_match `. */ 'exact_match'?: (string); - /** - * If specified, this regex string is a regular expression rule which implies the entire request - * header value must match the regex. The rule will not match if only a subsequence of the - * request header value matches the regex. The regex grammar used in the value field is defined - * `here `_. - * - * Examples: - * - * * The regex ``\d{3}`` matches the value *123* - * * The regex ``\d{3}`` does not match the value *1234* - * * The regex ``\d{3}`` does not match the value *123.456* - * - * .. attention:: - * This field has been deprecated in favor of `safe_regex_match` as it is not safe for use - * with untrusted input in all cases. - */ - 'regex_match'?: (string); /** * If specified, header match will be performed based on range. * The rule will match if the request header value is within this range. @@ -70,10 +55,10 @@ export interface HeaderMatcher { * * For range [-10,0), route will match for header value -1, but not for 0, "somestring", 10.9, * "-1somestring" */ - 'range_match'?: (_envoy_type_Int64Range); + 'range_match'?: (_envoy_type_v3_Int64Range | null); /** - * If specified, header match will be performed based on whether the header is in the - * request. + * If specified as true, header match will be performed based on whether the header is in the + * request. If specified as false, header match will be performed based on whether the header is absent. */ 'present_match'?: (boolean); /** @@ -88,6 +73,7 @@ export interface HeaderMatcher { /** * If specified, header match will be performed based on the prefix of the header value. * Note: empty prefix is not allowed, please use present_match instead. + * This field is deprecated. Please use :ref:`string_match `. * * Examples: * @@ -97,6 +83,7 @@ export interface HeaderMatcher { /** * If specified, header match will be performed based on the suffix of the header value. * Note: empty suffix is not allowed, please use present_match instead. + * This field is deprecated. Please use :ref:`string_match `. * * Examples: * @@ -107,12 +94,28 @@ export interface HeaderMatcher { * If specified, this regex string is a regular expression rule which implies the entire request * header value must match the regex. The rule will not match if only a subsequence of the * request header value matches the regex. + * This field is deprecated. Please use :ref:`string_match `. + */ + 'safe_regex_match'?: (_envoy_type_matcher_v3_RegexMatcher | null); + /** + * If specified, header match will be performed based on whether the header value contains + * the given value or not. + * Note: empty contains match is not allowed, please use present_match instead. + * This field is deprecated. Please use :ref:`string_match `. + * + * Examples: + * + * * The value *abcd* matches the value *xyzabcdpqr*, but not for *xyzbcdpqr*. + */ + 'contains_match'?: (string); + /** + * If specified, header match will be performed based on the string match of the header value. */ - 'safe_regex_match'?: (_envoy_type_matcher_RegexMatcher); + 'string_match'?: (_envoy_type_matcher_v3_StringMatcher | null); /** * Specifies how the header match will be performed to route the request. */ - 'header_match_specifier'?: "exact_match"|"regex_match"|"safe_regex_match"|"range_match"|"present_match"|"prefix_match"|"suffix_match"; + 'header_match_specifier'?: "exact_match"|"safe_regex_match"|"range_match"|"present_match"|"prefix_match"|"suffix_match"|"contains_match"|"string_match"; } /** @@ -135,12 +138,12 @@ export interface HeaderMatcher { * * .. attention:: * In the absence of any header match specifier, match will default to :ref:`present_match - * `. i.e, a request that has the :ref:`name - * ` header will match, regardless of the header's + * `. i.e, a request that has the :ref:`name + * ` header will match, regardless of the header's * value. * * [#next-major-version: HeaderMatcher should be refactored to use StringMatcher.] - * [#next-free-field: 12] + * [#next-free-field: 14] */ export interface HeaderMatcher__Output { /** @@ -149,25 +152,9 @@ export interface HeaderMatcher__Output { 'name': (string); /** * If specified, header match will be performed based on the value of the header. + * This field is deprecated. Please use :ref:`string_match `. */ 'exact_match'?: (string); - /** - * If specified, this regex string is a regular expression rule which implies the entire request - * header value must match the regex. The rule will not match if only a subsequence of the - * request header value matches the regex. The regex grammar used in the value field is defined - * `here `_. - * - * Examples: - * - * * The regex ``\d{3}`` matches the value *123* - * * The regex ``\d{3}`` does not match the value *1234* - * * The regex ``\d{3}`` does not match the value *123.456* - * - * .. attention:: - * This field has been deprecated in favor of `safe_regex_match` as it is not safe for use - * with untrusted input in all cases. - */ - 'regex_match'?: (string); /** * If specified, header match will be performed based on range. * The rule will match if the request header value is within this range. @@ -181,10 +168,10 @@ export interface HeaderMatcher__Output { * * For range [-10,0), route will match for header value -1, but not for 0, "somestring", 10.9, * "-1somestring" */ - 'range_match'?: (_envoy_type_Int64Range__Output); + 'range_match'?: (_envoy_type_v3_Int64Range__Output | null); /** - * If specified, header match will be performed based on whether the header is in the - * request. + * If specified as true, header match will be performed based on whether the header is in the + * request. If specified as false, header match will be performed based on whether the header is absent. */ 'present_match'?: (boolean); /** @@ -199,6 +186,7 @@ export interface HeaderMatcher__Output { /** * If specified, header match will be performed based on the prefix of the header value. * Note: empty prefix is not allowed, please use present_match instead. + * This field is deprecated. Please use :ref:`string_match `. * * Examples: * @@ -208,6 +196,7 @@ export interface HeaderMatcher__Output { /** * If specified, header match will be performed based on the suffix of the header value. * Note: empty suffix is not allowed, please use present_match instead. + * This field is deprecated. Please use :ref:`string_match `. * * Examples: * @@ -218,10 +207,26 @@ export interface HeaderMatcher__Output { * If specified, this regex string is a regular expression rule which implies the entire request * header value must match the regex. The rule will not match if only a subsequence of the * request header value matches the regex. + * This field is deprecated. Please use :ref:`string_match `. + */ + 'safe_regex_match'?: (_envoy_type_matcher_v3_RegexMatcher__Output | null); + /** + * If specified, header match will be performed based on whether the header value contains + * the given value or not. + * Note: empty contains match is not allowed, please use present_match instead. + * This field is deprecated. Please use :ref:`string_match `. + * + * Examples: + * + * * The value *abcd* matches the value *xyzabcdpqr*, but not for *xyzbcdpqr*. + */ + 'contains_match'?: (string); + /** + * If specified, header match will be performed based on the string match of the header value. */ - 'safe_regex_match'?: (_envoy_type_matcher_RegexMatcher__Output); + 'string_match'?: (_envoy_type_matcher_v3_StringMatcher__Output | null); /** * Specifies how the header match will be performed to route the request. */ - 'header_match_specifier': "exact_match"|"regex_match"|"safe_regex_match"|"range_match"|"present_match"|"prefix_match"|"suffix_match"; + 'header_match_specifier': "exact_match"|"safe_regex_match"|"range_match"|"present_match"|"prefix_match"|"suffix_match"|"contains_match"|"string_match"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/HedgePolicy.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/HedgePolicy.ts new file mode 100644 index 000000000..302b6d284 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/HedgePolicy.ts @@ -0,0 +1,76 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../envoy/type/v3/FractionalPercent'; + +/** + * HTTP request hedging :ref:`architecture overview `. + */ +export interface HedgePolicy { + /** + * Specifies the number of initial requests that should be sent upstream. + * Must be at least 1. + * Defaults to 1. + * [#not-implemented-hide:] + */ + 'initial_requests'?: (_google_protobuf_UInt32Value | null); + /** + * Specifies a probability that an additional upstream request should be sent + * on top of what is specified by initial_requests. + * Defaults to 0. + * [#not-implemented-hide:] + */ + 'additional_request_chance'?: (_envoy_type_v3_FractionalPercent | null); + /** + * Indicates that a hedged request should be sent when the per-try timeout is hit. + * This means that a retry will be issued without resetting the original request, leaving multiple upstream requests in flight. + * The first request to complete successfully will be the one returned to the caller. + * + * * At any time, a successful response (i.e. not triggering any of the retry-on conditions) would be returned to the client. + * * Before per-try timeout, an error response (per retry-on conditions) would be retried immediately or returned ot the client + * if there are no more retries left. + * * After per-try timeout, an error response would be discarded, as a retry in the form of a hedged request is already in progress. + * + * Note: For this to have effect, you must have a :ref:`RetryPolicy ` that retries at least + * one error code and specifies a maximum number of retries. + * + * Defaults to false. + */ + 'hedge_on_per_try_timeout'?: (boolean); +} + +/** + * HTTP request hedging :ref:`architecture overview `. + */ +export interface HedgePolicy__Output { + /** + * Specifies the number of initial requests that should be sent upstream. + * Must be at least 1. + * Defaults to 1. + * [#not-implemented-hide:] + */ + 'initial_requests': (_google_protobuf_UInt32Value__Output | null); + /** + * Specifies a probability that an additional upstream request should be sent + * on top of what is specified by initial_requests. + * Defaults to 0. + * [#not-implemented-hide:] + */ + 'additional_request_chance': (_envoy_type_v3_FractionalPercent__Output | null); + /** + * Indicates that a hedged request should be sent when the per-try timeout is hit. + * This means that a retry will be issued without resetting the original request, leaving multiple upstream requests in flight. + * The first request to complete successfully will be the one returned to the caller. + * + * * At any time, a successful response (i.e. not triggering any of the retry-on conditions) would be returned to the client. + * * Before per-try timeout, an error response (per retry-on conditions) would be retried immediately or returned ot the client + * if there are no more retries left. + * * After per-try timeout, an error response would be discarded, as a retry in the form of a hedged request is already in progress. + * + * Note: For this to have effect, you must have a :ref:`RetryPolicy ` that retries at least + * one error code and specifies a maximum number of retries. + * + * Defaults to false. + */ + 'hedge_on_per_try_timeout': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/InternalRedirectPolicy.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/InternalRedirectPolicy.ts new file mode 100644 index 000000000..ab74df94e --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/InternalRedirectPolicy.ts @@ -0,0 +1,74 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; + +/** + * HTTP Internal Redirect :ref:`architecture overview `. + */ +export interface InternalRedirectPolicy { + /** + * An internal redirect is not handled, unless the number of previous internal redirects that a + * downstream request has encountered is lower than this value. + * In the case where a downstream request is bounced among multiple routes by internal redirect, + * the first route that hits this threshold, or does not set :ref:`internal_redirect_policy + * ` + * will pass the redirect back to downstream. + * + * If not specified, at most one redirect will be followed. + */ + 'max_internal_redirects'?: (_google_protobuf_UInt32Value | null); + /** + * Defines what upstream response codes are allowed to trigger internal redirect. If unspecified, + * only 302 will be treated as internal redirect. + * Only 301, 302, 303, 307 and 308 are valid values. Any other codes will be ignored. + */ + 'redirect_response_codes'?: (number)[]; + /** + * Specifies a list of predicates that are queried when an upstream response is deemed + * to trigger an internal redirect by all other criteria. Any predicate in the list can reject + * the redirect, causing the response to be proxied to downstream. + * [#extension-category: envoy.internal_redirect_predicates] + */ + 'predicates'?: (_envoy_config_core_v3_TypedExtensionConfig)[]; + /** + * Allow internal redirect to follow a target URI with a different scheme than the value of + * x-forwarded-proto. The default is false. + */ + 'allow_cross_scheme_redirect'?: (boolean); +} + +/** + * HTTP Internal Redirect :ref:`architecture overview `. + */ +export interface InternalRedirectPolicy__Output { + /** + * An internal redirect is not handled, unless the number of previous internal redirects that a + * downstream request has encountered is lower than this value. + * In the case where a downstream request is bounced among multiple routes by internal redirect, + * the first route that hits this threshold, or does not set :ref:`internal_redirect_policy + * ` + * will pass the redirect back to downstream. + * + * If not specified, at most one redirect will be followed. + */ + 'max_internal_redirects': (_google_protobuf_UInt32Value__Output | null); + /** + * Defines what upstream response codes are allowed to trigger internal redirect. If unspecified, + * only 302 will be treated as internal redirect. + * Only 301, 302, 303, 307 and 308 are valid values. Any other codes will be ignored. + */ + 'redirect_response_codes': (number)[]; + /** + * Specifies a list of predicates that are queried when an upstream response is deemed + * to trigger an internal redirect by all other criteria. Any predicate in the list can reject + * the redirect, causing the response to be proxied to downstream. + * [#extension-category: envoy.internal_redirect_predicates] + */ + 'predicates': (_envoy_config_core_v3_TypedExtensionConfig__Output)[]; + /** + * Allow internal redirect to follow a target URI with a different scheme than the value of + * x-forwarded-proto. The default is false. + */ + 'allow_cross_scheme_redirect': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/NonForwardingAction.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/NonForwardingAction.ts new file mode 100644 index 000000000..e9c67d44f --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/NonForwardingAction.ts @@ -0,0 +1,14 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + + +/** + * [#not-implemented-hide:] + */ +export interface NonForwardingAction { +} + +/** + * [#not-implemented-hide:] + */ +export interface NonForwardingAction__Output { +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/QueryParameterMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/QueryParameterMatcher.ts new file mode 100644 index 000000000..d511259b0 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/QueryParameterMatcher.ts @@ -0,0 +1,47 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; + +/** + * Query parameter matching treats the query string of a request's :path header + * as an ampersand-separated list of keys and/or key=value elements. + * [#next-free-field: 7] + */ +export interface QueryParameterMatcher { + /** + * Specifies the name of a key that must be present in the requested + * *path*'s query string. + */ + 'name'?: (string); + /** + * Specifies whether a query parameter value should match against a string. + */ + 'string_match'?: (_envoy_type_matcher_v3_StringMatcher | null); + /** + * Specifies whether a query parameter should be present. + */ + 'present_match'?: (boolean); + 'query_parameter_match_specifier'?: "string_match"|"present_match"; +} + +/** + * Query parameter matching treats the query string of a request's :path header + * as an ampersand-separated list of keys and/or key=value elements. + * [#next-free-field: 7] + */ +export interface QueryParameterMatcher__Output { + /** + * Specifies the name of a key that must be present in the requested + * *path*'s query string. + */ + 'name': (string); + /** + * Specifies whether a query parameter value should match against a string. + */ + 'string_match'?: (_envoy_type_matcher_v3_StringMatcher__Output | null); + /** + * Specifies whether a query parameter should be present. + */ + 'present_match'?: (boolean); + 'query_parameter_match_specifier': "string_match"|"present_match"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RateLimit.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RateLimit.ts new file mode 100644 index 000000000..f1d49537c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RateLimit.ts @@ -0,0 +1,580 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { HeaderMatcher as _envoy_config_route_v3_HeaderMatcher, HeaderMatcher__Output as _envoy_config_route_v3_HeaderMatcher__Output } from '../../../../envoy/config/route/v3/HeaderMatcher'; +import type { MetadataKey as _envoy_type_metadata_v3_MetadataKey, MetadataKey__Output as _envoy_type_metadata_v3_MetadataKey__Output } from '../../../../envoy/type/metadata/v3/MetadataKey'; + +/** + * [#next-free-field: 10] + */ +export interface _envoy_config_route_v3_RateLimit_Action { + /** + * Rate limit on source cluster. + */ + 'source_cluster'?: (_envoy_config_route_v3_RateLimit_Action_SourceCluster | null); + /** + * Rate limit on destination cluster. + */ + 'destination_cluster'?: (_envoy_config_route_v3_RateLimit_Action_DestinationCluster | null); + /** + * Rate limit on request headers. + */ + 'request_headers'?: (_envoy_config_route_v3_RateLimit_Action_RequestHeaders | null); + /** + * Rate limit on remote address. + */ + 'remote_address'?: (_envoy_config_route_v3_RateLimit_Action_RemoteAddress | null); + /** + * Rate limit on a generic key. + */ + 'generic_key'?: (_envoy_config_route_v3_RateLimit_Action_GenericKey | null); + /** + * Rate limit on the existence of request headers. + */ + 'header_value_match'?: (_envoy_config_route_v3_RateLimit_Action_HeaderValueMatch | null); + /** + * Rate limit on dynamic metadata. + * + * .. attention:: + * This field has been deprecated in favor of the :ref:`metadata ` field + */ + 'dynamic_metadata'?: (_envoy_config_route_v3_RateLimit_Action_DynamicMetaData | null); + /** + * Rate limit on metadata. + */ + 'metadata'?: (_envoy_config_route_v3_RateLimit_Action_MetaData | null); + /** + * Rate limit descriptor extension. See the rate limit descriptor extensions documentation. + * [#extension-category: envoy.rate_limit_descriptors] + */ + 'extension'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + 'action_specifier'?: "source_cluster"|"destination_cluster"|"request_headers"|"remote_address"|"generic_key"|"header_value_match"|"dynamic_metadata"|"metadata"|"extension"; +} + +/** + * [#next-free-field: 10] + */ +export interface _envoy_config_route_v3_RateLimit_Action__Output { + /** + * Rate limit on source cluster. + */ + 'source_cluster'?: (_envoy_config_route_v3_RateLimit_Action_SourceCluster__Output | null); + /** + * Rate limit on destination cluster. + */ + 'destination_cluster'?: (_envoy_config_route_v3_RateLimit_Action_DestinationCluster__Output | null); + /** + * Rate limit on request headers. + */ + 'request_headers'?: (_envoy_config_route_v3_RateLimit_Action_RequestHeaders__Output | null); + /** + * Rate limit on remote address. + */ + 'remote_address'?: (_envoy_config_route_v3_RateLimit_Action_RemoteAddress__Output | null); + /** + * Rate limit on a generic key. + */ + 'generic_key'?: (_envoy_config_route_v3_RateLimit_Action_GenericKey__Output | null); + /** + * Rate limit on the existence of request headers. + */ + 'header_value_match'?: (_envoy_config_route_v3_RateLimit_Action_HeaderValueMatch__Output | null); + /** + * Rate limit on dynamic metadata. + * + * .. attention:: + * This field has been deprecated in favor of the :ref:`metadata ` field + */ + 'dynamic_metadata'?: (_envoy_config_route_v3_RateLimit_Action_DynamicMetaData__Output | null); + /** + * Rate limit on metadata. + */ + 'metadata'?: (_envoy_config_route_v3_RateLimit_Action_MetaData__Output | null); + /** + * Rate limit descriptor extension. See the rate limit descriptor extensions documentation. + * [#extension-category: envoy.rate_limit_descriptors] + */ + 'extension'?: (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + 'action_specifier': "source_cluster"|"destination_cluster"|"request_headers"|"remote_address"|"generic_key"|"header_value_match"|"dynamic_metadata"|"metadata"|"extension"; +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("destination_cluster", "") + * + * Once a request matches against a route table rule, a routed cluster is determined by one of + * the following :ref:`route table configuration ` + * settings: + * + * * :ref:`cluster ` indicates the upstream cluster + * to route to. + * * :ref:`weighted_clusters ` + * chooses a cluster randomly from a set of clusters with attributed weight. + * * :ref:`cluster_header ` indicates which + * header in the request contains the target cluster. + */ +export interface _envoy_config_route_v3_RateLimit_Action_DestinationCluster { +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("destination_cluster", "") + * + * Once a request matches against a route table rule, a routed cluster is determined by one of + * the following :ref:`route table configuration ` + * settings: + * + * * :ref:`cluster ` indicates the upstream cluster + * to route to. + * * :ref:`weighted_clusters ` + * chooses a cluster randomly from a set of clusters with attributed weight. + * * :ref:`cluster_header ` indicates which + * header in the request contains the target cluster. + */ +export interface _envoy_config_route_v3_RateLimit_Action_DestinationCluster__Output { +} + +/** + * The following descriptor entry is appended when the + * :ref:`dynamic metadata ` contains a key value: + * + * .. code-block:: cpp + * + * ("", "") + * + * .. attention:: + * This action has been deprecated in favor of the :ref:`metadata ` action + */ +export interface _envoy_config_route_v3_RateLimit_Action_DynamicMetaData { + /** + * The key to use in the descriptor entry. + */ + 'descriptor_key'?: (string); + /** + * Metadata struct that defines the key and path to retrieve the string value. A match will + * only happen if the value in the dynamic metadata is of type string. + */ + 'metadata_key'?: (_envoy_type_metadata_v3_MetadataKey | null); + /** + * An optional value to use if *metadata_key* is empty. If not set and + * no value is present under the metadata_key then no descriptor is generated. + */ + 'default_value'?: (string); +} + +/** + * The following descriptor entry is appended when the + * :ref:`dynamic metadata ` contains a key value: + * + * .. code-block:: cpp + * + * ("", "") + * + * .. attention:: + * This action has been deprecated in favor of the :ref:`metadata ` action + */ +export interface _envoy_config_route_v3_RateLimit_Action_DynamicMetaData__Output { + /** + * The key to use in the descriptor entry. + */ + 'descriptor_key': (string); + /** + * Metadata struct that defines the key and path to retrieve the string value. A match will + * only happen if the value in the dynamic metadata is of type string. + */ + 'metadata_key': (_envoy_type_metadata_v3_MetadataKey__Output | null); + /** + * An optional value to use if *metadata_key* is empty. If not set and + * no value is present under the metadata_key then no descriptor is generated. + */ + 'default_value': (string); +} + +/** + * Fetches the override from the dynamic metadata. + */ +export interface _envoy_config_route_v3_RateLimit_Override_DynamicMetadata { + /** + * Metadata struct that defines the key and path to retrieve the struct value. + * The value must be a struct containing an integer "requests_per_unit" property + * and a "unit" property with a value parseable to :ref:`RateLimitUnit + * enum ` + */ + 'metadata_key'?: (_envoy_type_metadata_v3_MetadataKey | null); +} + +/** + * Fetches the override from the dynamic metadata. + */ +export interface _envoy_config_route_v3_RateLimit_Override_DynamicMetadata__Output { + /** + * Metadata struct that defines the key and path to retrieve the struct value. + * The value must be a struct containing an integer "requests_per_unit" property + * and a "unit" property with a value parseable to :ref:`RateLimitUnit + * enum ` + */ + 'metadata_key': (_envoy_type_metadata_v3_MetadataKey__Output | null); +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("generic_key", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_GenericKey { + /** + * The value to use in the descriptor entry. + */ + 'descriptor_value'?: (string); + /** + * An optional key to use in the descriptor entry. If not set it defaults + * to 'generic_key' as the descriptor key. + */ + 'descriptor_key'?: (string); +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("generic_key", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_GenericKey__Output { + /** + * The value to use in the descriptor entry. + */ + 'descriptor_value': (string); + /** + * An optional key to use in the descriptor entry. If not set it defaults + * to 'generic_key' as the descriptor key. + */ + 'descriptor_key': (string); +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("header_match", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_HeaderValueMatch { + /** + * The value to use in the descriptor entry. + */ + 'descriptor_value'?: (string); + /** + * If set to true, the action will append a descriptor entry when the + * request matches the headers. If set to false, the action will append a + * descriptor entry when the request does not match the headers. The + * default value is true. + */ + 'expect_match'?: (_google_protobuf_BoolValue | null); + /** + * Specifies a set of headers that the rate limit action should match + * on. The action will check the request’s headers against all the + * specified headers in the config. A match will happen if all the + * headers in the config are present in the request with the same values + * (or based on presence if the value field is not in the config). + */ + 'headers'?: (_envoy_config_route_v3_HeaderMatcher)[]; +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("header_match", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_HeaderValueMatch__Output { + /** + * The value to use in the descriptor entry. + */ + 'descriptor_value': (string); + /** + * If set to true, the action will append a descriptor entry when the + * request matches the headers. If set to false, the action will append a + * descriptor entry when the request does not match the headers. The + * default value is true. + */ + 'expect_match': (_google_protobuf_BoolValue__Output | null); + /** + * Specifies a set of headers that the rate limit action should match + * on. The action will check the request’s headers against all the + * specified headers in the config. A match will happen if all the + * headers in the config are present in the request with the same values + * (or based on presence if the value field is not in the config). + */ + 'headers': (_envoy_config_route_v3_HeaderMatcher__Output)[]; +} + +/** + * The following descriptor entry is appended when the metadata contains a key value: + * + * .. code-block:: cpp + * + * ("", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_MetaData { + /** + * The key to use in the descriptor entry. + */ + 'descriptor_key'?: (string); + /** + * Metadata struct that defines the key and path to retrieve the string value. A match will + * only happen if the value in the metadata is of type string. + */ + 'metadata_key'?: (_envoy_type_metadata_v3_MetadataKey | null); + /** + * An optional value to use if *metadata_key* is empty. If not set and + * no value is present under the metadata_key then no descriptor is generated. + */ + 'default_value'?: (string); + /** + * Source of metadata + */ + 'source'?: (_envoy_config_route_v3_RateLimit_Action_MetaData_Source | keyof typeof _envoy_config_route_v3_RateLimit_Action_MetaData_Source); +} + +/** + * The following descriptor entry is appended when the metadata contains a key value: + * + * .. code-block:: cpp + * + * ("", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_MetaData__Output { + /** + * The key to use in the descriptor entry. + */ + 'descriptor_key': (string); + /** + * Metadata struct that defines the key and path to retrieve the string value. A match will + * only happen if the value in the metadata is of type string. + */ + 'metadata_key': (_envoy_type_metadata_v3_MetadataKey__Output | null); + /** + * An optional value to use if *metadata_key* is empty. If not set and + * no value is present under the metadata_key then no descriptor is generated. + */ + 'default_value': (string); + /** + * Source of metadata + */ + 'source': (keyof typeof _envoy_config_route_v3_RateLimit_Action_MetaData_Source); +} + +export interface _envoy_config_route_v3_RateLimit_Override { + /** + * Limit override from dynamic metadata. + */ + 'dynamic_metadata'?: (_envoy_config_route_v3_RateLimit_Override_DynamicMetadata | null); + 'override_specifier'?: "dynamic_metadata"; +} + +export interface _envoy_config_route_v3_RateLimit_Override__Output { + /** + * Limit override from dynamic metadata. + */ + 'dynamic_metadata'?: (_envoy_config_route_v3_RateLimit_Override_DynamicMetadata__Output | null); + 'override_specifier': "dynamic_metadata"; +} + +/** + * The following descriptor entry is appended to the descriptor and is populated using the + * trusted address from :ref:`x-forwarded-for `: + * + * .. code-block:: cpp + * + * ("remote_address", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_RemoteAddress { +} + +/** + * The following descriptor entry is appended to the descriptor and is populated using the + * trusted address from :ref:`x-forwarded-for `: + * + * .. code-block:: cpp + * + * ("remote_address", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_RemoteAddress__Output { +} + +/** + * The following descriptor entry is appended when a header contains a key that matches the + * *header_name*: + * + * .. code-block:: cpp + * + * ("", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_RequestHeaders { + /** + * The header name to be queried from the request headers. The header’s + * value is used to populate the value of the descriptor entry for the + * descriptor_key. + */ + 'header_name'?: (string); + /** + * The key to use in the descriptor entry. + */ + 'descriptor_key'?: (string); + /** + * If set to true, Envoy skips the descriptor while calling rate limiting service + * when header is not present in the request. By default it skips calling the + * rate limiting service if this header is not present in the request. + */ + 'skip_if_absent'?: (boolean); +} + +/** + * The following descriptor entry is appended when a header contains a key that matches the + * *header_name*: + * + * .. code-block:: cpp + * + * ("", "") + */ +export interface _envoy_config_route_v3_RateLimit_Action_RequestHeaders__Output { + /** + * The header name to be queried from the request headers. The header’s + * value is used to populate the value of the descriptor entry for the + * descriptor_key. + */ + 'header_name': (string); + /** + * The key to use in the descriptor entry. + */ + 'descriptor_key': (string); + /** + * If set to true, Envoy skips the descriptor while calling rate limiting service + * when header is not present in the request. By default it skips calling the + * rate limiting service if this header is not present in the request. + */ + 'skip_if_absent': (boolean); +} + +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +export enum _envoy_config_route_v3_RateLimit_Action_MetaData_Source { + /** + * Query :ref:`dynamic metadata ` + */ + DYNAMIC = 0, + /** + * Query :ref:`route entry metadata ` + */ + ROUTE_ENTRY = 1, +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("source_cluster", "") + * + * is derived from the :option:`--service-cluster` option. + */ +export interface _envoy_config_route_v3_RateLimit_Action_SourceCluster { +} + +/** + * The following descriptor entry is appended to the descriptor: + * + * .. code-block:: cpp + * + * ("source_cluster", "") + * + * is derived from the :option:`--service-cluster` option. + */ +export interface _envoy_config_route_v3_RateLimit_Action_SourceCluster__Output { +} + +/** + * Global rate limiting :ref:`architecture overview `. + * Also applies to Local rate limiting :ref:`using descriptors `. + */ +export interface RateLimit { + /** + * Refers to the stage set in the filter. The rate limit configuration only + * applies to filters with the same stage number. The default stage number is + * 0. + * + * .. note:: + * + * The filter supports a range of 0 - 10 inclusively for stage numbers. + */ + 'stage'?: (_google_protobuf_UInt32Value | null); + /** + * The key to be set in runtime to disable this rate limit configuration. + */ + 'disable_key'?: (string); + /** + * A list of actions that are to be applied for this rate limit configuration. + * Order matters as the actions are processed sequentially and the descriptor + * is composed by appending descriptor entries in that sequence. If an action + * cannot append a descriptor entry, no descriptor is generated for the + * configuration. See :ref:`composing actions + * ` for additional documentation. + */ + 'actions'?: (_envoy_config_route_v3_RateLimit_Action)[]; + /** + * An optional limit override to be appended to the descriptor produced by this + * rate limit configuration. If the override value is invalid or cannot be resolved + * from metadata, no override is provided. See :ref:`rate limit override + * ` for more information. + */ + 'limit'?: (_envoy_config_route_v3_RateLimit_Override | null); +} + +/** + * Global rate limiting :ref:`architecture overview `. + * Also applies to Local rate limiting :ref:`using descriptors `. + */ +export interface RateLimit__Output { + /** + * Refers to the stage set in the filter. The rate limit configuration only + * applies to filters with the same stage number. The default stage number is + * 0. + * + * .. note:: + * + * The filter supports a range of 0 - 10 inclusively for stage numbers. + */ + 'stage': (_google_protobuf_UInt32Value__Output | null); + /** + * The key to be set in runtime to disable this rate limit configuration. + */ + 'disable_key': (string); + /** + * A list of actions that are to be applied for this rate limit configuration. + * Order matters as the actions are processed sequentially and the descriptor + * is composed by appending descriptor entries in that sequence. If an action + * cannot append a descriptor entry, no descriptor is generated for the + * configuration. See :ref:`composing actions + * ` for additional documentation. + */ + 'actions': (_envoy_config_route_v3_RateLimit_Action__Output)[]; + /** + * An optional limit override to be appended to the descriptor produced by this + * rate limit configuration. If the override value is invalid or cannot be resolved + * from metadata, no override is provided. See :ref:`rate limit override + * ` for more information. + */ + 'limit': (_envoy_config_route_v3_RateLimit_Override__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RedirectAction.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RedirectAction.ts new file mode 100644 index 000000000..e6d41fd7b --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RedirectAction.ts @@ -0,0 +1,222 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { RegexMatchAndSubstitute as _envoy_type_matcher_v3_RegexMatchAndSubstitute, RegexMatchAndSubstitute__Output as _envoy_type_matcher_v3_RegexMatchAndSubstitute__Output } from '../../../../envoy/type/matcher/v3/RegexMatchAndSubstitute'; + +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +export enum _envoy_config_route_v3_RedirectAction_RedirectResponseCode { + /** + * Moved Permanently HTTP Status Code - 301. + */ + MOVED_PERMANENTLY = 0, + /** + * Found HTTP Status Code - 302. + */ + FOUND = 1, + /** + * See Other HTTP Status Code - 303. + */ + SEE_OTHER = 2, + /** + * Temporary Redirect HTTP Status Code - 307. + */ + TEMPORARY_REDIRECT = 3, + /** + * Permanent Redirect HTTP Status Code - 308. + */ + PERMANENT_REDIRECT = 4, +} + +/** + * [#next-free-field: 10] + */ +export interface RedirectAction { + /** + * The host portion of the URL will be swapped with this value. + */ + 'host_redirect'?: (string); + /** + * The path portion of the URL will be swapped with this value. + * Please note that query string in path_redirect will override the + * request's query string and will not be stripped. + * + * For example, let's say we have the following routes: + * + * - match: { path: "/old-path-1" } + * redirect: { path_redirect: "/new-path-1" } + * - match: { path: "/old-path-2" } + * redirect: { path_redirect: "/new-path-2", strip-query: "true" } + * - match: { path: "/old-path-3" } + * redirect: { path_redirect: "/new-path-3?foo=1", strip_query: "true" } + * + * 1. if request uri is "/old-path-1?bar=1", users will be redirected to "/new-path-1?bar=1" + * 2. if request uri is "/old-path-2?bar=1", users will be redirected to "/new-path-2" + * 3. if request uri is "/old-path-3?bar=1", users will be redirected to "/new-path-3?foo=1" + */ + 'path_redirect'?: (string); + /** + * The HTTP status code to use in the redirect response. The default response + * code is MOVED_PERMANENTLY (301). + */ + 'response_code'?: (_envoy_config_route_v3_RedirectAction_RedirectResponseCode | keyof typeof _envoy_config_route_v3_RedirectAction_RedirectResponseCode); + /** + * The scheme portion of the URL will be swapped with "https". + */ + 'https_redirect'?: (boolean); + /** + * Indicates that during redirection, the matched prefix (or path) + * should be swapped with this value. This option allows redirect URLs be dynamically created + * based on the request. + * + * .. attention:: + * + * Pay attention to the use of trailing slashes as mentioned in + * :ref:`RouteAction's prefix_rewrite `. + */ + 'prefix_rewrite'?: (string); + /** + * Indicates that during redirection, the query portion of the URL will + * be removed. Default value is false. + */ + 'strip_query'?: (boolean); + /** + * The scheme portion of the URL will be swapped with this value. + */ + 'scheme_redirect'?: (string); + /** + * The port value of the URL will be swapped with this value. + */ + 'port_redirect'?: (number); + /** + * Indicates that during redirect, portions of the path that match the + * pattern should be rewritten, even allowing the substitution of capture + * groups from the pattern into the new path as specified by the rewrite + * substitution string. This is useful to allow application paths to be + * rewritten in a way that is aware of segments with variable content like + * identifiers. + * + * Examples using Google's `RE2 `_ engine: + * + * * The path pattern ``^/service/([^/]+)(/.*)$`` paired with a substitution + * string of ``\2/instance/\1`` would transform ``/service/foo/v1/api`` + * into ``/v1/api/instance/foo``. + * + * * The pattern ``one`` paired with a substitution string of ``two`` would + * transform ``/xxx/one/yyy/one/zzz`` into ``/xxx/two/yyy/two/zzz``. + * + * * The pattern ``^(.*?)one(.*)$`` paired with a substitution string of + * ``\1two\2`` would replace only the first occurrence of ``one``, + * transforming path ``/xxx/one/yyy/one/zzz`` into ``/xxx/two/yyy/one/zzz``. + * + * * The pattern ``(?i)/xxx/`` paired with a substitution string of ``/yyy/`` + * would do a case-insensitive match and transform path ``/aaa/XxX/bbb`` to + * ``/aaa/yyy/bbb``. + */ + 'regex_rewrite'?: (_envoy_type_matcher_v3_RegexMatchAndSubstitute | null); + /** + * When the scheme redirection take place, the following rules apply: + * 1. If the source URI scheme is `http` and the port is explicitly + * set to `:80`, the port will be removed after the redirection + * 2. If the source URI scheme is `https` and the port is explicitly + * set to `:443`, the port will be removed after the redirection + */ + 'scheme_rewrite_specifier'?: "https_redirect"|"scheme_redirect"; + 'path_rewrite_specifier'?: "path_redirect"|"prefix_rewrite"|"regex_rewrite"; +} + +/** + * [#next-free-field: 10] + */ +export interface RedirectAction__Output { + /** + * The host portion of the URL will be swapped with this value. + */ + 'host_redirect': (string); + /** + * The path portion of the URL will be swapped with this value. + * Please note that query string in path_redirect will override the + * request's query string and will not be stripped. + * + * For example, let's say we have the following routes: + * + * - match: { path: "/old-path-1" } + * redirect: { path_redirect: "/new-path-1" } + * - match: { path: "/old-path-2" } + * redirect: { path_redirect: "/new-path-2", strip-query: "true" } + * - match: { path: "/old-path-3" } + * redirect: { path_redirect: "/new-path-3?foo=1", strip_query: "true" } + * + * 1. if request uri is "/old-path-1?bar=1", users will be redirected to "/new-path-1?bar=1" + * 2. if request uri is "/old-path-2?bar=1", users will be redirected to "/new-path-2" + * 3. if request uri is "/old-path-3?bar=1", users will be redirected to "/new-path-3?foo=1" + */ + 'path_redirect'?: (string); + /** + * The HTTP status code to use in the redirect response. The default response + * code is MOVED_PERMANENTLY (301). + */ + 'response_code': (keyof typeof _envoy_config_route_v3_RedirectAction_RedirectResponseCode); + /** + * The scheme portion of the URL will be swapped with "https". + */ + 'https_redirect'?: (boolean); + /** + * Indicates that during redirection, the matched prefix (or path) + * should be swapped with this value. This option allows redirect URLs be dynamically created + * based on the request. + * + * .. attention:: + * + * Pay attention to the use of trailing slashes as mentioned in + * :ref:`RouteAction's prefix_rewrite `. + */ + 'prefix_rewrite'?: (string); + /** + * Indicates that during redirection, the query portion of the URL will + * be removed. Default value is false. + */ + 'strip_query': (boolean); + /** + * The scheme portion of the URL will be swapped with this value. + */ + 'scheme_redirect'?: (string); + /** + * The port value of the URL will be swapped with this value. + */ + 'port_redirect': (number); + /** + * Indicates that during redirect, portions of the path that match the + * pattern should be rewritten, even allowing the substitution of capture + * groups from the pattern into the new path as specified by the rewrite + * substitution string. This is useful to allow application paths to be + * rewritten in a way that is aware of segments with variable content like + * identifiers. + * + * Examples using Google's `RE2 `_ engine: + * + * * The path pattern ``^/service/([^/]+)(/.*)$`` paired with a substitution + * string of ``\2/instance/\1`` would transform ``/service/foo/v1/api`` + * into ``/v1/api/instance/foo``. + * + * * The pattern ``one`` paired with a substitution string of ``two`` would + * transform ``/xxx/one/yyy/one/zzz`` into ``/xxx/two/yyy/two/zzz``. + * + * * The pattern ``^(.*?)one(.*)$`` paired with a substitution string of + * ``\1two\2`` would replace only the first occurrence of ``one``, + * transforming path ``/xxx/one/yyy/one/zzz`` into ``/xxx/two/yyy/one/zzz``. + * + * * The pattern ``(?i)/xxx/`` paired with a substitution string of ``/yyy/`` + * would do a case-insensitive match and transform path ``/aaa/XxX/bbb`` to + * ``/aaa/yyy/bbb``. + */ + 'regex_rewrite'?: (_envoy_type_matcher_v3_RegexMatchAndSubstitute__Output | null); + /** + * When the scheme redirection take place, the following rules apply: + * 1. If the source URI scheme is `http` and the port is explicitly + * set to `:80`, the port will be removed after the redirection + * 2. If the source URI scheme is `https` and the port is explicitly + * set to `:443`, the port will be removed after the redirection + */ + 'scheme_rewrite_specifier': "https_redirect"|"scheme_redirect"; + 'path_rewrite_specifier': "path_redirect"|"prefix_rewrite"|"regex_rewrite"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RetryPolicy.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RetryPolicy.ts new file mode 100644 index 000000000..0d523b52e --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RetryPolicy.ts @@ -0,0 +1,461 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; +import type { HeaderMatcher as _envoy_config_route_v3_HeaderMatcher, HeaderMatcher__Output as _envoy_config_route_v3_HeaderMatcher__Output } from '../../../../envoy/config/route/v3/HeaderMatcher'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../envoy/config/core/v3/TypedExtensionConfig'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { Long } from '@grpc/proto-loader'; + +/** + * A retry back-off strategy that applies when the upstream server rate limits + * the request. + * + * Given this configuration: + * + * .. code-block:: yaml + * + * rate_limited_retry_back_off: + * reset_headers: + * - name: Retry-After + * format: SECONDS + * - name: X-RateLimit-Reset + * format: UNIX_TIMESTAMP + * max_interval: "300s" + * + * The following algorithm will apply: + * + * 1. If the response contains the header ``Retry-After`` its value must be on + * the form ``120`` (an integer that represents the number of seconds to + * wait before retrying). If so, this value is used as the back-off interval. + * 2. Otherwise, if the response contains the header ``X-RateLimit-Reset`` its + * value must be on the form ``1595320702`` (an integer that represents the + * point in time at which to retry, as a Unix timestamp in seconds). If so, + * the current time is subtracted from this value and the result is used as + * the back-off interval. + * 3. Otherwise, Envoy will use the default + * :ref:`exponential back-off ` + * strategy. + * + * No matter which format is used, if the resulting back-off interval exceeds + * ``max_interval`` it is discarded and the next header in ``reset_headers`` + * is tried. If a request timeout is configured for the route it will further + * limit how long the request will be allowed to run. + * + * To prevent many clients retrying at the same point in time jitter is added + * to the back-off interval, so the resulting interval is decided by taking: + * ``random(interval, interval * 1.5)``. + * + * .. attention:: + * + * Configuring ``rate_limited_retry_back_off`` will not by itself cause a request + * to be retried. You will still need to configure the right retry policy to match + * the responses from the upstream server. + */ +export interface _envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff { + /** + * Specifies the reset headers (like ``Retry-After`` or ``X-RateLimit-Reset``) + * to match against the response. Headers are tried in order, and matched case + * insensitive. The first header to be parsed successfully is used. If no headers + * match the default exponential back-off is used instead. + */ + 'reset_headers'?: (_envoy_config_route_v3_RetryPolicy_ResetHeader)[]; + /** + * Specifies the maximum back off interval that Envoy will allow. If a reset + * header contains an interval longer than this then it will be discarded and + * the next header will be tried. Defaults to 300 seconds. + */ + 'max_interval'?: (_google_protobuf_Duration | null); +} + +/** + * A retry back-off strategy that applies when the upstream server rate limits + * the request. + * + * Given this configuration: + * + * .. code-block:: yaml + * + * rate_limited_retry_back_off: + * reset_headers: + * - name: Retry-After + * format: SECONDS + * - name: X-RateLimit-Reset + * format: UNIX_TIMESTAMP + * max_interval: "300s" + * + * The following algorithm will apply: + * + * 1. If the response contains the header ``Retry-After`` its value must be on + * the form ``120`` (an integer that represents the number of seconds to + * wait before retrying). If so, this value is used as the back-off interval. + * 2. Otherwise, if the response contains the header ``X-RateLimit-Reset`` its + * value must be on the form ``1595320702`` (an integer that represents the + * point in time at which to retry, as a Unix timestamp in seconds). If so, + * the current time is subtracted from this value and the result is used as + * the back-off interval. + * 3. Otherwise, Envoy will use the default + * :ref:`exponential back-off ` + * strategy. + * + * No matter which format is used, if the resulting back-off interval exceeds + * ``max_interval`` it is discarded and the next header in ``reset_headers`` + * is tried. If a request timeout is configured for the route it will further + * limit how long the request will be allowed to run. + * + * To prevent many clients retrying at the same point in time jitter is added + * to the back-off interval, so the resulting interval is decided by taking: + * ``random(interval, interval * 1.5)``. + * + * .. attention:: + * + * Configuring ``rate_limited_retry_back_off`` will not by itself cause a request + * to be retried. You will still need to configure the right retry policy to match + * the responses from the upstream server. + */ +export interface _envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff__Output { + /** + * Specifies the reset headers (like ``Retry-After`` or ``X-RateLimit-Reset``) + * to match against the response. Headers are tried in order, and matched case + * insensitive. The first header to be parsed successfully is used. If no headers + * match the default exponential back-off is used instead. + */ + 'reset_headers': (_envoy_config_route_v3_RetryPolicy_ResetHeader__Output)[]; + /** + * Specifies the maximum back off interval that Envoy will allow. If a reset + * header contains an interval longer than this then it will be discarded and + * the next header will be tried. Defaults to 300 seconds. + */ + 'max_interval': (_google_protobuf_Duration__Output | null); +} + +export interface _envoy_config_route_v3_RetryPolicy_ResetHeader { + /** + * The name of the reset header. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. + */ + 'name'?: (string); + /** + * The format of the reset header. + */ + 'format'?: (_envoy_config_route_v3_RetryPolicy_ResetHeaderFormat | keyof typeof _envoy_config_route_v3_RetryPolicy_ResetHeaderFormat); +} + +export interface _envoy_config_route_v3_RetryPolicy_ResetHeader__Output { + /** + * The name of the reset header. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. + */ + 'name': (string); + /** + * The format of the reset header. + */ + 'format': (keyof typeof _envoy_config_route_v3_RetryPolicy_ResetHeaderFormat); +} + +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto + +export enum _envoy_config_route_v3_RetryPolicy_ResetHeaderFormat { + SECONDS = 0, + UNIX_TIMESTAMP = 1, +} + +export interface _envoy_config_route_v3_RetryPolicy_RetryBackOff { + /** + * Specifies the base interval between retries. This parameter is required and must be greater + * than zero. Values less than 1 ms are rounded up to 1 ms. + * See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion of Envoy's + * back-off algorithm. + */ + 'base_interval'?: (_google_protobuf_Duration | null); + /** + * Specifies the maximum interval between retries. This parameter is optional, but must be + * greater than or equal to the `base_interval` if set. The default is 10 times the + * `base_interval`. See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion + * of Envoy's back-off algorithm. + */ + 'max_interval'?: (_google_protobuf_Duration | null); +} + +export interface _envoy_config_route_v3_RetryPolicy_RetryBackOff__Output { + /** + * Specifies the base interval between retries. This parameter is required and must be greater + * than zero. Values less than 1 ms are rounded up to 1 ms. + * See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion of Envoy's + * back-off algorithm. + */ + 'base_interval': (_google_protobuf_Duration__Output | null); + /** + * Specifies the maximum interval between retries. This parameter is optional, but must be + * greater than or equal to the `base_interval` if set. The default is 10 times the + * `base_interval`. See :ref:`config_http_filters_router_x-envoy-max-retries` for a discussion + * of Envoy's back-off algorithm. + */ + 'max_interval': (_google_protobuf_Duration__Output | null); +} + +export interface _envoy_config_route_v3_RetryPolicy_RetryHostPredicate { + 'name'?: (string); + 'typed_config'?: (_google_protobuf_Any | null); + /** + * [#extension-category: envoy.retry_host_predicates] + */ + 'config_type'?: "typed_config"; +} + +export interface _envoy_config_route_v3_RetryPolicy_RetryHostPredicate__Output { + 'name': (string); + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * [#extension-category: envoy.retry_host_predicates] + */ + 'config_type': "typed_config"; +} + +export interface _envoy_config_route_v3_RetryPolicy_RetryPriority { + 'name'?: (string); + 'typed_config'?: (_google_protobuf_Any | null); + /** + * [#extension-category: envoy.retry_priorities] + */ + 'config_type'?: "typed_config"; +} + +export interface _envoy_config_route_v3_RetryPolicy_RetryPriority__Output { + 'name': (string); + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * [#extension-category: envoy.retry_priorities] + */ + 'config_type': "typed_config"; +} + +/** + * HTTP retry :ref:`architecture overview `. + * [#next-free-field: 14] + */ +export interface RetryPolicy { + /** + * Specifies the conditions under which retry takes place. These are the same + * conditions documented for :ref:`config_http_filters_router_x-envoy-retry-on` and + * :ref:`config_http_filters_router_x-envoy-retry-grpc-on`. + */ + 'retry_on'?: (string); + /** + * Specifies the allowed number of retries. This parameter is optional and + * defaults to 1. These are the same conditions documented for + * :ref:`config_http_filters_router_x-envoy-max-retries`. + */ + 'num_retries'?: (_google_protobuf_UInt32Value | null); + /** + * Specifies a non-zero upstream timeout per retry attempt (including the initial attempt). This + * parameter is optional. The same conditions documented for + * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms` apply. + * + * .. note:: + * + * If left unspecified, Envoy will use the global + * :ref:`route timeout ` for the request. + * Consequently, when using a :ref:`5xx ` based + * retry policy, a request that times out will not be retried as the total timeout budget + * would have been exhausted. + */ + 'per_try_timeout'?: (_google_protobuf_Duration | null); + /** + * Specifies an implementation of a RetryPriority which is used to determine the + * distribution of load across priorities used for retries. Refer to + * :ref:`retry plugin configuration ` for more details. + */ + 'retry_priority'?: (_envoy_config_route_v3_RetryPolicy_RetryPriority | null); + /** + * Specifies a collection of RetryHostPredicates that will be consulted when selecting a host + * for retries. If any of the predicates reject the host, host selection will be reattempted. + * Refer to :ref:`retry plugin configuration ` for more + * details. + */ + 'retry_host_predicate'?: (_envoy_config_route_v3_RetryPolicy_RetryHostPredicate)[]; + /** + * The maximum number of times host selection will be reattempted before giving up, at which + * point the host that was last selected will be routed to. If unspecified, this will default to + * retrying once. + */ + 'host_selection_retry_max_attempts'?: (number | string | Long); + /** + * HTTP status codes that should trigger a retry in addition to those specified by retry_on. + */ + 'retriable_status_codes'?: (number)[]; + /** + * Specifies parameters that control exponential retry back off. This parameter is optional, in which case the + * default base interval is 25 milliseconds or, if set, the current value of the + * `upstream.base_retry_backoff_ms` runtime parameter. The default maximum interval is 10 times + * the base interval. The documentation for :ref:`config_http_filters_router_x-envoy-max-retries` + * describes Envoy's back-off algorithm. + */ + 'retry_back_off'?: (_envoy_config_route_v3_RetryPolicy_RetryBackOff | null); + /** + * HTTP response headers that trigger a retry if present in the response. A retry will be + * triggered if any of the header matches match the upstream response headers. + * The field is only consulted if 'retriable-headers' retry policy is active. + */ + 'retriable_headers'?: (_envoy_config_route_v3_HeaderMatcher)[]; + /** + * HTTP headers which must be present in the request for retries to be attempted. + */ + 'retriable_request_headers'?: (_envoy_config_route_v3_HeaderMatcher)[]; + /** + * Specifies parameters that control a retry back-off strategy that is used + * when the request is rate limited by the upstream server. The server may + * return a response header like ``Retry-After`` or ``X-RateLimit-Reset`` to + * provide feedback to the client on how long to wait before retrying. If + * configured, this back-off strategy will be used instead of the + * default exponential back off strategy (configured using `retry_back_off`) + * whenever a response includes the matching headers. + */ + 'rate_limited_retry_back_off'?: (_envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff | null); + /** + * Retry options predicates that will be applied prior to retrying a request. These predicates + * allow customizing request behavior between retries. + * [#comment: add [#extension-category: envoy.retry_options_predicates] when there are built-in extensions] + */ + 'retry_options_predicates'?: (_envoy_config_core_v3_TypedExtensionConfig)[]; + /** + * Specifies an upstream idle timeout per retry attempt (including the initial attempt). This + * parameter is optional and if absent there is no per try idle timeout. The semantics of the per + * try idle timeout are similar to the + * :ref:`route idle timeout ` and + * :ref:`stream idle timeout + * ` + * both enforced by the HTTP connection manager. The difference is that this idle timeout + * is enforced by the router for each individual attempt and thus after all previous filters have + * run, as opposed to *before* all previous filters run for the other idle timeouts. This timeout + * is useful in cases in which total request timeout is bounded by a number of retries and a + * :ref:`per_try_timeout `, but + * there is a desire to ensure each try is making incremental progress. Note also that similar + * to :ref:`per_try_timeout `, + * this idle timeout does not start until after both the entire request has been received by the + * router *and* a connection pool connection has been obtained. Unlike + * :ref:`per_try_timeout `, + * the idle timer continues once the response starts streaming back to the downstream client. + * This ensures that response data continues to make progress without using one of the HTTP + * connection manager idle timeouts. + */ + 'per_try_idle_timeout'?: (_google_protobuf_Duration | null); +} + +/** + * HTTP retry :ref:`architecture overview `. + * [#next-free-field: 14] + */ +export interface RetryPolicy__Output { + /** + * Specifies the conditions under which retry takes place. These are the same + * conditions documented for :ref:`config_http_filters_router_x-envoy-retry-on` and + * :ref:`config_http_filters_router_x-envoy-retry-grpc-on`. + */ + 'retry_on': (string); + /** + * Specifies the allowed number of retries. This parameter is optional and + * defaults to 1. These are the same conditions documented for + * :ref:`config_http_filters_router_x-envoy-max-retries`. + */ + 'num_retries': (_google_protobuf_UInt32Value__Output | null); + /** + * Specifies a non-zero upstream timeout per retry attempt (including the initial attempt). This + * parameter is optional. The same conditions documented for + * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms` apply. + * + * .. note:: + * + * If left unspecified, Envoy will use the global + * :ref:`route timeout ` for the request. + * Consequently, when using a :ref:`5xx ` based + * retry policy, a request that times out will not be retried as the total timeout budget + * would have been exhausted. + */ + 'per_try_timeout': (_google_protobuf_Duration__Output | null); + /** + * Specifies an implementation of a RetryPriority which is used to determine the + * distribution of load across priorities used for retries. Refer to + * :ref:`retry plugin configuration ` for more details. + */ + 'retry_priority': (_envoy_config_route_v3_RetryPolicy_RetryPriority__Output | null); + /** + * Specifies a collection of RetryHostPredicates that will be consulted when selecting a host + * for retries. If any of the predicates reject the host, host selection will be reattempted. + * Refer to :ref:`retry plugin configuration ` for more + * details. + */ + 'retry_host_predicate': (_envoy_config_route_v3_RetryPolicy_RetryHostPredicate__Output)[]; + /** + * The maximum number of times host selection will be reattempted before giving up, at which + * point the host that was last selected will be routed to. If unspecified, this will default to + * retrying once. + */ + 'host_selection_retry_max_attempts': (string); + /** + * HTTP status codes that should trigger a retry in addition to those specified by retry_on. + */ + 'retriable_status_codes': (number)[]; + /** + * Specifies parameters that control exponential retry back off. This parameter is optional, in which case the + * default base interval is 25 milliseconds or, if set, the current value of the + * `upstream.base_retry_backoff_ms` runtime parameter. The default maximum interval is 10 times + * the base interval. The documentation for :ref:`config_http_filters_router_x-envoy-max-retries` + * describes Envoy's back-off algorithm. + */ + 'retry_back_off': (_envoy_config_route_v3_RetryPolicy_RetryBackOff__Output | null); + /** + * HTTP response headers that trigger a retry if present in the response. A retry will be + * triggered if any of the header matches match the upstream response headers. + * The field is only consulted if 'retriable-headers' retry policy is active. + */ + 'retriable_headers': (_envoy_config_route_v3_HeaderMatcher__Output)[]; + /** + * HTTP headers which must be present in the request for retries to be attempted. + */ + 'retriable_request_headers': (_envoy_config_route_v3_HeaderMatcher__Output)[]; + /** + * Specifies parameters that control a retry back-off strategy that is used + * when the request is rate limited by the upstream server. The server may + * return a response header like ``Retry-After`` or ``X-RateLimit-Reset`` to + * provide feedback to the client on how long to wait before retrying. If + * configured, this back-off strategy will be used instead of the + * default exponential back off strategy (configured using `retry_back_off`) + * whenever a response includes the matching headers. + */ + 'rate_limited_retry_back_off': (_envoy_config_route_v3_RetryPolicy_RateLimitedRetryBackOff__Output | null); + /** + * Retry options predicates that will be applied prior to retrying a request. These predicates + * allow customizing request behavior between retries. + * [#comment: add [#extension-category: envoy.retry_options_predicates] when there are built-in extensions] + */ + 'retry_options_predicates': (_envoy_config_core_v3_TypedExtensionConfig__Output)[]; + /** + * Specifies an upstream idle timeout per retry attempt (including the initial attempt). This + * parameter is optional and if absent there is no per try idle timeout. The semantics of the per + * try idle timeout are similar to the + * :ref:`route idle timeout ` and + * :ref:`stream idle timeout + * ` + * both enforced by the HTTP connection manager. The difference is that this idle timeout + * is enforced by the router for each individual attempt and thus after all previous filters have + * run, as opposed to *before* all previous filters run for the other idle timeouts. This timeout + * is useful in cases in which total request timeout is bounded by a number of retries and a + * :ref:`per_try_timeout `, but + * there is a desire to ensure each try is making incremental progress. Note also that similar + * to :ref:`per_try_timeout `, + * this idle timeout does not start until after both the entire request has been received by the + * router *and* a connection pool connection has been obtained. Unlike + * :ref:`per_try_timeout `, + * the idle timer continues once the response starts streaming back to the downstream client. + * This ensures that response data continues to make progress without using one of the HTTP + * connection manager idle timeouts. + */ + 'per_try_idle_timeout': (_google_protobuf_Duration__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/Route.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Route.ts similarity index 50% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/Route.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/Route.ts index 86cb4ac3d..d48b554d0 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/Route.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Route.ts @@ -1,17 +1,17 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -import type { RouteMatch as _envoy_api_v2_route_RouteMatch, RouteMatch__Output as _envoy_api_v2_route_RouteMatch__Output } from '../../../../envoy/api/v2/route/RouteMatch'; -import type { RouteAction as _envoy_api_v2_route_RouteAction, RouteAction__Output as _envoy_api_v2_route_RouteAction__Output } from '../../../../envoy/api/v2/route/RouteAction'; -import type { RedirectAction as _envoy_api_v2_route_RedirectAction, RedirectAction__Output as _envoy_api_v2_route_RedirectAction__Output } from '../../../../envoy/api/v2/route/RedirectAction'; -import type { Metadata as _envoy_api_v2_core_Metadata, Metadata__Output as _envoy_api_v2_core_Metadata__Output } from '../../../../envoy/api/v2/core/Metadata'; -import type { Decorator as _envoy_api_v2_route_Decorator, Decorator__Output as _envoy_api_v2_route_Decorator__Output } from '../../../../envoy/api/v2/route/Decorator'; -import type { DirectResponseAction as _envoy_api_v2_route_DirectResponseAction, DirectResponseAction__Output as _envoy_api_v2_route_DirectResponseAction__Output } from '../../../../envoy/api/v2/route/DirectResponseAction'; -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { HeaderValueOption as _envoy_api_v2_core_HeaderValueOption, HeaderValueOption__Output as _envoy_api_v2_core_HeaderValueOption__Output } from '../../../../envoy/api/v2/core/HeaderValueOption'; +import type { RouteMatch as _envoy_config_route_v3_RouteMatch, RouteMatch__Output as _envoy_config_route_v3_RouteMatch__Output } from '../../../../envoy/config/route/v3/RouteMatch'; +import type { RouteAction as _envoy_config_route_v3_RouteAction, RouteAction__Output as _envoy_config_route_v3_RouteAction__Output } from '../../../../envoy/config/route/v3/RouteAction'; +import type { RedirectAction as _envoy_config_route_v3_RedirectAction, RedirectAction__Output as _envoy_config_route_v3_RedirectAction__Output } from '../../../../envoy/config/route/v3/RedirectAction'; +import type { Metadata as _envoy_config_core_v3_Metadata, Metadata__Output as _envoy_config_core_v3_Metadata__Output } from '../../../../envoy/config/core/v3/Metadata'; +import type { Decorator as _envoy_config_route_v3_Decorator, Decorator__Output as _envoy_config_route_v3_Decorator__Output } from '../../../../envoy/config/route/v3/Decorator'; +import type { DirectResponseAction as _envoy_config_route_v3_DirectResponseAction, DirectResponseAction__Output as _envoy_config_route_v3_DirectResponseAction__Output } from '../../../../envoy/config/route/v3/DirectResponseAction'; +import type { HeaderValueOption as _envoy_config_core_v3_HeaderValueOption, HeaderValueOption__Output as _envoy_config_core_v3_HeaderValueOption__Output } from '../../../../envoy/config/core/v3/HeaderValueOption'; import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; -import type { Tracing as _envoy_api_v2_route_Tracing, Tracing__Output as _envoy_api_v2_route_Tracing__Output } from '../../../../envoy/api/v2/route/Tracing'; +import type { Tracing as _envoy_config_route_v3_Tracing, Tracing__Output as _envoy_config_route_v3_Tracing__Output } from '../../../../envoy/config/route/v3/Tracing'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -import type { FilterAction as _envoy_api_v2_route_FilterAction, FilterAction__Output as _envoy_api_v2_route_FilterAction__Output } from '../../../../envoy/api/v2/route/FilterAction'; +import type { FilterAction as _envoy_config_route_v3_FilterAction, FilterAction__Output as _envoy_config_route_v3_FilterAction__Output } from '../../../../envoy/config/route/v3/FilterAction'; +import type { NonForwardingAction as _envoy_config_route_v3_NonForwardingAction, NonForwardingAction__Output as _envoy_config_route_v3_NonForwardingAction__Output } from '../../../../envoy/config/route/v3/NonForwardingAction'; /** * A route is both a specification of how to match a request as well as an indication of what to do @@ -20,22 +20,22 @@ import type { FilterAction as _envoy_api_v2_route_FilterAction, FilterAction__Ou * .. attention:: * * Envoy supports routing on HTTP method via :ref:`header matching - * `. - * [#next-free-field: 18] + * `. + * [#next-free-field: 19] */ export interface Route { /** * Route matching parameters. */ - 'match'?: (_envoy_api_v2_route_RouteMatch); + 'match'?: (_envoy_config_route_v3_RouteMatch | null); /** * Route request to some upstream cluster. */ - 'route'?: (_envoy_api_v2_route_RouteAction); + 'route'?: (_envoy_config_route_v3_RouteAction | null); /** * Return a redirect. */ - 'redirect'?: (_envoy_api_v2_route_RedirectAction); + 'redirect'?: (_envoy_config_route_v3_RedirectAction | null); /** * The Metadata field can be used to provide additional information * about the route. It can be used for configuration, stats, and logging. @@ -43,41 +43,33 @@ export interface Route { * For instance, if the metadata is intended for the Router filter, * the filter name should be specified as *envoy.filters.http.router*. */ - 'metadata'?: (_envoy_api_v2_core_Metadata); + 'metadata'?: (_envoy_config_core_v3_Metadata | null); /** * Decorator for the matched route. */ - 'decorator'?: (_envoy_api_v2_route_Decorator); + 'decorator'?: (_envoy_config_route_v3_Decorator | null); /** * Return an arbitrary HTTP response directly, without proxying. */ - 'direct_response'?: (_envoy_api_v2_route_DirectResponseAction); - /** - * The per_filter_config field can be used to provide route-specific - * configurations for filters. The key should match the filter name, such as - * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter - * specific; see the :ref:`HTTP filter documentation ` for - * if and how it is utilized. - */ - 'per_filter_config'?: ({[key: string]: _google_protobuf_Struct}); + 'direct_response'?: (_envoy_config_route_v3_DirectResponseAction | null); /** * Specifies a set of headers that will be added to requests matching this * route. Headers specified at this level are applied before headers from the - * enclosing :ref:`envoy_api_msg_route.VirtualHost` and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including details on + * enclosing :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'request_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Specifies a set of headers that will be added to responses to requests * matching this route. Headers specified at this level are applied before - * headers from the enclosing :ref:`envoy_api_msg_route.VirtualHost` and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including + * headers from the enclosing :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including * details on header value syntax, see the documentation on * :ref:`custom request headers `. */ - 'response_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'response_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Specifies a list of HTTP headers that should be removed from each response * to requests matching this route. @@ -94,6 +86,9 @@ export interface Route { * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter * specific; see the :ref:`HTTP filter documentation ` for * if and how it is utilized. + * [#comment: An entry's value may be wrapped in a + * :ref:`FilterConfig` + * message to specify additional options.] */ 'typed_per_filter_config'?: ({[key: string]: _google_protobuf_Any}); /** @@ -104,20 +99,29 @@ export interface Route { * Presence of the object defines whether the connection manager's tracing configuration * is overridden by this route specific instance. */ - 'tracing'?: (_envoy_api_v2_route_Tracing); + 'tracing'?: (_envoy_config_route_v3_Tracing | null); /** * The maximum bytes which will be buffered for retries and shadowing. * If set, the bytes actually buffered will be the minimum value of this and the * listener per_connection_buffer_limit_bytes. */ - 'per_request_buffer_limit_bytes'?: (_google_protobuf_UInt32Value); + 'per_request_buffer_limit_bytes'?: (_google_protobuf_UInt32Value | null); + /** + * [#not-implemented-hide:] + * A filter-defined action (e.g., it could dynamically generate the RouteAction). + * [#comment: TODO(samflattery): Remove cleanup in route_fuzz_test.cc when + * implemented] + */ + 'filter_action'?: (_envoy_config_route_v3_FilterAction | null); /** * [#not-implemented-hide:] - * If true, a filter will define the action (e.g., it could dynamically generate the - * RouteAction). + * An action used when the route will generate a response directly, + * without forwarding to an upstream host. This will be used in non-proxy + * xDS clients like the gRPC server. It could also be used in the future + * in Envoy for a filter that directly generates responses for requests. */ - 'filter_action'?: (_envoy_api_v2_route_FilterAction); - 'action'?: "route"|"redirect"|"direct_response"|"filter_action"; + 'non_forwarding_action'?: (_envoy_config_route_v3_NonForwardingAction | null); + 'action'?: "route"|"redirect"|"direct_response"|"filter_action"|"non_forwarding_action"; } /** @@ -127,22 +131,22 @@ export interface Route { * .. attention:: * * Envoy supports routing on HTTP method via :ref:`header matching - * `. - * [#next-free-field: 18] + * `. + * [#next-free-field: 19] */ export interface Route__Output { /** * Route matching parameters. */ - 'match'?: (_envoy_api_v2_route_RouteMatch__Output); + 'match': (_envoy_config_route_v3_RouteMatch__Output | null); /** * Route request to some upstream cluster. */ - 'route'?: (_envoy_api_v2_route_RouteAction__Output); + 'route'?: (_envoy_config_route_v3_RouteAction__Output | null); /** * Return a redirect. */ - 'redirect'?: (_envoy_api_v2_route_RedirectAction__Output); + 'redirect'?: (_envoy_config_route_v3_RedirectAction__Output | null); /** * The Metadata field can be used to provide additional information * about the route. It can be used for configuration, stats, and logging. @@ -150,41 +154,33 @@ export interface Route__Output { * For instance, if the metadata is intended for the Router filter, * the filter name should be specified as *envoy.filters.http.router*. */ - 'metadata'?: (_envoy_api_v2_core_Metadata__Output); + 'metadata': (_envoy_config_core_v3_Metadata__Output | null); /** * Decorator for the matched route. */ - 'decorator'?: (_envoy_api_v2_route_Decorator__Output); + 'decorator': (_envoy_config_route_v3_Decorator__Output | null); /** * Return an arbitrary HTTP response directly, without proxying. */ - 'direct_response'?: (_envoy_api_v2_route_DirectResponseAction__Output); - /** - * The per_filter_config field can be used to provide route-specific - * configurations for filters. The key should match the filter name, such as - * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter - * specific; see the :ref:`HTTP filter documentation ` for - * if and how it is utilized. - */ - 'per_filter_config'?: ({[key: string]: _google_protobuf_Struct__Output}); + 'direct_response'?: (_envoy_config_route_v3_DirectResponseAction__Output | null); /** * Specifies a set of headers that will be added to requests matching this * route. Headers specified at this level are applied before headers from the - * enclosing :ref:`envoy_api_msg_route.VirtualHost` and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including details on + * enclosing :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'request_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Specifies a set of headers that will be added to responses to requests * matching this route. Headers specified at this level are applied before - * headers from the enclosing :ref:`envoy_api_msg_route.VirtualHost` and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including + * headers from the enclosing :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including * details on header value syntax, see the documentation on * :ref:`custom request headers `. */ - 'response_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'response_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Specifies a list of HTTP headers that should be removed from each response * to requests matching this route. @@ -201,8 +197,11 @@ export interface Route__Output { * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter * specific; see the :ref:`HTTP filter documentation ` for * if and how it is utilized. + * [#comment: An entry's value may be wrapped in a + * :ref:`FilterConfig` + * message to specify additional options.] */ - 'typed_per_filter_config'?: ({[key: string]: _google_protobuf_Any__Output}); + 'typed_per_filter_config': ({[key: string]: _google_protobuf_Any__Output}); /** * Name for the route. */ @@ -211,18 +210,27 @@ export interface Route__Output { * Presence of the object defines whether the connection manager's tracing configuration * is overridden by this route specific instance. */ - 'tracing'?: (_envoy_api_v2_route_Tracing__Output); + 'tracing': (_envoy_config_route_v3_Tracing__Output | null); /** * The maximum bytes which will be buffered for retries and shadowing. * If set, the bytes actually buffered will be the minimum value of this and the * listener per_connection_buffer_limit_bytes. */ - 'per_request_buffer_limit_bytes'?: (_google_protobuf_UInt32Value__Output); + 'per_request_buffer_limit_bytes': (_google_protobuf_UInt32Value__Output | null); + /** + * [#not-implemented-hide:] + * A filter-defined action (e.g., it could dynamically generate the RouteAction). + * [#comment: TODO(samflattery): Remove cleanup in route_fuzz_test.cc when + * implemented] + */ + 'filter_action'?: (_envoy_config_route_v3_FilterAction__Output | null); /** * [#not-implemented-hide:] - * If true, a filter will define the action (e.g., it could dynamically generate the - * RouteAction). + * An action used when the route will generate a response directly, + * without forwarding to an upstream host. This will be used in non-proxy + * xDS clients like the gRPC server. It could also be used in the future + * in Envoy for a filter that directly generates responses for requests. */ - 'filter_action'?: (_envoy_api_v2_route_FilterAction__Output); - 'action': "route"|"redirect"|"direct_response"|"filter_action"; + 'non_forwarding_action'?: (_envoy_config_route_v3_NonForwardingAction__Output | null); + 'action': "route"|"redirect"|"direct_response"|"filter_action"|"non_forwarding_action"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RouteAction.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteAction.ts similarity index 59% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/RouteAction.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteAction.ts index 5f07bae9b..43bd51723 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RouteAction.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteAction.ts @@ -1,22 +1,24 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -import type { WeightedCluster as _envoy_api_v2_route_WeightedCluster, WeightedCluster__Output as _envoy_api_v2_route_WeightedCluster__Output } from '../../../../envoy/api/v2/route/WeightedCluster'; -import type { Metadata as _envoy_api_v2_core_Metadata, Metadata__Output as _envoy_api_v2_core_Metadata__Output } from '../../../../envoy/api/v2/core/Metadata'; +import type { WeightedCluster as _envoy_config_route_v3_WeightedCluster, WeightedCluster__Output as _envoy_config_route_v3_WeightedCluster__Output } from '../../../../envoy/config/route/v3/WeightedCluster'; +import type { Metadata as _envoy_config_core_v3_Metadata, Metadata__Output as _envoy_config_core_v3_Metadata__Output } from '../../../../envoy/config/core/v3/Metadata'; import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; -import type { RetryPolicy as _envoy_api_v2_route_RetryPolicy, RetryPolicy__Output as _envoy_api_v2_route_RetryPolicy__Output } from '../../../../envoy/api/v2/route/RetryPolicy'; -import type { RoutingPriority as _envoy_api_v2_core_RoutingPriority } from '../../../../envoy/api/v2/core/RoutingPriority'; -import type { RateLimit as _envoy_api_v2_route_RateLimit, RateLimit__Output as _envoy_api_v2_route_RateLimit__Output } from '../../../../envoy/api/v2/route/RateLimit'; -import type { CorsPolicy as _envoy_api_v2_route_CorsPolicy, CorsPolicy__Output as _envoy_api_v2_route_CorsPolicy__Output } from '../../../../envoy/api/v2/route/CorsPolicy'; -import type { HedgePolicy as _envoy_api_v2_route_HedgePolicy, HedgePolicy__Output as _envoy_api_v2_route_HedgePolicy__Output } from '../../../../envoy/api/v2/route/HedgePolicy'; +import type { RetryPolicy as _envoy_config_route_v3_RetryPolicy, RetryPolicy__Output as _envoy_config_route_v3_RetryPolicy__Output } from '../../../../envoy/config/route/v3/RetryPolicy'; +import type { RoutingPriority as _envoy_config_core_v3_RoutingPriority } from '../../../../envoy/config/core/v3/RoutingPriority'; +import type { RateLimit as _envoy_config_route_v3_RateLimit, RateLimit__Output as _envoy_config_route_v3_RateLimit__Output } from '../../../../envoy/config/route/v3/RateLimit'; +import type { CorsPolicy as _envoy_config_route_v3_CorsPolicy, CorsPolicy__Output as _envoy_config_route_v3_CorsPolicy__Output } from '../../../../envoy/config/route/v3/CorsPolicy'; +import type { HedgePolicy as _envoy_config_route_v3_HedgePolicy, HedgePolicy__Output as _envoy_config_route_v3_HedgePolicy__Output } from '../../../../envoy/config/route/v3/HedgePolicy'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -import type { RegexMatchAndSubstitute as _envoy_type_matcher_RegexMatchAndSubstitute, RegexMatchAndSubstitute__Output as _envoy_type_matcher_RegexMatchAndSubstitute__Output } from '../../../../envoy/type/matcher/RegexMatchAndSubstitute'; +import type { RegexMatchAndSubstitute as _envoy_type_matcher_v3_RegexMatchAndSubstitute, RegexMatchAndSubstitute__Output as _envoy_type_matcher_v3_RegexMatchAndSubstitute__Output } from '../../../../envoy/type/matcher/v3/RegexMatchAndSubstitute'; import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; -import type { RuntimeFractionalPercent as _envoy_api_v2_core_RuntimeFractionalPercent, RuntimeFractionalPercent__Output as _envoy_api_v2_core_RuntimeFractionalPercent__Output } from '../../../../envoy/api/v2/core/RuntimeFractionalPercent'; +import type { InternalRedirectPolicy as _envoy_config_route_v3_InternalRedirectPolicy, InternalRedirectPolicy__Output as _envoy_config_route_v3_InternalRedirectPolicy__Output } from '../../../../envoy/config/route/v3/InternalRedirectPolicy'; +import type { RuntimeFractionalPercent as _envoy_config_core_v3_RuntimeFractionalPercent, RuntimeFractionalPercent__Output as _envoy_config_core_v3_RuntimeFractionalPercent__Output } from '../../../../envoy/config/core/v3/RuntimeFractionalPercent'; +import type { ProxyProtocolConfig as _envoy_config_core_v3_ProxyProtocolConfig, ProxyProtocolConfig__Output as _envoy_config_core_v3_ProxyProtocolConfig__Output } from '../../../../envoy/config/core/v3/ProxyProtocolConfig'; -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -export enum _envoy_api_v2_route_RouteAction_ClusterNotFoundResponseCode { +export enum _envoy_config_route_v3_RouteAction_ClusterNotFoundResponseCode { /** * HTTP status code - 503 Service Unavailable. */ @@ -27,14 +29,44 @@ export enum _envoy_api_v2_route_RouteAction_ClusterNotFoundResponseCode { NOT_FOUND = 1, } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties { +/** + * Configuration for sending data upstream as a raw data payload. This is used for + * CONNECT or POST requests, when forwarding request payload as raw TCP. + */ +export interface _envoy_config_route_v3_RouteAction_UpgradeConfig_ConnectConfig { + /** + * If present, the proxy protocol header will be prepended to the CONNECT payload sent upstream. + */ + 'proxy_protocol_config'?: (_envoy_config_core_v3_ProxyProtocolConfig | null); + /** + * If set, the route will also allow forwarding POST payload as raw TCP. + */ + 'allow_post'?: (boolean); +} + +/** + * Configuration for sending data upstream as a raw data payload. This is used for + * CONNECT or POST requests, when forwarding request payload as raw TCP. + */ +export interface _envoy_config_route_v3_RouteAction_UpgradeConfig_ConnectConfig__Output { + /** + * If present, the proxy protocol header will be prepended to the CONNECT payload sent upstream. + */ + 'proxy_protocol_config': (_envoy_config_core_v3_ProxyProtocolConfig__Output | null); + /** + * If set, the route will also allow forwarding POST payload as raw TCP. + */ + 'allow_post': (boolean); +} + +export interface _envoy_config_route_v3_RouteAction_HashPolicy_ConnectionProperties { /** * Hash on source IP address. */ 'source_ip'?: (boolean); } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties__Output { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_ConnectionProperties__Output { /** * Hash on source IP address. */ @@ -57,7 +89,7 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties * streams on the same connection will independently receive the same * cookie, even if they arrive at the Envoy simultaneously. */ -export interface _envoy_api_v2_route_RouteAction_HashPolicy_Cookie { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_Cookie { /** * The name of the cookie that will be used to obtain the hash key. If the * cookie is not present and ttl below is not set, no hash will be @@ -69,7 +101,7 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_Cookie { * not present. If the TTL is present and zero, the generated cookie will * be a session cookie. */ - 'ttl'?: (_google_protobuf_Duration); + 'ttl'?: (_google_protobuf_Duration | null); /** * The name of the path for the cookie. If no path is specified here, no path * will be set for the cookie. @@ -93,7 +125,7 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_Cookie { * streams on the same connection will independently receive the same * cookie, even if they arrive at the Envoy simultaneously. */ -export interface _envoy_api_v2_route_RouteAction_HashPolicy_Cookie__Output { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_Cookie__Output { /** * The name of the cookie that will be used to obtain the hash key. If the * cookie is not present and ttl below is not set, no hash will be @@ -105,7 +137,7 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_Cookie__Output { * not present. If the TTL is present and zero, the generated cookie will * be a session cookie. */ - 'ttl'?: (_google_protobuf_Duration__Output); + 'ttl': (_google_protobuf_Duration__Output | null); /** * The name of the path for the cookie. If no path is specified here, no path * will be set for the cookie. @@ -113,7 +145,7 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_Cookie__Output { 'path': (string); } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_FilterState { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_FilterState { /** * The name of the Object in the per-request filterState, which is an * Envoy::Http::Hashable object. If there is no data associated with the key, @@ -122,7 +154,7 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_FilterState { 'key'?: (string); } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_FilterState__Output { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_FilterState__Output { /** * The name of the Object in the per-request filterState, which is an * Envoy::Http::Hashable object. If there is no data associated with the key, @@ -136,27 +168,27 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_FilterState__Output * `. * [#next-free-field: 7] */ -export interface _envoy_api_v2_route_RouteAction_HashPolicy { +export interface _envoy_config_route_v3_RouteAction_HashPolicy { /** * Header hash policy. */ - 'header'?: (_envoy_api_v2_route_RouteAction_HashPolicy_Header); + 'header'?: (_envoy_config_route_v3_RouteAction_HashPolicy_Header | null); /** * Cookie hash policy. */ - 'cookie'?: (_envoy_api_v2_route_RouteAction_HashPolicy_Cookie); + 'cookie'?: (_envoy_config_route_v3_RouteAction_HashPolicy_Cookie | null); /** * Connection properties hash policy. */ - 'connection_properties'?: (_envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties); + 'connection_properties'?: (_envoy_config_route_v3_RouteAction_HashPolicy_ConnectionProperties | null); /** * Query parameter hash policy. */ - 'query_parameter'?: (_envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter); + 'query_parameter'?: (_envoy_config_route_v3_RouteAction_HashPolicy_QueryParameter | null); /** * Filter state hash policy. */ - 'filter_state'?: (_envoy_api_v2_route_RouteAction_HashPolicy_FilterState); + 'filter_state'?: (_envoy_config_route_v3_RouteAction_HashPolicy_FilterState | null); /** * The flag that short-circuits the hash computing. This field provides a * 'fallback' style of configuration: "if a terminal policy doesn't work, @@ -187,27 +219,27 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy { * `. * [#next-free-field: 7] */ -export interface _envoy_api_v2_route_RouteAction_HashPolicy__Output { +export interface _envoy_config_route_v3_RouteAction_HashPolicy__Output { /** * Header hash policy. */ - 'header'?: (_envoy_api_v2_route_RouteAction_HashPolicy_Header__Output); + 'header'?: (_envoy_config_route_v3_RouteAction_HashPolicy_Header__Output | null); /** * Cookie hash policy. */ - 'cookie'?: (_envoy_api_v2_route_RouteAction_HashPolicy_Cookie__Output); + 'cookie'?: (_envoy_config_route_v3_RouteAction_HashPolicy_Cookie__Output | null); /** * Connection properties hash policy. */ - 'connection_properties'?: (_envoy_api_v2_route_RouteAction_HashPolicy_ConnectionProperties__Output); + 'connection_properties'?: (_envoy_config_route_v3_RouteAction_HashPolicy_ConnectionProperties__Output | null); /** * Query parameter hash policy. */ - 'query_parameter'?: (_envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter__Output); + 'query_parameter'?: (_envoy_config_route_v3_RouteAction_HashPolicy_QueryParameter__Output | null); /** * Filter state hash policy. */ - 'filter_state'?: (_envoy_api_v2_route_RouteAction_HashPolicy_FilterState__Output); + 'filter_state'?: (_envoy_config_route_v3_RouteAction_HashPolicy_FilterState__Output | null); /** * The flag that short-circuits the hash computing. This field provides a * 'fallback' style of configuration: "if a terminal policy doesn't work, @@ -233,33 +265,104 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy__Output { 'policy_specifier': "header"|"cookie"|"connection_properties"|"query_parameter"|"filter_state"; } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_Header { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_Header { /** * The name of the request header that will be used to obtain the hash * key. If the request header is not present, no hash will be produced. */ 'header_name'?: (string); + /** + * If specified, the request header value will be rewritten and used + * to produce the hash key. + */ + 'regex_rewrite'?: (_envoy_type_matcher_v3_RegexMatchAndSubstitute | null); } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_Header__Output { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_Header__Output { /** * The name of the request header that will be used to obtain the hash * key. If the request header is not present, no hash will be produced. */ 'header_name': (string); + /** + * If specified, the request header value will be rewritten and used + * to produce the hash key. + */ + 'regex_rewrite': (_envoy_type_matcher_v3_RegexMatchAndSubstitute__Output | null); } -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto /** * Configures :ref:`internal redirect ` behavior. + * [#next-major-version: remove this definition - it's defined in the InternalRedirectPolicy message.] */ -export enum _envoy_api_v2_route_RouteAction_InternalRedirectAction { +export enum _envoy_config_route_v3_RouteAction_InternalRedirectAction { PASS_THROUGH_INTERNAL_REDIRECT = 0, HANDLE_INTERNAL_REDIRECT = 1, } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter { +export interface _envoy_config_route_v3_RouteAction_MaxStreamDuration { + /** + * Specifies the maximum duration allowed for streams on the route. If not specified, the value + * from the :ref:`max_stream_duration + * ` field in + * :ref:`HttpConnectionManager.common_http_protocol_options + * ` + * is used. If this field is set explicitly to zero, any + * HttpConnectionManager max_stream_duration timeout will be disabled for + * this route. + */ + 'max_stream_duration'?: (_google_protobuf_Duration | null); + /** + * If present, and the request contains a `grpc-timeout header + * `_, use that value as the + * *max_stream_duration*, but limit the applied timeout to the maximum value specified here. + * If set to 0, the `grpc-timeout` header is used without modification. + */ + 'grpc_timeout_header_max'?: (_google_protobuf_Duration | null); + /** + * If present, Envoy will adjust the timeout provided by the `grpc-timeout` header by + * subtracting the provided duration from the header. This is useful for allowing Envoy to set + * its global timeout to be less than that of the deadline imposed by the calling client, which + * makes it more likely that Envoy will handle the timeout instead of having the call canceled + * by the client. If, after applying the offset, the resulting timeout is zero or negative, + * the stream will timeout immediately. + */ + 'grpc_timeout_header_offset'?: (_google_protobuf_Duration | null); +} + +export interface _envoy_config_route_v3_RouteAction_MaxStreamDuration__Output { + /** + * Specifies the maximum duration allowed for streams on the route. If not specified, the value + * from the :ref:`max_stream_duration + * ` field in + * :ref:`HttpConnectionManager.common_http_protocol_options + * ` + * is used. If this field is set explicitly to zero, any + * HttpConnectionManager max_stream_duration timeout will be disabled for + * this route. + */ + 'max_stream_duration': (_google_protobuf_Duration__Output | null); + /** + * If present, and the request contains a `grpc-timeout header + * `_, use that value as the + * *max_stream_duration*, but limit the applied timeout to the maximum value specified here. + * If set to 0, the `grpc-timeout` header is used without modification. + */ + 'grpc_timeout_header_max': (_google_protobuf_Duration__Output | null); + /** + * If present, Envoy will adjust the timeout provided by the `grpc-timeout` header by + * subtracting the provided duration from the header. This is useful for allowing Envoy to set + * its global timeout to be less than that of the deadline imposed by the calling client, which + * makes it more likely that Envoy will handle the timeout instead of having the call canceled + * by the client. If, after applying the offset, the resulting timeout is zero or negative, + * the stream will timeout immediately. + */ + 'grpc_timeout_header_offset': (_google_protobuf_Duration__Output | null); +} + +export interface _envoy_config_route_v3_RouteAction_HashPolicy_QueryParameter { /** * The name of the URL query parameter that will be used to obtain the hash * key. If the parameter is not present, no hash will be produced. Query @@ -268,7 +371,7 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter { 'name'?: (string); } -export interface _envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter__Output { +export interface _envoy_config_route_v3_RouteAction_HashPolicy_QueryParameter__Output { /** * The name of the URL query parameter that will be used to obtain the hash * key. If the parameter is not present, no hash will be produced. Query @@ -290,30 +393,12 @@ export interface _envoy_api_v2_route_RouteAction_HashPolicy_QueryParameter__Outp * * Shadowing will not be triggered if the primary cluster does not exist. */ -export interface _envoy_api_v2_route_RouteAction_RequestMirrorPolicy { +export interface _envoy_config_route_v3_RouteAction_RequestMirrorPolicy { /** * Specifies the cluster that requests will be mirrored to. The cluster must * exist in the cluster manager configuration. */ 'cluster'?: (string); - /** - * If not specified, all requests to the target cluster will be mirrored. If - * specified, Envoy will lookup the runtime key to get the % of requests to - * mirror. Valid values are from 0 to 10000, allowing for increments of - * 0.01% of requests to be mirrored. If the runtime key is specified in the - * configuration but not present in runtime, 0 is the default and thus 0% of - * requests will be mirrored. - * - * .. attention:: - * - * **This field is deprecated**. Set the - * :ref:`runtime_fraction - * ` - * field instead. Mirroring occurs if both this and - * ` - * are not set. - */ - 'runtime_key'?: (string); /** * If not specified, all requests to the target cluster will be mirrored. * @@ -324,11 +409,11 @@ export interface _envoy_api_v2_route_RouteAction_RequestMirrorPolicy { * number is <= the value of the numerator N, or if the key is not present, the default * value, the request will be mirrored. */ - 'runtime_fraction'?: (_envoy_api_v2_core_RuntimeFractionalPercent); + 'runtime_fraction'?: (_envoy_config_core_v3_RuntimeFractionalPercent | null); /** * Determines if the trace span should be sampled. Defaults to true. */ - 'trace_sampled'?: (_google_protobuf_BoolValue); + 'trace_sampled'?: (_google_protobuf_BoolValue | null); } /** @@ -344,30 +429,12 @@ export interface _envoy_api_v2_route_RouteAction_RequestMirrorPolicy { * * Shadowing will not be triggered if the primary cluster does not exist. */ -export interface _envoy_api_v2_route_RouteAction_RequestMirrorPolicy__Output { +export interface _envoy_config_route_v3_RouteAction_RequestMirrorPolicy__Output { /** * Specifies the cluster that requests will be mirrored to. The cluster must * exist in the cluster manager configuration. */ 'cluster': (string); - /** - * If not specified, all requests to the target cluster will be mirrored. If - * specified, Envoy will lookup the runtime key to get the % of requests to - * mirror. Valid values are from 0 to 10000, allowing for increments of - * 0.01% of requests to be mirrored. If the runtime key is specified in the - * configuration but not present in runtime, 0 is the default and thus 0% of - * requests will be mirrored. - * - * .. attention:: - * - * **This field is deprecated**. Set the - * :ref:`runtime_fraction - * ` - * field instead. Mirroring occurs if both this and - * ` - * are not set. - */ - 'runtime_key': (string); /** * If not specified, all requests to the target cluster will be mirrored. * @@ -378,11 +445,11 @@ export interface _envoy_api_v2_route_RouteAction_RequestMirrorPolicy__Output { * number is <= the value of the numerator N, or if the key is not present, the default * value, the request will be mirrored. */ - 'runtime_fraction'?: (_envoy_api_v2_core_RuntimeFractionalPercent__Output); + 'runtime_fraction': (_envoy_config_core_v3_RuntimeFractionalPercent__Output | null); /** * Determines if the trace span should be sampled. Defaults to true. */ - 'trace_sampled'?: (_google_protobuf_BoolValue__Output); + 'trace_sampled': (_google_protobuf_BoolValue__Output | null); } /** @@ -390,10 +457,10 @@ export interface _envoy_api_v2_route_RouteAction_RequestMirrorPolicy__Output { * This overrides any enabled/disabled upgrade filter chain specified in the * HttpConnectionManager * :ref:`upgrade_configs - * ` + * ` * but does not affect any custom filter chain specified there. */ -export interface _envoy_api_v2_route_RouteAction_UpgradeConfig { +export interface _envoy_config_route_v3_RouteAction_UpgradeConfig { /** * The case-insensitive name of this upgrade, e.g. "websocket". * For each upgrade type present in upgrade_configs, requests with @@ -403,7 +470,14 @@ export interface _envoy_api_v2_route_RouteAction_UpgradeConfig { /** * Determines if upgrades are available on this route. Defaults to true. */ - 'enabled'?: (_google_protobuf_BoolValue); + 'enabled'?: (_google_protobuf_BoolValue | null); + /** + * Configuration for sending data upstream as a raw data payload. This is used for + * CONNECT requests, when forwarding CONNECT payload as raw TCP. + * Note that CONNECT support is currently considered alpha in Envoy. + * [#comment: TODO(htuch): Replace the above comment with an alpha tag.] + */ + 'connect_config'?: (_envoy_config_route_v3_RouteAction_UpgradeConfig_ConnectConfig | null); } /** @@ -411,10 +485,10 @@ export interface _envoy_api_v2_route_RouteAction_UpgradeConfig { * This overrides any enabled/disabled upgrade filter chain specified in the * HttpConnectionManager * :ref:`upgrade_configs - * ` + * ` * but does not affect any custom filter chain specified there. */ -export interface _envoy_api_v2_route_RouteAction_UpgradeConfig__Output { +export interface _envoy_config_route_v3_RouteAction_UpgradeConfig__Output { /** * The case-insensitive name of this upgrade, e.g. "websocket". * For each upgrade type present in upgrade_configs, requests with @@ -424,11 +498,18 @@ export interface _envoy_api_v2_route_RouteAction_UpgradeConfig__Output { /** * Determines if upgrades are available on this route. Defaults to true. */ - 'enabled'?: (_google_protobuf_BoolValue__Output); + 'enabled': (_google_protobuf_BoolValue__Output | null); + /** + * Configuration for sending data upstream as a raw data payload. This is used for + * CONNECT requests, when forwarding CONNECT payload as raw TCP. + * Note that CONNECT support is currently considered alpha in Envoy. + * [#comment: TODO(htuch): Replace the above comment with an alpha tag.] + */ + 'connect_config': (_envoy_config_route_v3_RouteAction_UpgradeConfig_ConnectConfig__Output | null); } /** - * [#next-free-field: 34] + * [#next-free-field: 38] */ export interface RouteAction { /** @@ -446,6 +527,10 @@ export interface RouteAction { * * Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1 * *Host* header. Thus, if attempting to match on *Host*, match on *:authority* instead. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. */ 'cluster_header'?: (string); /** @@ -455,15 +540,15 @@ export interface RouteAction { * :ref:`traffic splitting ` * for additional documentation. */ - 'weighted_clusters'?: (_envoy_api_v2_route_WeightedCluster); + 'weighted_clusters'?: (_envoy_config_route_v3_WeightedCluster | null); /** * Optional endpoint metadata match criteria used by the subset load balancer. Only endpoints * in the upstream cluster with metadata matching what's set in this field will be considered * for load balancing. If using :ref:`weighted_clusters - * `, metadata will be merged, with values + * `, metadata will be merged, with values * provided there taking precedence. The filter name should be specified as *envoy.lb*. */ - 'metadata_match'?: (_envoy_api_v2_core_Metadata); + 'metadata_match'?: (_envoy_config_core_v3_Metadata | null); /** * Indicates that during forwarding, the matched prefix (or path) should be * swapped with this value. This option allows application URLs to be rooted @@ -472,16 +557,16 @@ export interface RouteAction { * ` header. * * Only one of *prefix_rewrite* or - * :ref:`regex_rewrite ` + * :ref:`regex_rewrite ` * may be specified. * * .. attention:: * * Pay careful attention to the use of trailing slashes in the - * :ref:`route's match ` prefix value. + * :ref:`route's match ` prefix value. * Stripping a prefix from a path requires multiple Routes to handle all cases. For example, * rewriting * /prefix* to * /* and * /prefix/etc* to * /etc* cannot be done in a single - * :ref:`Route `, as shown by the below config entries: + * :ref:`Route `, as shown by the below config entries: * * .. code-block:: yaml * @@ -502,7 +587,7 @@ export interface RouteAction { * Indicates that during forwarding, the host header will be swapped with * this value. */ - 'host_rewrite'?: (string); + 'host_rewrite_literal'?: (string); /** * Indicates that during forwarding, the host header will be swapped with * the hostname of the upstream host chosen by the cluster manager. This @@ -510,7 +595,7 @@ export interface RouteAction { * type *strict_dns* or *logical_dns*. Setting this to true with other cluster * types has no effect. */ - 'auto_host_rewrite'?: (_google_protobuf_BoolValue); + 'auto_host_rewrite'?: (_google_protobuf_BoolValue | null); /** * Specifies the upstream timeout for the route. If not specified, the default is 15s. This * spans between the point at which the entire downstream request (i.e. end-of-stream) has been @@ -524,37 +609,31 @@ export interface RouteAction { * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms`, and the * :ref:`retry overview `. */ - 'timeout'?: (_google_protobuf_Duration); + 'timeout'?: (_google_protobuf_Duration | null); /** * Indicates that the route has a retry policy. Note that if this is set, * it'll take precedence over the virtual host level retry policy entirely * (e.g.: policies are not merged, most internal one becomes the enforced policy). */ - 'retry_policy'?: (_envoy_api_v2_route_RetryPolicy); - /** - * Indicates that the route has a request mirroring policy. - * - * .. attention:: - * This field has been deprecated in favor of `request_mirror_policies` which supports one or - * more mirroring policies. - */ - 'request_mirror_policy'?: (_envoy_api_v2_route_RouteAction_RequestMirrorPolicy); + 'retry_policy'?: (_envoy_config_route_v3_RetryPolicy | null); /** * Optionally specifies the :ref:`routing priority `. */ - 'priority'?: (_envoy_api_v2_core_RoutingPriority | keyof typeof _envoy_api_v2_core_RoutingPriority); + 'priority'?: (_envoy_config_core_v3_RoutingPriority | keyof typeof _envoy_config_core_v3_RoutingPriority); /** * Specifies a set of rate limit configurations that could be applied to the * route. */ - 'rate_limits'?: (_envoy_api_v2_route_RateLimit)[]; + 'rate_limits'?: (_envoy_config_route_v3_RateLimit)[]; /** * Specifies if the rate limit filter should include the virtual host rate * limits. By default, if the route configured rate limits, the virtual host - * :ref:`rate_limits ` are not applied to the + * :ref:`rate_limits ` are not applied to the * request. + * + * This field is deprecated. Please use :ref:`vh_rate_limits ` */ - 'include_vh_rate_limits'?: (_google_protobuf_BoolValue); + 'include_vh_rate_limits'?: (_google_protobuf_BoolValue | null); /** * Specifies a list of hash policies to use for ring hash load balancing. Each * hash policy is evaluated individually and the combined result is used to @@ -569,25 +648,26 @@ export interface RouteAction { * there is already a hash generated, the hash is returned immediately, * ignoring the rest of the hash policy list. */ - 'hash_policy'?: (_envoy_api_v2_route_RouteAction_HashPolicy)[]; + 'hash_policy'?: (_envoy_config_route_v3_RouteAction_HashPolicy)[]; /** * Indicates that the route has a CORS policy. */ - 'cors'?: (_envoy_api_v2_route_CorsPolicy); + 'cors'?: (_envoy_config_route_v3_CorsPolicy | null); /** * The HTTP status code to use when configured cluster is not found. * The default response code is 503 Service Unavailable. */ - 'cluster_not_found_response_code'?: (_envoy_api_v2_route_RouteAction_ClusterNotFoundResponseCode | keyof typeof _envoy_api_v2_route_RouteAction_ClusterNotFoundResponseCode); + 'cluster_not_found_response_code'?: (_envoy_config_route_v3_RouteAction_ClusterNotFoundResponseCode | keyof typeof _envoy_config_route_v3_RouteAction_ClusterNotFoundResponseCode); /** + * Deprecated by :ref:`grpc_timeout_header_max ` * If present, and the request is a gRPC request, use the * `grpc-timeout header `_, * or its default value (infinity) instead of - * :ref:`timeout `, but limit the applied timeout + * :ref:`timeout `, but limit the applied timeout * to the maximum value specified here. If configured as 0, the maximum allowed timeout for * gRPC requests is infinity. If not configured at all, the `grpc-timeout` header is not used * and gRPC requests time out like any other requests using - * :ref:`timeout ` or its default. + * :ref:`timeout ` or its default. * This can be used to prevent unexpected upstream request timeouts due to potentially long * time gaps between gRPC request and response in gRPC streaming mode. * @@ -600,18 +680,18 @@ export interface RouteAction { * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms`, and the * :ref:`retry overview `. */ - 'max_grpc_timeout'?: (_google_protobuf_Duration); + 'max_grpc_timeout'?: (_google_protobuf_Duration | null); /** * Specifies the idle timeout for the route. If not specified, there is no per-route idle timeout, * although the connection manager wide :ref:`stream_idle_timeout - * ` + * ` * will still apply. A value of 0 will completely disable the route's idle timeout, even if a * connection manager stream idle timeout is configured. * * The idle timeout is distinct to :ref:`timeout - * `, which provides an upper bound + * `, which provides an upper bound * on the upstream response time; :ref:`idle_timeout - * ` instead bounds the amount + * ` instead bounds the amount * of time the request's stream may be idle. * * After header decoding, the idle timeout will apply on downstream and @@ -620,17 +700,22 @@ export interface RouteAction { * fires, the stream is terminated with a 408 Request Timeout error code if no * upstream response header has been received, otherwise a stream reset * occurs. + * + * If the :ref:`overload action ` "envoy.overload_actions.reduce_timeouts" + * is configured, this timeout is scaled according to the value for + * :ref:`HTTP_DOWNSTREAM_STREAM_IDLE `. */ - 'idle_timeout'?: (_google_protobuf_Duration); - 'upgrade_configs'?: (_envoy_api_v2_route_RouteAction_UpgradeConfig)[]; - 'internal_redirect_action'?: (_envoy_api_v2_route_RouteAction_InternalRedirectAction | keyof typeof _envoy_api_v2_route_RouteAction_InternalRedirectAction); + 'idle_timeout'?: (_google_protobuf_Duration | null); + 'upgrade_configs'?: (_envoy_config_route_v3_RouteAction_UpgradeConfig)[]; + 'internal_redirect_action'?: (_envoy_config_route_v3_RouteAction_InternalRedirectAction | keyof typeof _envoy_config_route_v3_RouteAction_InternalRedirectAction); /** * Indicates that the route has a hedge policy. Note that if this is set, * it'll take precedence over the virtual host level hedge policy entirely * (e.g.: policies are not merged, most internal one becomes the enforced policy). */ - 'hedge_policy'?: (_envoy_api_v2_route_HedgePolicy); + 'hedge_policy'?: (_envoy_config_route_v3_HedgePolicy | null); /** + * Deprecated by :ref:`grpc_timeout_header_offset `. * If present, Envoy will adjust the timeout provided by the `grpc-timeout` header by subtracting * the provided duration from the header. This is useful in allowing Envoy to set its global * timeout to be less than that of the deadline imposed by the calling client, which makes it more @@ -639,7 +724,7 @@ export interface RouteAction { * ensures that the offset will only ever decrease the timeout and never set it to 0 (meaning * infinity). */ - 'grpc_timeout_offset'?: (_google_protobuf_Duration); + 'grpc_timeout_offset'?: (_google_protobuf_Duration | null); /** * Indicates that during forwarding, the host header will be swapped with the content of given * downstream or :ref:`custom ` header. @@ -649,29 +734,33 @@ export interface RouteAction { * * Pay attention to the potential security implications of using this option. Provided header * must come from trusted source. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. */ - 'auto_host_rewrite_header'?: (string); + 'host_rewrite_header'?: (string); /** * Indicates that the route has request mirroring policies. */ - 'request_mirror_policies'?: (_envoy_api_v2_route_RouteAction_RequestMirrorPolicy)[]; + 'request_mirror_policies'?: (_envoy_config_route_v3_RouteAction_RequestMirrorPolicy)[]; /** * An internal redirect is handled, iff the number of previous internal redirects that a * downstream request has encountered is lower than this value, and - * :ref:`internal_redirect_action ` + * :ref:`internal_redirect_action ` * is set to :ref:`HANDLE_INTERNAL_REDIRECT - * ` + * ` * In the case where a downstream request is bounced among multiple routes by internal redirect, * the first route that hits this threshold, or has - * :ref:`internal_redirect_action ` + * :ref:`internal_redirect_action ` * set to * :ref:`PASS_THROUGH_INTERNAL_REDIRECT - * ` + * ` * will pass the redirect back to downstream. * * If not specified, at most one redirect will be followed. */ - 'max_internal_redirects'?: (_google_protobuf_UInt32Value); + 'max_internal_redirects'?: (_google_protobuf_UInt32Value | null); /** * Indicates that during forwarding, portions of the path that match the * pattern should be rewritten, even allowing the substitution of capture @@ -682,7 +771,7 @@ export interface RouteAction { * before the rewrite into the :ref:`x-envoy-original-path * ` header. * - * Only one of :ref:`prefix_rewrite ` + * Only one of :ref:`prefix_rewrite ` * or *regex_rewrite* may be specified. * * Examples using Google's `RE2 `_ engine: @@ -702,21 +791,59 @@ export interface RouteAction { * would do a case-insensitive match and transform path ``/aaa/XxX/bbb`` to * ``/aaa/yyy/bbb``. */ - 'regex_rewrite'?: (_envoy_type_matcher_RegexMatchAndSubstitute); + 'regex_rewrite'?: (_envoy_type_matcher_v3_RegexMatchAndSubstitute | null); /** * [#not-implemented-hide:] * Specifies the configuration for retry policy extension. Note that if this is set, it'll take * precedence over the virtual host level retry policy entirely (e.g.: policies are not merged, - * most internal one becomes the enforced policy). :ref:`Retry policy ` + * most internal one becomes the enforced policy). :ref:`Retry policy ` * should not be set if this field is used. */ - 'retry_policy_typed_config'?: (_google_protobuf_Any); - 'cluster_specifier'?: "cluster"|"cluster_header"|"weighted_clusters"; - 'host_rewrite_specifier'?: "host_rewrite"|"auto_host_rewrite"|"auto_host_rewrite_header"; + 'retry_policy_typed_config'?: (_google_protobuf_Any | null); + /** + * If present, Envoy will try to follow an upstream redirect response instead of proxying the + * response back to the downstream. An upstream redirect response is defined + * by :ref:`redirect_response_codes + * `. + */ + 'internal_redirect_policy'?: (_envoy_config_route_v3_InternalRedirectPolicy | null); + /** + * Indicates that during forwarding, the host header will be swapped with + * the result of the regex substitution executed on path value with query and fragment removed. + * This is useful for transitioning variable content between path segment and subdomain. + * + * For example with the following config: + * + * .. code-block:: yaml + * + * host_rewrite_path_regex: + * pattern: + * google_re2: {} + * regex: "^/(.+)/.+$" + * substitution: \1 + * + * Would rewrite the host header to `envoyproxy.io` given the path `/envoyproxy.io/some/path`. + */ + 'host_rewrite_path_regex'?: (_envoy_type_matcher_v3_RegexMatchAndSubstitute | null); + /** + * Specifies the maximum stream duration for this route. + */ + 'max_stream_duration'?: (_envoy_config_route_v3_RouteAction_MaxStreamDuration | null); + /** + * [#not-implemented-hide:] + * Name of the cluster specifier plugin to use to determine the cluster for + * requests on this route. The plugin name must be defined in the associated + * :ref:`envoy_v3_api_field_config.route.v3.RouteConfiguration.cluster_specifier_plugins` + * in the + * :ref:`envoy_v3_api_field_config.core.v3.TypedExtensionConfig.name` field. + */ + 'cluster_specifier_plugin'?: (string); + 'cluster_specifier'?: "cluster"|"cluster_header"|"weighted_clusters"|"cluster_specifier_plugin"; + 'host_rewrite_specifier'?: "host_rewrite_literal"|"auto_host_rewrite"|"host_rewrite_header"|"host_rewrite_path_regex"; } /** - * [#next-free-field: 34] + * [#next-free-field: 38] */ export interface RouteAction__Output { /** @@ -734,6 +861,10 @@ export interface RouteAction__Output { * * Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1 * *Host* header. Thus, if attempting to match on *Host*, match on *:authority* instead. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. */ 'cluster_header'?: (string); /** @@ -743,15 +874,15 @@ export interface RouteAction__Output { * :ref:`traffic splitting ` * for additional documentation. */ - 'weighted_clusters'?: (_envoy_api_v2_route_WeightedCluster__Output); + 'weighted_clusters'?: (_envoy_config_route_v3_WeightedCluster__Output | null); /** * Optional endpoint metadata match criteria used by the subset load balancer. Only endpoints * in the upstream cluster with metadata matching what's set in this field will be considered * for load balancing. If using :ref:`weighted_clusters - * `, metadata will be merged, with values + * `, metadata will be merged, with values * provided there taking precedence. The filter name should be specified as *envoy.lb*. */ - 'metadata_match'?: (_envoy_api_v2_core_Metadata__Output); + 'metadata_match': (_envoy_config_core_v3_Metadata__Output | null); /** * Indicates that during forwarding, the matched prefix (or path) should be * swapped with this value. This option allows application URLs to be rooted @@ -760,16 +891,16 @@ export interface RouteAction__Output { * ` header. * * Only one of *prefix_rewrite* or - * :ref:`regex_rewrite ` + * :ref:`regex_rewrite ` * may be specified. * * .. attention:: * * Pay careful attention to the use of trailing slashes in the - * :ref:`route's match ` prefix value. + * :ref:`route's match ` prefix value. * Stripping a prefix from a path requires multiple Routes to handle all cases. For example, * rewriting * /prefix* to * /* and * /prefix/etc* to * /etc* cannot be done in a single - * :ref:`Route `, as shown by the below config entries: + * :ref:`Route `, as shown by the below config entries: * * .. code-block:: yaml * @@ -790,7 +921,7 @@ export interface RouteAction__Output { * Indicates that during forwarding, the host header will be swapped with * this value. */ - 'host_rewrite'?: (string); + 'host_rewrite_literal'?: (string); /** * Indicates that during forwarding, the host header will be swapped with * the hostname of the upstream host chosen by the cluster manager. This @@ -798,7 +929,7 @@ export interface RouteAction__Output { * type *strict_dns* or *logical_dns*. Setting this to true with other cluster * types has no effect. */ - 'auto_host_rewrite'?: (_google_protobuf_BoolValue__Output); + 'auto_host_rewrite'?: (_google_protobuf_BoolValue__Output | null); /** * Specifies the upstream timeout for the route. If not specified, the default is 15s. This * spans between the point at which the entire downstream request (i.e. end-of-stream) has been @@ -812,37 +943,31 @@ export interface RouteAction__Output { * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms`, and the * :ref:`retry overview `. */ - 'timeout'?: (_google_protobuf_Duration__Output); + 'timeout': (_google_protobuf_Duration__Output | null); /** * Indicates that the route has a retry policy. Note that if this is set, * it'll take precedence over the virtual host level retry policy entirely * (e.g.: policies are not merged, most internal one becomes the enforced policy). */ - 'retry_policy'?: (_envoy_api_v2_route_RetryPolicy__Output); - /** - * Indicates that the route has a request mirroring policy. - * - * .. attention:: - * This field has been deprecated in favor of `request_mirror_policies` which supports one or - * more mirroring policies. - */ - 'request_mirror_policy'?: (_envoy_api_v2_route_RouteAction_RequestMirrorPolicy__Output); + 'retry_policy': (_envoy_config_route_v3_RetryPolicy__Output | null); /** * Optionally specifies the :ref:`routing priority `. */ - 'priority': (keyof typeof _envoy_api_v2_core_RoutingPriority); + 'priority': (keyof typeof _envoy_config_core_v3_RoutingPriority); /** * Specifies a set of rate limit configurations that could be applied to the * route. */ - 'rate_limits': (_envoy_api_v2_route_RateLimit__Output)[]; + 'rate_limits': (_envoy_config_route_v3_RateLimit__Output)[]; /** * Specifies if the rate limit filter should include the virtual host rate * limits. By default, if the route configured rate limits, the virtual host - * :ref:`rate_limits ` are not applied to the + * :ref:`rate_limits ` are not applied to the * request. + * + * This field is deprecated. Please use :ref:`vh_rate_limits ` */ - 'include_vh_rate_limits'?: (_google_protobuf_BoolValue__Output); + 'include_vh_rate_limits': (_google_protobuf_BoolValue__Output | null); /** * Specifies a list of hash policies to use for ring hash load balancing. Each * hash policy is evaluated individually and the combined result is used to @@ -857,25 +982,26 @@ export interface RouteAction__Output { * there is already a hash generated, the hash is returned immediately, * ignoring the rest of the hash policy list. */ - 'hash_policy': (_envoy_api_v2_route_RouteAction_HashPolicy__Output)[]; + 'hash_policy': (_envoy_config_route_v3_RouteAction_HashPolicy__Output)[]; /** * Indicates that the route has a CORS policy. */ - 'cors'?: (_envoy_api_v2_route_CorsPolicy__Output); + 'cors': (_envoy_config_route_v3_CorsPolicy__Output | null); /** * The HTTP status code to use when configured cluster is not found. * The default response code is 503 Service Unavailable. */ - 'cluster_not_found_response_code': (keyof typeof _envoy_api_v2_route_RouteAction_ClusterNotFoundResponseCode); + 'cluster_not_found_response_code': (keyof typeof _envoy_config_route_v3_RouteAction_ClusterNotFoundResponseCode); /** + * Deprecated by :ref:`grpc_timeout_header_max ` * If present, and the request is a gRPC request, use the * `grpc-timeout header `_, * or its default value (infinity) instead of - * :ref:`timeout `, but limit the applied timeout + * :ref:`timeout `, but limit the applied timeout * to the maximum value specified here. If configured as 0, the maximum allowed timeout for * gRPC requests is infinity. If not configured at all, the `grpc-timeout` header is not used * and gRPC requests time out like any other requests using - * :ref:`timeout ` or its default. + * :ref:`timeout ` or its default. * This can be used to prevent unexpected upstream request timeouts due to potentially long * time gaps between gRPC request and response in gRPC streaming mode. * @@ -888,18 +1014,18 @@ export interface RouteAction__Output { * :ref:`config_http_filters_router_x-envoy-upstream-rq-per-try-timeout-ms`, and the * :ref:`retry overview `. */ - 'max_grpc_timeout'?: (_google_protobuf_Duration__Output); + 'max_grpc_timeout': (_google_protobuf_Duration__Output | null); /** * Specifies the idle timeout for the route. If not specified, there is no per-route idle timeout, * although the connection manager wide :ref:`stream_idle_timeout - * ` + * ` * will still apply. A value of 0 will completely disable the route's idle timeout, even if a * connection manager stream idle timeout is configured. * * The idle timeout is distinct to :ref:`timeout - * `, which provides an upper bound + * `, which provides an upper bound * on the upstream response time; :ref:`idle_timeout - * ` instead bounds the amount + * ` instead bounds the amount * of time the request's stream may be idle. * * After header decoding, the idle timeout will apply on downstream and @@ -908,17 +1034,22 @@ export interface RouteAction__Output { * fires, the stream is terminated with a 408 Request Timeout error code if no * upstream response header has been received, otherwise a stream reset * occurs. + * + * If the :ref:`overload action ` "envoy.overload_actions.reduce_timeouts" + * is configured, this timeout is scaled according to the value for + * :ref:`HTTP_DOWNSTREAM_STREAM_IDLE `. */ - 'idle_timeout'?: (_google_protobuf_Duration__Output); - 'upgrade_configs': (_envoy_api_v2_route_RouteAction_UpgradeConfig__Output)[]; - 'internal_redirect_action': (keyof typeof _envoy_api_v2_route_RouteAction_InternalRedirectAction); + 'idle_timeout': (_google_protobuf_Duration__Output | null); + 'upgrade_configs': (_envoy_config_route_v3_RouteAction_UpgradeConfig__Output)[]; + 'internal_redirect_action': (keyof typeof _envoy_config_route_v3_RouteAction_InternalRedirectAction); /** * Indicates that the route has a hedge policy. Note that if this is set, * it'll take precedence over the virtual host level hedge policy entirely * (e.g.: policies are not merged, most internal one becomes the enforced policy). */ - 'hedge_policy'?: (_envoy_api_v2_route_HedgePolicy__Output); + 'hedge_policy': (_envoy_config_route_v3_HedgePolicy__Output | null); /** + * Deprecated by :ref:`grpc_timeout_header_offset `. * If present, Envoy will adjust the timeout provided by the `grpc-timeout` header by subtracting * the provided duration from the header. This is useful in allowing Envoy to set its global * timeout to be less than that of the deadline imposed by the calling client, which makes it more @@ -927,7 +1058,7 @@ export interface RouteAction__Output { * ensures that the offset will only ever decrease the timeout and never set it to 0 (meaning * infinity). */ - 'grpc_timeout_offset'?: (_google_protobuf_Duration__Output); + 'grpc_timeout_offset': (_google_protobuf_Duration__Output | null); /** * Indicates that during forwarding, the host header will be swapped with the content of given * downstream or :ref:`custom ` header. @@ -937,29 +1068,33 @@ export interface RouteAction__Output { * * Pay attention to the potential security implications of using this option. Provided header * must come from trusted source. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. */ - 'auto_host_rewrite_header'?: (string); + 'host_rewrite_header'?: (string); /** * Indicates that the route has request mirroring policies. */ - 'request_mirror_policies': (_envoy_api_v2_route_RouteAction_RequestMirrorPolicy__Output)[]; + 'request_mirror_policies': (_envoy_config_route_v3_RouteAction_RequestMirrorPolicy__Output)[]; /** * An internal redirect is handled, iff the number of previous internal redirects that a * downstream request has encountered is lower than this value, and - * :ref:`internal_redirect_action ` + * :ref:`internal_redirect_action ` * is set to :ref:`HANDLE_INTERNAL_REDIRECT - * ` + * ` * In the case where a downstream request is bounced among multiple routes by internal redirect, * the first route that hits this threshold, or has - * :ref:`internal_redirect_action ` + * :ref:`internal_redirect_action ` * set to * :ref:`PASS_THROUGH_INTERNAL_REDIRECT - * ` + * ` * will pass the redirect back to downstream. * * If not specified, at most one redirect will be followed. */ - 'max_internal_redirects'?: (_google_protobuf_UInt32Value__Output); + 'max_internal_redirects': (_google_protobuf_UInt32Value__Output | null); /** * Indicates that during forwarding, portions of the path that match the * pattern should be rewritten, even allowing the substitution of capture @@ -970,7 +1105,7 @@ export interface RouteAction__Output { * before the rewrite into the :ref:`x-envoy-original-path * ` header. * - * Only one of :ref:`prefix_rewrite ` + * Only one of :ref:`prefix_rewrite ` * or *regex_rewrite* may be specified. * * Examples using Google's `RE2 `_ engine: @@ -990,15 +1125,53 @@ export interface RouteAction__Output { * would do a case-insensitive match and transform path ``/aaa/XxX/bbb`` to * ``/aaa/yyy/bbb``. */ - 'regex_rewrite'?: (_envoy_type_matcher_RegexMatchAndSubstitute__Output); + 'regex_rewrite': (_envoy_type_matcher_v3_RegexMatchAndSubstitute__Output | null); /** * [#not-implemented-hide:] * Specifies the configuration for retry policy extension. Note that if this is set, it'll take * precedence over the virtual host level retry policy entirely (e.g.: policies are not merged, - * most internal one becomes the enforced policy). :ref:`Retry policy ` + * most internal one becomes the enforced policy). :ref:`Retry policy ` * should not be set if this field is used. */ - 'retry_policy_typed_config'?: (_google_protobuf_Any__Output); - 'cluster_specifier': "cluster"|"cluster_header"|"weighted_clusters"; - 'host_rewrite_specifier': "host_rewrite"|"auto_host_rewrite"|"auto_host_rewrite_header"; + 'retry_policy_typed_config': (_google_protobuf_Any__Output | null); + /** + * If present, Envoy will try to follow an upstream redirect response instead of proxying the + * response back to the downstream. An upstream redirect response is defined + * by :ref:`redirect_response_codes + * `. + */ + 'internal_redirect_policy': (_envoy_config_route_v3_InternalRedirectPolicy__Output | null); + /** + * Indicates that during forwarding, the host header will be swapped with + * the result of the regex substitution executed on path value with query and fragment removed. + * This is useful for transitioning variable content between path segment and subdomain. + * + * For example with the following config: + * + * .. code-block:: yaml + * + * host_rewrite_path_regex: + * pattern: + * google_re2: {} + * regex: "^/(.+)/.+$" + * substitution: \1 + * + * Would rewrite the host header to `envoyproxy.io` given the path `/envoyproxy.io/some/path`. + */ + 'host_rewrite_path_regex'?: (_envoy_type_matcher_v3_RegexMatchAndSubstitute__Output | null); + /** + * Specifies the maximum stream duration for this route. + */ + 'max_stream_duration': (_envoy_config_route_v3_RouteAction_MaxStreamDuration__Output | null); + /** + * [#not-implemented-hide:] + * Name of the cluster specifier plugin to use to determine the cluster for + * requests on this route. The plugin name must be defined in the associated + * :ref:`envoy_v3_api_field_config.route.v3.RouteConfiguration.cluster_specifier_plugins` + * in the + * :ref:`envoy_v3_api_field_config.core.v3.TypedExtensionConfig.name` field. + */ + 'cluster_specifier_plugin'?: (string); + 'cluster_specifier': "cluster"|"cluster_header"|"weighted_clusters"|"cluster_specifier_plugin"; + 'host_rewrite_specifier': "host_rewrite_literal"|"auto_host_rewrite"|"host_rewrite_header"|"host_rewrite_path_regex"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/RouteConfiguration.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteConfiguration.ts similarity index 55% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/RouteConfiguration.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteConfiguration.ts index de0634c24..516f4b06b 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/RouteConfiguration.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteConfiguration.ts @@ -1,25 +1,27 @@ -// Original file: deps/envoy-api/envoy/api/v2/route.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route.proto -import type { VirtualHost as _envoy_api_v2_route_VirtualHost, VirtualHost__Output as _envoy_api_v2_route_VirtualHost__Output } from '../../../envoy/api/v2/route/VirtualHost'; -import type { HeaderValueOption as _envoy_api_v2_core_HeaderValueOption, HeaderValueOption__Output as _envoy_api_v2_core_HeaderValueOption__Output } from '../../../envoy/api/v2/core/HeaderValueOption'; -import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../google/protobuf/BoolValue'; -import type { Vhds as _envoy_api_v2_Vhds, Vhds__Output as _envoy_api_v2_Vhds__Output } from '../../../envoy/api/v2/Vhds'; +import type { VirtualHost as _envoy_config_route_v3_VirtualHost, VirtualHost__Output as _envoy_config_route_v3_VirtualHost__Output } from '../../../../envoy/config/route/v3/VirtualHost'; +import type { HeaderValueOption as _envoy_config_core_v3_HeaderValueOption, HeaderValueOption__Output as _envoy_config_core_v3_HeaderValueOption__Output } from '../../../../envoy/config/core/v3/HeaderValueOption'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; +import type { Vhds as _envoy_config_route_v3_Vhds, Vhds__Output as _envoy_config_route_v3_Vhds__Output } from '../../../../envoy/config/route/v3/Vhds'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; +import type { ClusterSpecifierPlugin as _envoy_config_route_v3_ClusterSpecifierPlugin, ClusterSpecifierPlugin__Output as _envoy_config_route_v3_ClusterSpecifierPlugin__Output } from '../../../../envoy/config/route/v3/ClusterSpecifierPlugin'; /** - * [#next-free-field: 11] + * [#next-free-field: 13] */ export interface RouteConfiguration { /** * The name of the route configuration. For example, it might match * :ref:`route_config_name - * ` in - * :ref:`envoy_api_msg_config.filter.network.http_connection_manager.v2.Rds`. + * ` in + * :ref:`envoy_v3_api_msg_extensions.filters.network.http_connection_manager.v3.Rds`. */ 'name'?: (string); /** * An array of virtual hosts that make up the route table. */ - 'virtual_hosts'?: (_envoy_api_v2_route_VirtualHost)[]; + 'virtual_hosts'?: (_envoy_config_route_v3_VirtualHost)[]; /** * Optionally specifies a list of HTTP headers that the connection manager * will consider to be internal only. If they are found on external requests they will be cleaned @@ -30,12 +32,12 @@ export interface RouteConfiguration { /** * Specifies a list of HTTP headers that should be added to each response that * the connection manager encodes. Headers specified at this level are applied - * after headers from any enclosed :ref:`envoy_api_msg_route.VirtualHost` or - * :ref:`envoy_api_msg_route.RouteAction`. For more information, including details on + * after headers from any enclosed :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` or + * :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'response_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'response_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Specifies a list of HTTP headers that should be removed from each response * that the connection manager encodes. @@ -44,12 +46,12 @@ export interface RouteConfiguration { /** * Specifies a list of HTTP headers that should be added to each request * routed by the HTTP connection manager. Headers specified at this level are - * applied after headers from any enclosed :ref:`envoy_api_msg_route.VirtualHost` or - * :ref:`envoy_api_msg_route.RouteAction`. For more information, including details on + * applied after headers from any enclosed :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` or + * :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'request_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * An optional boolean that specifies whether the clusters that the route * table refers to will be validated by the cluster manager. If set to true @@ -58,14 +60,14 @@ export interface RouteConfiguration { * route table will load and the router filter will return a 404 if the route * is selected at runtime. This setting defaults to true if the route table * is statically defined via the :ref:`route_config - * ` + * ` * option. This setting default to false if the route table is loaded dynamically via the * :ref:`rds - * ` + * ` * option. Users may wish to override the default behavior in certain cases (for example when * using CDS with a static route table). */ - 'validate_clusters'?: (_google_protobuf_BoolValue); + 'validate_clusters'?: (_google_protobuf_BoolValue | null); /** * Specifies a list of HTTP headers that should be removed from each request * routed by the HTTP connection manager. @@ -79,7 +81,7 @@ export interface RouteConfiguration { * generate a routing table for a given RouteConfiguration, with *vhds* derived configuration * taking precedence. */ - 'vhds'?: (_envoy_api_v2_Vhds); + 'vhds'?: (_envoy_config_route_v3_Vhds | null); /** * By default, headers that should be added/removed are evaluated from most to least specific: * @@ -93,23 +95,43 @@ export interface RouteConfiguration { * [#next-major-version: In the v3 API, this will default to true.] */ 'most_specific_header_mutations_wins'?: (boolean); + /** + * The maximum bytes of the response :ref:`direct response body + * ` size. If not specified the default + * is 4096. + * + * .. warning:: + * + * Envoy currently holds the content of :ref:`direct response body + * ` in memory. Be careful setting + * this to be larger than the default 4KB, since the allocated memory for direct response body + * is not subject to data plane buffering controls. + */ + 'max_direct_response_body_size_bytes'?: (_google_protobuf_UInt32Value | null); + /** + * [#not-implemented-hide:] + * A list of plugins and their configurations which may be used by a + * :ref:`envoy_v3_api_field_config.route.v3.RouteAction.cluster_specifier_plugin` + * within the route. All *extension.name* fields in this list must be unique. + */ + 'cluster_specifier_plugins'?: (_envoy_config_route_v3_ClusterSpecifierPlugin)[]; } /** - * [#next-free-field: 11] + * [#next-free-field: 13] */ export interface RouteConfiguration__Output { /** * The name of the route configuration. For example, it might match * :ref:`route_config_name - * ` in - * :ref:`envoy_api_msg_config.filter.network.http_connection_manager.v2.Rds`. + * ` in + * :ref:`envoy_v3_api_msg_extensions.filters.network.http_connection_manager.v3.Rds`. */ 'name': (string); /** * An array of virtual hosts that make up the route table. */ - 'virtual_hosts': (_envoy_api_v2_route_VirtualHost__Output)[]; + 'virtual_hosts': (_envoy_config_route_v3_VirtualHost__Output)[]; /** * Optionally specifies a list of HTTP headers that the connection manager * will consider to be internal only. If they are found on external requests they will be cleaned @@ -120,12 +142,12 @@ export interface RouteConfiguration__Output { /** * Specifies a list of HTTP headers that should be added to each response that * the connection manager encodes. Headers specified at this level are applied - * after headers from any enclosed :ref:`envoy_api_msg_route.VirtualHost` or - * :ref:`envoy_api_msg_route.RouteAction`. For more information, including details on + * after headers from any enclosed :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` or + * :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'response_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'response_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Specifies a list of HTTP headers that should be removed from each response * that the connection manager encodes. @@ -134,12 +156,12 @@ export interface RouteConfiguration__Output { /** * Specifies a list of HTTP headers that should be added to each request * routed by the HTTP connection manager. Headers specified at this level are - * applied after headers from any enclosed :ref:`envoy_api_msg_route.VirtualHost` or - * :ref:`envoy_api_msg_route.RouteAction`. For more information, including details on + * applied after headers from any enclosed :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost` or + * :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'request_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * An optional boolean that specifies whether the clusters that the route * table refers to will be validated by the cluster manager. If set to true @@ -148,14 +170,14 @@ export interface RouteConfiguration__Output { * route table will load and the router filter will return a 404 if the route * is selected at runtime. This setting defaults to true if the route table * is statically defined via the :ref:`route_config - * ` + * ` * option. This setting default to false if the route table is loaded dynamically via the * :ref:`rds - * ` + * ` * option. Users may wish to override the default behavior in certain cases (for example when * using CDS with a static route table). */ - 'validate_clusters'?: (_google_protobuf_BoolValue__Output); + 'validate_clusters': (_google_protobuf_BoolValue__Output | null); /** * Specifies a list of HTTP headers that should be removed from each request * routed by the HTTP connection manager. @@ -169,7 +191,7 @@ export interface RouteConfiguration__Output { * generate a routing table for a given RouteConfiguration, with *vhds* derived configuration * taking precedence. */ - 'vhds'?: (_envoy_api_v2_Vhds__Output); + 'vhds': (_envoy_config_route_v3_Vhds__Output | null); /** * By default, headers that should be added/removed are evaluated from most to least specific: * @@ -183,4 +205,24 @@ export interface RouteConfiguration__Output { * [#next-major-version: In the v3 API, this will default to true.] */ 'most_specific_header_mutations_wins': (boolean); + /** + * The maximum bytes of the response :ref:`direct response body + * ` size. If not specified the default + * is 4096. + * + * .. warning:: + * + * Envoy currently holds the content of :ref:`direct response body + * ` in memory. Be careful setting + * this to be larger than the default 4KB, since the allocated memory for direct response body + * is not subject to data plane buffering controls. + */ + 'max_direct_response_body_size_bytes': (_google_protobuf_UInt32Value__Output | null); + /** + * [#not-implemented-hide:] + * A list of plugins and their configurations which may be used by a + * :ref:`envoy_v3_api_field_config.route.v3.RouteAction.cluster_specifier_plugin` + * within the route. All *extension.name* fields in this list must be unique. + */ + 'cluster_specifier_plugins': (_envoy_config_route_v3_ClusterSpecifierPlugin__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RouteMatch.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteMatch.ts similarity index 56% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/RouteMatch.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteMatch.ts index b055c0506..9d872ed18 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/RouteMatch.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/RouteMatch.ts @@ -1,45 +1,58 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../google/protobuf/BoolValue'; -import type { HeaderMatcher as _envoy_api_v2_route_HeaderMatcher, HeaderMatcher__Output as _envoy_api_v2_route_HeaderMatcher__Output } from '../../../../envoy/api/v2/route/HeaderMatcher'; -import type { QueryParameterMatcher as _envoy_api_v2_route_QueryParameterMatcher, QueryParameterMatcher__Output as _envoy_api_v2_route_QueryParameterMatcher__Output } from '../../../../envoy/api/v2/route/QueryParameterMatcher'; -import type { RuntimeFractionalPercent as _envoy_api_v2_core_RuntimeFractionalPercent, RuntimeFractionalPercent__Output as _envoy_api_v2_core_RuntimeFractionalPercent__Output } from '../../../../envoy/api/v2/core/RuntimeFractionalPercent'; -import type { RegexMatcher as _envoy_type_matcher_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_RegexMatcher__Output } from '../../../../envoy/type/matcher/RegexMatcher'; +import type { HeaderMatcher as _envoy_config_route_v3_HeaderMatcher, HeaderMatcher__Output as _envoy_config_route_v3_HeaderMatcher__Output } from '../../../../envoy/config/route/v3/HeaderMatcher'; +import type { QueryParameterMatcher as _envoy_config_route_v3_QueryParameterMatcher, QueryParameterMatcher__Output as _envoy_config_route_v3_QueryParameterMatcher__Output } from '../../../../envoy/config/route/v3/QueryParameterMatcher'; +import type { RuntimeFractionalPercent as _envoy_config_core_v3_RuntimeFractionalPercent, RuntimeFractionalPercent__Output as _envoy_config_core_v3_RuntimeFractionalPercent__Output } from '../../../../envoy/config/core/v3/RuntimeFractionalPercent'; +import type { RegexMatcher as _envoy_type_matcher_v3_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_v3_RegexMatcher__Output } from '../../../../envoy/type/matcher/v3/RegexMatcher'; +import type { MetadataMatcher as _envoy_type_matcher_v3_MetadataMatcher, MetadataMatcher__Output as _envoy_type_matcher_v3_MetadataMatcher__Output } from '../../../../envoy/type/matcher/v3/MetadataMatcher'; -export interface _envoy_api_v2_route_RouteMatch_GrpcRouteMatchOptions { +/** + * An extensible message for matching CONNECT requests. + */ +export interface _envoy_config_route_v3_RouteMatch_ConnectMatcher { +} + +/** + * An extensible message for matching CONNECT requests. + */ +export interface _envoy_config_route_v3_RouteMatch_ConnectMatcher__Output { +} + +export interface _envoy_config_route_v3_RouteMatch_GrpcRouteMatchOptions { } -export interface _envoy_api_v2_route_RouteMatch_GrpcRouteMatchOptions__Output { +export interface _envoy_config_route_v3_RouteMatch_GrpcRouteMatchOptions__Output { } -export interface _envoy_api_v2_route_RouteMatch_TlsContextMatchOptions { +export interface _envoy_config_route_v3_RouteMatch_TlsContextMatchOptions { /** * If specified, the route will match against whether or not a certificate is presented. * If not specified, certificate presentation status (true or false) will not be considered when route matching. */ - 'presented'?: (_google_protobuf_BoolValue); + 'presented'?: (_google_protobuf_BoolValue | null); /** * If specified, the route will match against whether or not a certificate is validated. * If not specified, certificate validation status (true or false) will not be considered when route matching. */ - 'validated'?: (_google_protobuf_BoolValue); + 'validated'?: (_google_protobuf_BoolValue | null); } -export interface _envoy_api_v2_route_RouteMatch_TlsContextMatchOptions__Output { +export interface _envoy_config_route_v3_RouteMatch_TlsContextMatchOptions__Output { /** * If specified, the route will match against whether or not a certificate is presented. * If not specified, certificate presentation status (true or false) will not be considered when route matching. */ - 'presented'?: (_google_protobuf_BoolValue__Output); + 'presented': (_google_protobuf_BoolValue__Output | null); /** * If specified, the route will match against whether or not a certificate is validated. * If not specified, certificate validation status (true or false) will not be considered when route matching. */ - 'validated'?: (_google_protobuf_BoolValue__Output); + 'validated': (_google_protobuf_BoolValue__Output | null); } /** - * [#next-free-field: 12] + * [#next-free-field: 14] */ export interface RouteMatch { /** @@ -53,29 +66,10 @@ export interface RouteMatch { */ 'path'?: (string); /** - * If specified, the route is a regular expression rule meaning that the - * regex must match the *:path* header once the query string is removed. The entire path - * (without the query string) must match the regex. The rule will not match if only a - * subsequence of the *:path* header matches the regex. The regex grammar is defined `here - * `_. - * - * Examples: - * - * * The regex ``/b[io]t`` matches the path * /bit* - * * The regex ``/b[io]t`` matches the path * /bot* - * * The regex ``/b[io]t`` does not match the path * /bite* - * * The regex ``/b[io]t`` does not match the path * /bit/bot* - * - * .. attention:: - * This field has been deprecated in favor of `safe_regex` as it is not safe for use with - * untrusted input in all cases. + * Indicates that prefix/path matching should be case sensitive. The default + * is true. Ignored for safe_regex matching. */ - 'regex'?: (string); - /** - * Indicates that prefix/path matching should be case insensitive. The default - * is true. - */ - 'case_sensitive'?: (_google_protobuf_BoolValue); + 'case_sensitive'?: (_google_protobuf_BoolValue | null); /** * Specifies a set of headers that the route should match on. The router will * check the request’s headers against all the specified headers in the route @@ -83,21 +77,29 @@ export interface RouteMatch { * the request with the same values (or based on presence if the value field * is not in the config). */ - 'headers'?: (_envoy_api_v2_route_HeaderMatcher)[]; + 'headers'?: (_envoy_config_route_v3_HeaderMatcher)[]; /** * Specifies a set of URL query parameters on which the route should * match. The router will check the query string from the *path* header * against all the specified query parameters. If the number of specified * query parameters is nonzero, they all must match the *path* header's * query string for a match to occur. + * + * .. note:: + * + * If query parameters are used to pass request message fields when + * `grpc_json_transcoder `_ + * is used, the transcoded message fields maybe different. The query parameters are + * url encoded, but the message fields are not. For example, if a query + * parameter is "foo%20bar", the message field will be "foo bar". */ - 'query_parameters'?: (_envoy_api_v2_route_QueryParameterMatcher)[]; + 'query_parameters'?: (_envoy_config_route_v3_QueryParameterMatcher)[]; /** * If specified, only gRPC requests will be matched. The router will check * that the content-type header has a application/grpc or one of the various * application/grpc+ values. */ - 'grpc'?: (_envoy_api_v2_route_RouteMatch_GrpcRouteMatchOptions); + 'grpc'?: (_envoy_config_route_v3_RouteMatch_GrpcRouteMatchOptions | null); /** * Indicates that the route should additionally match on a runtime key. Every time the route * is considered for a match, it must also fall under the percentage of matches indicated by @@ -116,7 +118,7 @@ export interface RouteMatch { * instance, a runtime key lookup returning the value "42" would parse as a FractionalPercent * whose numerator is 42 and denominator is HUNDRED. This preserves legacy semantics. */ - 'runtime_fraction'?: (_envoy_api_v2_core_RuntimeFractionalPercent); + 'runtime_fraction'?: (_envoy_config_core_v3_RuntimeFractionalPercent | null); /** * If specified, the route is a regular expression rule meaning that the * regex must match the *:path* header once the query string is removed. The entire path @@ -131,19 +133,38 @@ export interface RouteMatch { * on :path, etc. The issue with that is it is unclear how to generically deal with query string * stripping. This needs more thought.] */ - 'safe_regex'?: (_envoy_type_matcher_RegexMatcher); + 'safe_regex'?: (_envoy_type_matcher_v3_RegexMatcher | null); /** * If specified, the client tls context will be matched against the defined * match options. * * [#next-major-version: unify with RBAC] */ - 'tls_context'?: (_envoy_api_v2_route_RouteMatch_TlsContextMatchOptions); - 'path_specifier'?: "prefix"|"path"|"regex"|"safe_regex"; + 'tls_context'?: (_envoy_config_route_v3_RouteMatch_TlsContextMatchOptions | null); + /** + * If this is used as the matcher, the matcher will only match CONNECT requests. + * Note that this will not match HTTP/2 upgrade-style CONNECT requests + * (WebSocket and the like) as they are normalized in Envoy as HTTP/1.1 style + * upgrades. + * This is the only way to match CONNECT requests for HTTP/1.1. For HTTP/2, + * where Extended CONNECT requests may have a path, the path matchers will work if + * there is a path present. + * Note that CONNECT support is currently considered alpha in Envoy. + * [#comment: TODO(htuch): Replace the above comment with an alpha tag.] + */ + 'connect_matcher'?: (_envoy_config_route_v3_RouteMatch_ConnectMatcher | null); + /** + * Specifies a set of dynamic metadata matchers on which the route should match. + * The router will check the dynamic metadata against all the specified dynamic metadata matchers. + * If the number of specified dynamic metadata matchers is nonzero, they all must match the + * dynamic metadata for a match to occur. + */ + 'dynamic_metadata'?: (_envoy_type_matcher_v3_MetadataMatcher)[]; + 'path_specifier'?: "prefix"|"path"|"safe_regex"|"connect_matcher"; } /** - * [#next-free-field: 12] + * [#next-free-field: 14] */ export interface RouteMatch__Output { /** @@ -157,29 +178,10 @@ export interface RouteMatch__Output { */ 'path'?: (string); /** - * If specified, the route is a regular expression rule meaning that the - * regex must match the *:path* header once the query string is removed. The entire path - * (without the query string) must match the regex. The rule will not match if only a - * subsequence of the *:path* header matches the regex. The regex grammar is defined `here - * `_. - * - * Examples: - * - * * The regex ``/b[io]t`` matches the path * /bit* - * * The regex ``/b[io]t`` matches the path * /bot* - * * The regex ``/b[io]t`` does not match the path * /bite* - * * The regex ``/b[io]t`` does not match the path * /bit/bot* - * - * .. attention:: - * This field has been deprecated in favor of `safe_regex` as it is not safe for use with - * untrusted input in all cases. + * Indicates that prefix/path matching should be case sensitive. The default + * is true. Ignored for safe_regex matching. */ - 'regex'?: (string); - /** - * Indicates that prefix/path matching should be case insensitive. The default - * is true. - */ - 'case_sensitive'?: (_google_protobuf_BoolValue__Output); + 'case_sensitive': (_google_protobuf_BoolValue__Output | null); /** * Specifies a set of headers that the route should match on. The router will * check the request’s headers against all the specified headers in the route @@ -187,21 +189,29 @@ export interface RouteMatch__Output { * the request with the same values (or based on presence if the value field * is not in the config). */ - 'headers': (_envoy_api_v2_route_HeaderMatcher__Output)[]; + 'headers': (_envoy_config_route_v3_HeaderMatcher__Output)[]; /** * Specifies a set of URL query parameters on which the route should * match. The router will check the query string from the *path* header * against all the specified query parameters. If the number of specified * query parameters is nonzero, they all must match the *path* header's * query string for a match to occur. + * + * .. note:: + * + * If query parameters are used to pass request message fields when + * `grpc_json_transcoder `_ + * is used, the transcoded message fields maybe different. The query parameters are + * url encoded, but the message fields are not. For example, if a query + * parameter is "foo%20bar", the message field will be "foo bar". */ - 'query_parameters': (_envoy_api_v2_route_QueryParameterMatcher__Output)[]; + 'query_parameters': (_envoy_config_route_v3_QueryParameterMatcher__Output)[]; /** * If specified, only gRPC requests will be matched. The router will check * that the content-type header has a application/grpc or one of the various * application/grpc+ values. */ - 'grpc'?: (_envoy_api_v2_route_RouteMatch_GrpcRouteMatchOptions__Output); + 'grpc': (_envoy_config_route_v3_RouteMatch_GrpcRouteMatchOptions__Output | null); /** * Indicates that the route should additionally match on a runtime key. Every time the route * is considered for a match, it must also fall under the percentage of matches indicated by @@ -220,7 +230,7 @@ export interface RouteMatch__Output { * instance, a runtime key lookup returning the value "42" would parse as a FractionalPercent * whose numerator is 42 and denominator is HUNDRED. This preserves legacy semantics. */ - 'runtime_fraction'?: (_envoy_api_v2_core_RuntimeFractionalPercent__Output); + 'runtime_fraction': (_envoy_config_core_v3_RuntimeFractionalPercent__Output | null); /** * If specified, the route is a regular expression rule meaning that the * regex must match the *:path* header once the query string is removed. The entire path @@ -235,13 +245,32 @@ export interface RouteMatch__Output { * on :path, etc. The issue with that is it is unclear how to generically deal with query string * stripping. This needs more thought.] */ - 'safe_regex'?: (_envoy_type_matcher_RegexMatcher__Output); + 'safe_regex'?: (_envoy_type_matcher_v3_RegexMatcher__Output | null); /** * If specified, the client tls context will be matched against the defined * match options. * * [#next-major-version: unify with RBAC] */ - 'tls_context'?: (_envoy_api_v2_route_RouteMatch_TlsContextMatchOptions__Output); - 'path_specifier': "prefix"|"path"|"regex"|"safe_regex"; + 'tls_context': (_envoy_config_route_v3_RouteMatch_TlsContextMatchOptions__Output | null); + /** + * If this is used as the matcher, the matcher will only match CONNECT requests. + * Note that this will not match HTTP/2 upgrade-style CONNECT requests + * (WebSocket and the like) as they are normalized in Envoy as HTTP/1.1 style + * upgrades. + * This is the only way to match CONNECT requests for HTTP/1.1. For HTTP/2, + * where Extended CONNECT requests may have a path, the path matchers will work if + * there is a path present. + * Note that CONNECT support is currently considered alpha in Envoy. + * [#comment: TODO(htuch): Replace the above comment with an alpha tag.] + */ + 'connect_matcher'?: (_envoy_config_route_v3_RouteMatch_ConnectMatcher__Output | null); + /** + * Specifies a set of dynamic metadata matchers on which the route should match. + * The router will check the dynamic metadata against all the specified dynamic metadata matchers. + * If the number of specified dynamic metadata matchers is nonzero, they all must match the + * dynamic metadata for a match to occur. + */ + 'dynamic_metadata': (_envoy_type_matcher_v3_MetadataMatcher__Output)[]; + 'path_specifier': "prefix"|"path"|"safe_regex"|"connect_matcher"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/ScopedRouteConfiguration.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/ScopedRouteConfiguration.ts similarity index 58% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/ScopedRouteConfiguration.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/ScopedRouteConfiguration.ts index 02810bf02..5865eadd3 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/ScopedRouteConfiguration.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/ScopedRouteConfiguration.ts @@ -1,7 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/scoped_route.proto +// Original file: deps/envoy-api/envoy/config/route/v3/scoped_route.proto -export interface _envoy_api_v2_ScopedRouteConfiguration_Key_Fragment { +export interface _envoy_config_route_v3_ScopedRouteConfiguration_Key_Fragment { /** * A string to match against. */ @@ -9,7 +9,7 @@ export interface _envoy_api_v2_ScopedRouteConfiguration_Key_Fragment { 'type'?: "string_key"; } -export interface _envoy_api_v2_ScopedRouteConfiguration_Key_Fragment__Output { +export interface _envoy_config_route_v3_ScopedRouteConfiguration_Key_Fragment__Output { /** * A string to match against. */ @@ -19,45 +19,45 @@ export interface _envoy_api_v2_ScopedRouteConfiguration_Key_Fragment__Output { /** * Specifies a key which is matched against the output of the - * :ref:`scope_key_builder` + * :ref:`scope_key_builder` * specified in the HttpConnectionManager. The matching is done per HTTP * request and is dependent on the order of the fragments contained in the * Key. */ -export interface _envoy_api_v2_ScopedRouteConfiguration_Key { +export interface _envoy_config_route_v3_ScopedRouteConfiguration_Key { /** * The ordered set of fragments to match against. The order must match the * fragments in the corresponding - * :ref:`scope_key_builder`. + * :ref:`scope_key_builder`. */ - 'fragments'?: (_envoy_api_v2_ScopedRouteConfiguration_Key_Fragment)[]; + 'fragments'?: (_envoy_config_route_v3_ScopedRouteConfiguration_Key_Fragment)[]; } /** * Specifies a key which is matched against the output of the - * :ref:`scope_key_builder` + * :ref:`scope_key_builder` * specified in the HttpConnectionManager. The matching is done per HTTP * request and is dependent on the order of the fragments contained in the * Key. */ -export interface _envoy_api_v2_ScopedRouteConfiguration_Key__Output { +export interface _envoy_config_route_v3_ScopedRouteConfiguration_Key__Output { /** * The ordered set of fragments to match against. The order must match the * fragments in the corresponding - * :ref:`scope_key_builder`. + * :ref:`scope_key_builder`. */ - 'fragments': (_envoy_api_v2_ScopedRouteConfiguration_Key_Fragment__Output)[]; + 'fragments': (_envoy_config_route_v3_ScopedRouteConfiguration_Key_Fragment__Output)[]; } /** * Specifies a routing scope, which associates a - * :ref:`Key` to a - * :ref:`envoy_api_msg_RouteConfiguration` (identified by its resource name). + * :ref:`Key` to a + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration` (identified by its resource name). * * The HTTP connection manager builds up a table consisting of these Key to * RouteConfiguration mappings, and looks up the RouteConfiguration to use per * request according to the algorithm specified in the - * :ref:`scope_key_builder` + * :ref:`scope_key_builder` * assigned to the HttpConnectionManager. * * For example, with the following configurations (in YAML): @@ -79,7 +79,7 @@ export interface _envoy_api_v2_ScopedRouteConfiguration_Key__Output { * key: vip * * ScopedRouteConfiguration resources (specified statically via - * :ref:`scoped_route_configurations_list` + * :ref:`scoped_route_configurations_list` * or obtained dynamically via SRDS): * * .. code:: @@ -115,26 +115,30 @@ export interface ScopedRouteConfiguration { */ 'name'?: (string); /** - * The resource name to use for a :ref:`envoy_api_msg_DiscoveryRequest` to an - * RDS server to fetch the :ref:`envoy_api_msg_RouteConfiguration` associated + * The resource name to use for a :ref:`envoy_v3_api_msg_service.discovery.v3.DiscoveryRequest` to an + * RDS server to fetch the :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration` associated * with this scope. */ 'route_configuration_name'?: (string); /** * The key to match against. */ - 'key'?: (_envoy_api_v2_ScopedRouteConfiguration_Key); + 'key'?: (_envoy_config_route_v3_ScopedRouteConfiguration_Key | null); + /** + * Whether the RouteConfiguration should be loaded on demand. + */ + 'on_demand'?: (boolean); } /** * Specifies a routing scope, which associates a - * :ref:`Key` to a - * :ref:`envoy_api_msg_RouteConfiguration` (identified by its resource name). + * :ref:`Key` to a + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration` (identified by its resource name). * * The HTTP connection manager builds up a table consisting of these Key to * RouteConfiguration mappings, and looks up the RouteConfiguration to use per * request according to the algorithm specified in the - * :ref:`scope_key_builder` + * :ref:`scope_key_builder` * assigned to the HttpConnectionManager. * * For example, with the following configurations (in YAML): @@ -156,7 +160,7 @@ export interface ScopedRouteConfiguration { * key: vip * * ScopedRouteConfiguration resources (specified statically via - * :ref:`scoped_route_configurations_list` + * :ref:`scoped_route_configurations_list` * or obtained dynamically via SRDS): * * .. code:: @@ -192,13 +196,17 @@ export interface ScopedRouteConfiguration__Output { */ 'name': (string); /** - * The resource name to use for a :ref:`envoy_api_msg_DiscoveryRequest` to an - * RDS server to fetch the :ref:`envoy_api_msg_RouteConfiguration` associated + * The resource name to use for a :ref:`envoy_v3_api_msg_service.discovery.v3.DiscoveryRequest` to an + * RDS server to fetch the :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration` associated * with this scope. */ 'route_configuration_name': (string); /** * The key to match against. */ - 'key'?: (_envoy_api_v2_ScopedRouteConfiguration_Key__Output); + 'key': (_envoy_config_route_v3_ScopedRouteConfiguration_Key__Output | null); + /** + * Whether the RouteConfiguration should be loaded on demand. + */ + 'on_demand': (boolean); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/Tracing.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Tracing.ts similarity index 74% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/Tracing.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/Tracing.ts index 18b063339..962e9d51a 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/Tracing.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Tracing.ts @@ -1,7 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -import type { FractionalPercent as _envoy_type_FractionalPercent, FractionalPercent__Output as _envoy_type_FractionalPercent__Output } from '../../../../envoy/type/FractionalPercent'; -import type { CustomTag as _envoy_type_tracing_v2_CustomTag, CustomTag__Output as _envoy_type_tracing_v2_CustomTag__Output } from '../../../../envoy/type/tracing/v2/CustomTag'; +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../envoy/type/v3/FractionalPercent'; +import type { CustomTag as _envoy_type_tracing_v3_CustomTag, CustomTag__Output as _envoy_type_tracing_v3_CustomTag__Output } from '../../../../envoy/type/tracing/v3/CustomTag'; export interface Tracing { /** @@ -12,7 +12,7 @@ export interface Tracing { * `. * Default: 100% */ - 'client_sampling'?: (_envoy_type_FractionalPercent); + 'client_sampling'?: (_envoy_type_v3_FractionalPercent | null); /** * Target percentage of requests managed by this HTTP connection manager that will be randomly * selected for trace generation, if not requested by the client or not forced. This field is @@ -20,7 +20,7 @@ export interface Tracing { * :ref:`HTTP Connection Manager `. * Default: 100% */ - 'random_sampling'?: (_envoy_type_FractionalPercent); + 'random_sampling'?: (_envoy_type_v3_FractionalPercent | null); /** * Target percentage of requests managed by this HTTP connection manager that will be traced * after all other sampling checks have been applied (client-directed, force tracing, random @@ -31,16 +31,16 @@ export interface Tracing { * :ref:`HTTP Connection Manager `. * Default: 100% */ - 'overall_sampling'?: (_envoy_type_FractionalPercent); + 'overall_sampling'?: (_envoy_type_v3_FractionalPercent | null); /** * A list of custom tags with unique tag name to create tags for the active span. * It will take effect after merging with the :ref:`corresponding configuration - * ` + * ` * configured in the HTTP connection manager. If two tags with the same name are configured * each in the HTTP connection manager and the route level, the one configured here takes * priority. */ - 'custom_tags'?: (_envoy_type_tracing_v2_CustomTag)[]; + 'custom_tags'?: (_envoy_type_tracing_v3_CustomTag)[]; } export interface Tracing__Output { @@ -52,7 +52,7 @@ export interface Tracing__Output { * `. * Default: 100% */ - 'client_sampling'?: (_envoy_type_FractionalPercent__Output); + 'client_sampling': (_envoy_type_v3_FractionalPercent__Output | null); /** * Target percentage of requests managed by this HTTP connection manager that will be randomly * selected for trace generation, if not requested by the client or not forced. This field is @@ -60,7 +60,7 @@ export interface Tracing__Output { * :ref:`HTTP Connection Manager `. * Default: 100% */ - 'random_sampling'?: (_envoy_type_FractionalPercent__Output); + 'random_sampling': (_envoy_type_v3_FractionalPercent__Output | null); /** * Target percentage of requests managed by this HTTP connection manager that will be traced * after all other sampling checks have been applied (client-directed, force tracing, random @@ -71,14 +71,14 @@ export interface Tracing__Output { * :ref:`HTTP Connection Manager `. * Default: 100% */ - 'overall_sampling'?: (_envoy_type_FractionalPercent__Output); + 'overall_sampling': (_envoy_type_v3_FractionalPercent__Output | null); /** * A list of custom tags with unique tag name to create tags for the active span. * It will take effect after merging with the :ref:`corresponding configuration - * ` + * ` * configured in the HTTP connection manager. If two tags with the same name are configured * each in the HTTP connection manager and the route level, the one configured here takes * priority. */ - 'custom_tags': (_envoy_type_tracing_v2_CustomTag__Output)[]; + 'custom_tags': (_envoy_type_tracing_v3_CustomTag__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Vhds.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Vhds.ts new file mode 100644 index 000000000..b8a37be65 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/Vhds.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/config/route/v3/route.proto + +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../envoy/config/core/v3/ConfigSource'; + +export interface Vhds { + /** + * Configuration source specifier for VHDS. + */ + 'config_source'?: (_envoy_config_core_v3_ConfigSource | null); +} + +export interface Vhds__Output { + /** + * Configuration source specifier for VHDS. + */ + 'config_source': (_envoy_config_core_v3_ConfigSource__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/VirtualCluster.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/VirtualCluster.ts similarity index 58% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/VirtualCluster.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/VirtualCluster.ts index f072710ce..7674da733 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/VirtualCluster.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/VirtualCluster.ts @@ -1,7 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -import type { RequestMethod as _envoy_api_v2_core_RequestMethod } from '../../../../envoy/api/v2/core/RequestMethod'; -import type { HeaderMatcher as _envoy_api_v2_route_HeaderMatcher, HeaderMatcher__Output as _envoy_api_v2_route_HeaderMatcher__Output } from '../../../../envoy/api/v2/route/HeaderMatcher'; +import type { HeaderMatcher as _envoy_config_route_v3_HeaderMatcher, HeaderMatcher__Output as _envoy_config_route_v3_HeaderMatcher__Output } from '../../../../envoy/config/route/v3/HeaderMatcher'; /** * A virtual cluster is a way of specifying a regex matching rule against @@ -23,42 +22,18 @@ import type { HeaderMatcher as _envoy_api_v2_route_HeaderMatcher, HeaderMatcher_ * statistics output are not free. */ export interface VirtualCluster { - /** - * Specifies a regex pattern to use for matching requests. The entire path of the request - * must match the regex. The regex grammar used is defined `here - * `_. - * - * Examples: - * - * * The regex ``/rides/\d+`` matches the path * /rides/0* - * * The regex ``/rides/\d+`` matches the path * /rides/123* - * * The regex ``/rides/\d+`` does not match the path * /rides/123/456* - * - * .. attention:: - * This field has been deprecated in favor of `headers` as it is not safe for use with - * untrusted input in all cases. - */ - 'pattern'?: (string); /** * Specifies the name of the virtual cluster. The virtual cluster name as well * as the virtual host name are used when emitting statistics. The statistics are emitted by the * router filter and are documented :ref:`here `. */ 'name'?: (string); - /** - * Optionally specifies the HTTP method to match on. For example GET, PUT, - * etc. - * - * .. attention:: - * This field has been deprecated in favor of `headers`. - */ - 'method'?: (_envoy_api_v2_core_RequestMethod | keyof typeof _envoy_api_v2_core_RequestMethod); /** * Specifies a list of header matchers to use for matching requests. Each specified header must * match. The pseudo-headers `:path` and `:method` can be used to match the request path and * method, respectively. */ - 'headers'?: (_envoy_api_v2_route_HeaderMatcher)[]; + 'headers'?: (_envoy_config_route_v3_HeaderMatcher)[]; } /** @@ -81,40 +56,16 @@ export interface VirtualCluster { * statistics output are not free. */ export interface VirtualCluster__Output { - /** - * Specifies a regex pattern to use for matching requests. The entire path of the request - * must match the regex. The regex grammar used is defined `here - * `_. - * - * Examples: - * - * * The regex ``/rides/\d+`` matches the path * /rides/0* - * * The regex ``/rides/\d+`` matches the path * /rides/123* - * * The regex ``/rides/\d+`` does not match the path * /rides/123/456* - * - * .. attention:: - * This field has been deprecated in favor of `headers` as it is not safe for use with - * untrusted input in all cases. - */ - 'pattern': (string); /** * Specifies the name of the virtual cluster. The virtual cluster name as well * as the virtual host name are used when emitting statistics. The statistics are emitted by the * router filter and are documented :ref:`here `. */ 'name': (string); - /** - * Optionally specifies the HTTP method to match on. For example GET, PUT, - * etc. - * - * .. attention:: - * This field has been deprecated in favor of `headers`. - */ - 'method': (keyof typeof _envoy_api_v2_core_RequestMethod); /** * Specifies a list of header matchers to use for matching requests. Each specified header must * match. The pseudo-headers `:path` and `:method` can be used to match the request path and * method, respectively. */ - 'headers': (_envoy_api_v2_route_HeaderMatcher__Output)[]; + 'headers': (_envoy_config_route_v3_HeaderMatcher__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/VirtualHost.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/VirtualHost.ts similarity index 70% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/VirtualHost.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/VirtualHost.ts index ad806e949..017900ed9 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/VirtualHost.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/VirtualHost.ts @@ -1,19 +1,18 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -import type { Route as _envoy_api_v2_route_Route, Route__Output as _envoy_api_v2_route_Route__Output } from '../../../../envoy/api/v2/route/Route'; -import type { VirtualCluster as _envoy_api_v2_route_VirtualCluster, VirtualCluster__Output as _envoy_api_v2_route_VirtualCluster__Output } from '../../../../envoy/api/v2/route/VirtualCluster'; -import type { RateLimit as _envoy_api_v2_route_RateLimit, RateLimit__Output as _envoy_api_v2_route_RateLimit__Output } from '../../../../envoy/api/v2/route/RateLimit'; -import type { HeaderValueOption as _envoy_api_v2_core_HeaderValueOption, HeaderValueOption__Output as _envoy_api_v2_core_HeaderValueOption__Output } from '../../../../envoy/api/v2/core/HeaderValueOption'; -import type { CorsPolicy as _envoy_api_v2_route_CorsPolicy, CorsPolicy__Output as _envoy_api_v2_route_CorsPolicy__Output } from '../../../../envoy/api/v2/route/CorsPolicy'; -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import type { Route as _envoy_config_route_v3_Route, Route__Output as _envoy_config_route_v3_Route__Output } from '../../../../envoy/config/route/v3/Route'; +import type { VirtualCluster as _envoy_config_route_v3_VirtualCluster, VirtualCluster__Output as _envoy_config_route_v3_VirtualCluster__Output } from '../../../../envoy/config/route/v3/VirtualCluster'; +import type { RateLimit as _envoy_config_route_v3_RateLimit, RateLimit__Output as _envoy_config_route_v3_RateLimit__Output } from '../../../../envoy/config/route/v3/RateLimit'; +import type { HeaderValueOption as _envoy_config_core_v3_HeaderValueOption, HeaderValueOption__Output as _envoy_config_core_v3_HeaderValueOption__Output } from '../../../../envoy/config/core/v3/HeaderValueOption'; +import type { CorsPolicy as _envoy_config_route_v3_CorsPolicy, CorsPolicy__Output as _envoy_config_route_v3_CorsPolicy__Output } from '../../../../envoy/config/route/v3/CorsPolicy'; import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; -import type { RetryPolicy as _envoy_api_v2_route_RetryPolicy, RetryPolicy__Output as _envoy_api_v2_route_RetryPolicy__Output } from '../../../../envoy/api/v2/route/RetryPolicy'; -import type { HedgePolicy as _envoy_api_v2_route_HedgePolicy, HedgePolicy__Output as _envoy_api_v2_route_HedgePolicy__Output } from '../../../../envoy/api/v2/route/HedgePolicy'; +import type { RetryPolicy as _envoy_config_route_v3_RetryPolicy, RetryPolicy__Output as _envoy_config_route_v3_RetryPolicy__Output } from '../../../../envoy/config/route/v3/RetryPolicy'; +import type { HedgePolicy as _envoy_config_route_v3_HedgePolicy, HedgePolicy__Output as _envoy_config_route_v3_HedgePolicy__Output } from '../../../../envoy/config/route/v3/HedgePolicy'; import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto -export enum _envoy_api_v2_route_VirtualHost_TlsRequirementType { +export enum _envoy_config_route_v3_VirtualHost_TlsRequirementType { /** * No TLS requirement for the virtual host. */ @@ -69,57 +68,49 @@ export interface VirtualHost { * The list of routes that will be matched, in order, for incoming requests. * The first route that matches will be used. */ - 'routes'?: (_envoy_api_v2_route_Route)[]; + 'routes'?: (_envoy_config_route_v3_Route)[]; /** * Specifies the type of TLS enforcement the virtual host expects. If this option is not * specified, there is no TLS requirement for the virtual host. */ - 'require_tls'?: (_envoy_api_v2_route_VirtualHost_TlsRequirementType | keyof typeof _envoy_api_v2_route_VirtualHost_TlsRequirementType); + 'require_tls'?: (_envoy_config_route_v3_VirtualHost_TlsRequirementType | keyof typeof _envoy_config_route_v3_VirtualHost_TlsRequirementType); /** * A list of virtual clusters defined for this virtual host. Virtual clusters * are used for additional statistics gathering. */ - 'virtual_clusters'?: (_envoy_api_v2_route_VirtualCluster)[]; + 'virtual_clusters'?: (_envoy_config_route_v3_VirtualCluster)[]; /** * Specifies a set of rate limit configurations that will be applied to the * virtual host. */ - 'rate_limits'?: (_envoy_api_v2_route_RateLimit)[]; + 'rate_limits'?: (_envoy_config_route_v3_RateLimit)[]; /** * Specifies a list of HTTP headers that should be added to each request * handled by this virtual host. Headers specified at this level are applied - * after headers from enclosed :ref:`envoy_api_msg_route.Route` and before headers from the - * enclosing :ref:`envoy_api_msg_RouteConfiguration`. For more information, including + * after headers from enclosed :ref:`envoy_v3_api_msg_config.route.v3.Route` and before headers from the + * enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including * details on header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'request_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Indicates that the virtual host has a CORS policy. */ - 'cors'?: (_envoy_api_v2_route_CorsPolicy); + 'cors'?: (_envoy_config_route_v3_CorsPolicy | null); /** * Specifies a list of HTTP headers that should be added to each response * handled by this virtual host. Headers specified at this level are applied - * after headers from enclosed :ref:`envoy_api_msg_route.Route` and before headers from the - * enclosing :ref:`envoy_api_msg_RouteConfiguration`. For more information, including + * after headers from enclosed :ref:`envoy_v3_api_msg_config.route.v3.Route` and before headers from the + * enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including * details on header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'response_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'response_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Specifies a list of HTTP headers that should be removed from each response * handled by this virtual host. */ 'response_headers_to_remove'?: (string)[]; - /** - * The per_filter_config field can be used to provide virtual host-specific - * configurations for filters. The key should match the filter name, such as - * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter - * specific; see the :ref:`HTTP filter documentation ` - * for if and how it is utilized. - */ - 'per_filter_config'?: ({[key: string]: _google_protobuf_Struct}); /** * Specifies a list of HTTP headers that should be removed from each request * handled by this virtual host. @@ -133,7 +124,7 @@ export interface VirtualHost { * will see the attempt count as perceived by the second Envoy. Defaults to false. * This header is unaffected by the * :ref:`suppress_envoy_headers - * ` flag. + * ` flag. * * [#next-major-version: rename to include_attempt_count_in_request.] */ @@ -144,6 +135,9 @@ export interface VirtualHost { * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter * specific; see the :ref:`HTTP filter documentation ` * for if and how it is utilized. + * [#comment: An entry's value may be wrapped in a + * :ref:`FilterConfig` + * message to specify additional options.] */ 'typed_per_filter_config'?: ({[key: string]: _google_protobuf_Any}); /** @@ -151,19 +145,19 @@ export interface VirtualHost { * route level entry will take precedence over this config and it'll be treated * independently (e.g.: values are not inherited). */ - 'retry_policy'?: (_envoy_api_v2_route_RetryPolicy); + 'retry_policy'?: (_envoy_config_route_v3_RetryPolicy | null); /** * Indicates the hedge policy for all routes in this virtual host. Note that setting a * route level entry will take precedence over this config and it'll be treated * independently (e.g.: values are not inherited). */ - 'hedge_policy'?: (_envoy_api_v2_route_HedgePolicy); + 'hedge_policy'?: (_envoy_config_route_v3_HedgePolicy | null); /** * The maximum bytes which will be buffered for retries and shadowing. * If set and a route-specific limit is not set, the bytes actually buffered will be the minimum * value of this and the listener per_connection_buffer_limit_bytes. */ - 'per_request_buffer_limit_bytes'?: (_google_protobuf_UInt32Value); + 'per_request_buffer_limit_bytes'?: (_google_protobuf_UInt32Value | null); /** * Decides whether the :ref:`x-envoy-attempt-count * ` header should be included @@ -172,17 +166,17 @@ export interface VirtualHost { * will see the attempt count as perceived by the Envoy closest upstream from itself. Defaults to false. * This header is unaffected by the * :ref:`suppress_envoy_headers - * ` flag. + * ` flag. */ 'include_attempt_count_in_response'?: (boolean); /** * [#not-implemented-hide:] * Specifies the configuration for retry policy extension. Note that setting a route level entry * will take precedence over this config and it'll be treated independently (e.g.: values are not - * inherited). :ref:`Retry policy ` should not be + * inherited). :ref:`Retry policy ` should not be * set if this field is used. */ - 'retry_policy_typed_config'?: (_google_protobuf_Any); + 'retry_policy_typed_config'?: (_google_protobuf_Any | null); } /** @@ -224,57 +218,49 @@ export interface VirtualHost__Output { * The list of routes that will be matched, in order, for incoming requests. * The first route that matches will be used. */ - 'routes': (_envoy_api_v2_route_Route__Output)[]; + 'routes': (_envoy_config_route_v3_Route__Output)[]; /** * Specifies the type of TLS enforcement the virtual host expects. If this option is not * specified, there is no TLS requirement for the virtual host. */ - 'require_tls': (keyof typeof _envoy_api_v2_route_VirtualHost_TlsRequirementType); + 'require_tls': (keyof typeof _envoy_config_route_v3_VirtualHost_TlsRequirementType); /** * A list of virtual clusters defined for this virtual host. Virtual clusters * are used for additional statistics gathering. */ - 'virtual_clusters': (_envoy_api_v2_route_VirtualCluster__Output)[]; + 'virtual_clusters': (_envoy_config_route_v3_VirtualCluster__Output)[]; /** * Specifies a set of rate limit configurations that will be applied to the * virtual host. */ - 'rate_limits': (_envoy_api_v2_route_RateLimit__Output)[]; + 'rate_limits': (_envoy_config_route_v3_RateLimit__Output)[]; /** * Specifies a list of HTTP headers that should be added to each request * handled by this virtual host. Headers specified at this level are applied - * after headers from enclosed :ref:`envoy_api_msg_route.Route` and before headers from the - * enclosing :ref:`envoy_api_msg_RouteConfiguration`. For more information, including + * after headers from enclosed :ref:`envoy_v3_api_msg_config.route.v3.Route` and before headers from the + * enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including * details on header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'request_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Indicates that the virtual host has a CORS policy. */ - 'cors'?: (_envoy_api_v2_route_CorsPolicy__Output); + 'cors': (_envoy_config_route_v3_CorsPolicy__Output | null); /** * Specifies a list of HTTP headers that should be added to each response * handled by this virtual host. Headers specified at this level are applied - * after headers from enclosed :ref:`envoy_api_msg_route.Route` and before headers from the - * enclosing :ref:`envoy_api_msg_RouteConfiguration`. For more information, including + * after headers from enclosed :ref:`envoy_v3_api_msg_config.route.v3.Route` and before headers from the + * enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including * details on header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'response_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'response_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Specifies a list of HTTP headers that should be removed from each response * handled by this virtual host. */ 'response_headers_to_remove': (string)[]; - /** - * The per_filter_config field can be used to provide virtual host-specific - * configurations for filters. The key should match the filter name, such as - * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter - * specific; see the :ref:`HTTP filter documentation ` - * for if and how it is utilized. - */ - 'per_filter_config'?: ({[key: string]: _google_protobuf_Struct__Output}); /** * Specifies a list of HTTP headers that should be removed from each request * handled by this virtual host. @@ -288,7 +274,7 @@ export interface VirtualHost__Output { * will see the attempt count as perceived by the second Envoy. Defaults to false. * This header is unaffected by the * :ref:`suppress_envoy_headers - * ` flag. + * ` flag. * * [#next-major-version: rename to include_attempt_count_in_request.] */ @@ -299,26 +285,29 @@ export interface VirtualHost__Output { * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter * specific; see the :ref:`HTTP filter documentation ` * for if and how it is utilized. + * [#comment: An entry's value may be wrapped in a + * :ref:`FilterConfig` + * message to specify additional options.] */ - 'typed_per_filter_config'?: ({[key: string]: _google_protobuf_Any__Output}); + 'typed_per_filter_config': ({[key: string]: _google_protobuf_Any__Output}); /** * Indicates the retry policy for all routes in this virtual host. Note that setting a * route level entry will take precedence over this config and it'll be treated * independently (e.g.: values are not inherited). */ - 'retry_policy'?: (_envoy_api_v2_route_RetryPolicy__Output); + 'retry_policy': (_envoy_config_route_v3_RetryPolicy__Output | null); /** * Indicates the hedge policy for all routes in this virtual host. Note that setting a * route level entry will take precedence over this config and it'll be treated * independently (e.g.: values are not inherited). */ - 'hedge_policy'?: (_envoy_api_v2_route_HedgePolicy__Output); + 'hedge_policy': (_envoy_config_route_v3_HedgePolicy__Output | null); /** * The maximum bytes which will be buffered for retries and shadowing. * If set and a route-specific limit is not set, the bytes actually buffered will be the minimum * value of this and the listener per_connection_buffer_limit_bytes. */ - 'per_request_buffer_limit_bytes'?: (_google_protobuf_UInt32Value__Output); + 'per_request_buffer_limit_bytes': (_google_protobuf_UInt32Value__Output | null); /** * Decides whether the :ref:`x-envoy-attempt-count * ` header should be included @@ -327,15 +316,15 @@ export interface VirtualHost__Output { * will see the attempt count as perceived by the Envoy closest upstream from itself. Defaults to false. * This header is unaffected by the * :ref:`suppress_envoy_headers - * ` flag. + * ` flag. */ 'include_attempt_count_in_response': (boolean); /** * [#not-implemented-hide:] * Specifies the configuration for retry policy extension. Note that setting a route level entry * will take precedence over this config and it'll be treated independently (e.g.: values are not - * inherited). :ref:`Retry policy ` should not be + * inherited). :ref:`Retry policy ` should not be * set if this field is used. */ - 'retry_policy_typed_config'?: (_google_protobuf_Any__Output); + 'retry_policy_typed_config': (_google_protobuf_Any__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/WeightedCluster.ts b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/WeightedCluster.ts similarity index 52% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/route/WeightedCluster.ts rename to packages/grpc-js-xds/src/generated/envoy/config/route/v3/WeightedCluster.ts index 5b283404b..e734073be 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/route/WeightedCluster.ts +++ b/packages/grpc-js-xds/src/generated/envoy/config/route/v3/WeightedCluster.ts @@ -1,63 +1,82 @@ -// Original file: deps/envoy-api/envoy/api/v2/route/route_components.proto +// Original file: deps/envoy-api/envoy/config/route/v3/route_components.proto import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; -import type { Metadata as _envoy_api_v2_core_Metadata, Metadata__Output as _envoy_api_v2_core_Metadata__Output } from '../../../../envoy/api/v2/core/Metadata'; -import type { HeaderValueOption as _envoy_api_v2_core_HeaderValueOption, HeaderValueOption__Output as _envoy_api_v2_core_HeaderValueOption__Output } from '../../../../envoy/api/v2/core/HeaderValueOption'; -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; +import type { Metadata as _envoy_config_core_v3_Metadata, Metadata__Output as _envoy_config_core_v3_Metadata__Output } from '../../../../envoy/config/core/v3/Metadata'; +import type { HeaderValueOption as _envoy_config_core_v3_HeaderValueOption, HeaderValueOption__Output as _envoy_config_core_v3_HeaderValueOption__Output } from '../../../../envoy/config/core/v3/HeaderValueOption'; import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; /** - * [#next-free-field: 11] + * [#next-free-field: 13] */ -export interface _envoy_api_v2_route_WeightedCluster_ClusterWeight { +export interface _envoy_config_route_v3_WeightedCluster_ClusterWeight { /** + * Only one of *name* and *cluster_header* may be specified. + * [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1}] * Name of the upstream cluster. The cluster must exist in the * :ref:`cluster manager configuration `. */ 'name'?: (string); + /** + * Only one of *name* and *cluster_header* may be specified. + * [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1 }] + * Envoy will determine the cluster to route to by reading the value of the + * HTTP header named by cluster_header from the request headers. If the + * header is not found or the referenced cluster does not exist, Envoy will + * return a 404 response. + * + * .. attention:: + * + * Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1 + * *Host* header. Thus, if attempting to match on *Host*, match on *:authority* instead. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. + */ + 'cluster_header'?: (string); /** * An integer between 0 and :ref:`total_weight - * `. When a request matches the route, + * `. When a request matches the route, * the choice of an upstream cluster is determined by its weight. The sum of weights across all * entries in the clusters array must add up to the total_weight, which defaults to 100. */ - 'weight'?: (_google_protobuf_UInt32Value); + 'weight'?: (_google_protobuf_UInt32Value | null); /** * Optional endpoint metadata match criteria used by the subset load balancer. Only endpoints in * the upstream cluster with metadata matching what is set in this field will be considered for * load balancing. Note that this will be merged with what's provided in - * :ref:`RouteAction.metadata_match `, with + * :ref:`RouteAction.metadata_match `, with * values here taking precedence. The filter name should be specified as *envoy.lb*. */ - 'metadata_match'?: (_envoy_api_v2_core_Metadata); + 'metadata_match'?: (_envoy_config_core_v3_Metadata | null); /** * Specifies a list of headers to be added to requests when this cluster is selected - * through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. * Headers specified at this level are applied before headers from the enclosing - * :ref:`envoy_api_msg_route.Route`, :ref:`envoy_api_msg_route.VirtualHost`, and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including details on + * :ref:`envoy_v3_api_msg_config.route.v3.Route`, :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost`, and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'request_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Specifies a list of HTTP headers that should be removed from each request when - * this cluster is selected through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * this cluster is selected through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. */ 'request_headers_to_remove'?: (string)[]; /** * Specifies a list of headers to be added to responses when this cluster is selected - * through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. * Headers specified at this level are applied before headers from the enclosing - * :ref:`envoy_api_msg_route.Route`, :ref:`envoy_api_msg_route.VirtualHost`, and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including details on + * :ref:`envoy_v3_api_msg_config.route.v3.Route`, :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost`, and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'response_headers_to_add'?: (_envoy_api_v2_core_HeaderValueOption)[]; + 'response_headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; /** * Specifies a list of headers to be removed from responses when this cluster is selected - * through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. */ 'response_headers_to_remove'?: (string)[]; /** @@ -66,70 +85,91 @@ export interface _envoy_api_v2_route_WeightedCluster_ClusterWeight { * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter * specific; see the :ref:`HTTP filter documentation ` * for if and how it is utilized. + * [#comment: An entry's value may be wrapped in a + * :ref:`FilterConfig` + * message to specify additional options.] */ - 'per_filter_config'?: ({[key: string]: _google_protobuf_Struct}); + 'typed_per_filter_config'?: ({[key: string]: _google_protobuf_Any}); /** - * The per_filter_config field can be used to provide weighted cluster-specific - * configurations for filters. The key should match the filter name, such as - * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter - * specific; see the :ref:`HTTP filter documentation ` - * for if and how it is utilized. + * Indicates that during forwarding, the host header will be swapped with + * this value. */ - 'typed_per_filter_config'?: ({[key: string]: _google_protobuf_Any}); + 'host_rewrite_literal'?: (string); + 'host_rewrite_specifier'?: "host_rewrite_literal"; } /** - * [#next-free-field: 11] + * [#next-free-field: 13] */ -export interface _envoy_api_v2_route_WeightedCluster_ClusterWeight__Output { +export interface _envoy_config_route_v3_WeightedCluster_ClusterWeight__Output { /** + * Only one of *name* and *cluster_header* may be specified. + * [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1}] * Name of the upstream cluster. The cluster must exist in the * :ref:`cluster manager configuration `. */ 'name': (string); + /** + * Only one of *name* and *cluster_header* may be specified. + * [#next-major-version: Need to add back the validation rule: (validate.rules).string = {min_len: 1 }] + * Envoy will determine the cluster to route to by reading the value of the + * HTTP header named by cluster_header from the request headers. If the + * header is not found or the referenced cluster does not exist, Envoy will + * return a 404 response. + * + * .. attention:: + * + * Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1 + * *Host* header. Thus, if attempting to match on *Host*, match on *:authority* instead. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. + */ + 'cluster_header': (string); /** * An integer between 0 and :ref:`total_weight - * `. When a request matches the route, + * `. When a request matches the route, * the choice of an upstream cluster is determined by its weight. The sum of weights across all * entries in the clusters array must add up to the total_weight, which defaults to 100. */ - 'weight'?: (_google_protobuf_UInt32Value__Output); + 'weight': (_google_protobuf_UInt32Value__Output | null); /** * Optional endpoint metadata match criteria used by the subset load balancer. Only endpoints in * the upstream cluster with metadata matching what is set in this field will be considered for * load balancing. Note that this will be merged with what's provided in - * :ref:`RouteAction.metadata_match `, with + * :ref:`RouteAction.metadata_match `, with * values here taking precedence. The filter name should be specified as *envoy.lb*. */ - 'metadata_match'?: (_envoy_api_v2_core_Metadata__Output); + 'metadata_match': (_envoy_config_core_v3_Metadata__Output | null); /** * Specifies a list of headers to be added to requests when this cluster is selected - * through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. * Headers specified at this level are applied before headers from the enclosing - * :ref:`envoy_api_msg_route.Route`, :ref:`envoy_api_msg_route.VirtualHost`, and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including details on + * :ref:`envoy_v3_api_msg_config.route.v3.Route`, :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost`, and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'request_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'request_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Specifies a list of HTTP headers that should be removed from each request when - * this cluster is selected through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * this cluster is selected through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. */ 'request_headers_to_remove': (string)[]; /** * Specifies a list of headers to be added to responses when this cluster is selected - * through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. * Headers specified at this level are applied before headers from the enclosing - * :ref:`envoy_api_msg_route.Route`, :ref:`envoy_api_msg_route.VirtualHost`, and - * :ref:`envoy_api_msg_RouteConfiguration`. For more information, including details on + * :ref:`envoy_v3_api_msg_config.route.v3.Route`, :ref:`envoy_v3_api_msg_config.route.v3.VirtualHost`, and + * :ref:`envoy_v3_api_msg_config.route.v3.RouteConfiguration`. For more information, including details on * header value syntax, see the documentation on :ref:`custom request headers * `. */ - 'response_headers_to_add': (_envoy_api_v2_core_HeaderValueOption__Output)[]; + 'response_headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; /** * Specifies a list of headers to be removed from responses when this cluster is selected - * through the enclosing :ref:`envoy_api_msg_route.RouteAction`. + * through the enclosing :ref:`envoy_v3_api_msg_config.route.v3.RouteAction`. */ 'response_headers_to_remove': (string)[]; /** @@ -138,22 +178,23 @@ export interface _envoy_api_v2_route_WeightedCluster_ClusterWeight__Output { * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter * specific; see the :ref:`HTTP filter documentation ` * for if and how it is utilized. + * [#comment: An entry's value may be wrapped in a + * :ref:`FilterConfig` + * message to specify additional options.] */ - 'per_filter_config'?: ({[key: string]: _google_protobuf_Struct__Output}); + 'typed_per_filter_config': ({[key: string]: _google_protobuf_Any__Output}); /** - * The per_filter_config field can be used to provide weighted cluster-specific - * configurations for filters. The key should match the filter name, such as - * *envoy.filters.http.buffer* for the HTTP buffer filter. Use of this field is filter - * specific; see the :ref:`HTTP filter documentation ` - * for if and how it is utilized. + * Indicates that during forwarding, the host header will be swapped with + * this value. */ - 'typed_per_filter_config'?: ({[key: string]: _google_protobuf_Any__Output}); + 'host_rewrite_literal'?: (string); + 'host_rewrite_specifier': "host_rewrite_literal"; } /** - * Compared to the :ref:`cluster ` field that specifies a + * Compared to the :ref:`cluster ` field that specifies a * single upstream cluster as the target of a request, the :ref:`weighted_clusters - * ` option allows for specification of + * ` option allows for specification of * multiple upstream clusters along with weights that indicate the percentage of * traffic to be forwarded to each cluster. The router selects an upstream cluster based on the * weights. @@ -162,7 +203,7 @@ export interface WeightedCluster { /** * Specifies one or more upstream clusters associated with the route. */ - 'clusters'?: (_envoy_api_v2_route_WeightedCluster_ClusterWeight)[]; + 'clusters'?: (_envoy_config_route_v3_WeightedCluster_ClusterWeight)[]; /** * Specifies the runtime key prefix that should be used to construct the * runtime keys associated with each cluster. When the *runtime_key_prefix* is @@ -178,13 +219,13 @@ export interface WeightedCluster { * Specifies the total weight across all clusters. The sum of all cluster weights must equal this * value, which must be greater than 0. Defaults to 100. */ - 'total_weight'?: (_google_protobuf_UInt32Value); + 'total_weight'?: (_google_protobuf_UInt32Value | null); } /** - * Compared to the :ref:`cluster ` field that specifies a + * Compared to the :ref:`cluster ` field that specifies a * single upstream cluster as the target of a request, the :ref:`weighted_clusters - * ` option allows for specification of + * ` option allows for specification of * multiple upstream clusters along with weights that indicate the percentage of * traffic to be forwarded to each cluster. The router selects an upstream cluster based on the * weights. @@ -193,7 +234,7 @@ export interface WeightedCluster__Output { /** * Specifies one or more upstream clusters associated with the route. */ - 'clusters': (_envoy_api_v2_route_WeightedCluster_ClusterWeight__Output)[]; + 'clusters': (_envoy_config_route_v3_WeightedCluster_ClusterWeight__Output)[]; /** * Specifies the runtime key prefix that should be used to construct the * runtime keys associated with each cluster. When the *runtime_key_prefix* is @@ -209,5 +250,5 @@ export interface WeightedCluster__Output { * Specifies the total weight across all clusters. The sum of all cluster weights must equal this * value, which must be greater than 0. Defaults to 100. */ - 'total_weight'?: (_google_protobuf_UInt32Value__Output); + 'total_weight': (_google_protobuf_UInt32Value__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/config/trace/v2/Tracing.ts b/packages/grpc-js-xds/src/generated/envoy/config/trace/v2/Tracing.ts deleted file mode 100644 index 629e3f1cc..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/config/trace/v2/Tracing.ts +++ /dev/null @@ -1,114 +0,0 @@ -// Original file: deps/envoy-api/envoy/config/trace/v2/http_tracer.proto - -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; - -/** - * Configuration for an HTTP tracer provider used by Envoy. - * - * The configuration is defined by the - * :ref:`HttpConnectionManager.Tracing ` - * :ref:`provider ` - * field. - */ -export interface _envoy_config_trace_v2_Tracing_Http { - /** - * The name of the HTTP trace driver to instantiate. The name must match a - * supported HTTP trace driver. Built-in trace drivers: - * - * - *envoy.tracers.lightstep* - * - *envoy.tracers.zipkin* - * - *envoy.tracers.dynamic_ot* - * - *envoy.tracers.datadog* - * - *envoy.tracers.opencensus* - * - *envoy.tracers.xray* - */ - 'name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); - /** - * Trace driver specific configuration which depends on the driver being instantiated. - * See the trace drivers for examples: - * - * - :ref:`LightstepConfig ` - * - :ref:`ZipkinConfig ` - * - :ref:`DynamicOtConfig ` - * - :ref:`DatadogConfig ` - * - :ref:`OpenCensusConfig ` - * - :ref:`AWS X-Ray ` - */ - 'config_type'?: "config"|"typed_config"; -} - -/** - * Configuration for an HTTP tracer provider used by Envoy. - * - * The configuration is defined by the - * :ref:`HttpConnectionManager.Tracing ` - * :ref:`provider ` - * field. - */ -export interface _envoy_config_trace_v2_Tracing_Http__Output { - /** - * The name of the HTTP trace driver to instantiate. The name must match a - * supported HTTP trace driver. Built-in trace drivers: - * - * - *envoy.tracers.lightstep* - * - *envoy.tracers.zipkin* - * - *envoy.tracers.dynamic_ot* - * - *envoy.tracers.datadog* - * - *envoy.tracers.opencensus* - * - *envoy.tracers.xray* - */ - 'name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); - /** - * Trace driver specific configuration which depends on the driver being instantiated. - * See the trace drivers for examples: - * - * - :ref:`LightstepConfig ` - * - :ref:`ZipkinConfig ` - * - :ref:`DynamicOtConfig ` - * - :ref:`DatadogConfig ` - * - :ref:`OpenCensusConfig ` - * - :ref:`AWS X-Ray ` - */ - 'config_type': "config"|"typed_config"; -} - -/** - * The tracing configuration specifies settings for an HTTP tracer provider used by Envoy. - * - * Envoy may support other tracers in the future, but right now the HTTP tracer is the only one - * supported. - * - * .. attention:: - * - * Use of this message type has been deprecated in favor of direct use of - * :ref:`Tracing.Http `. - */ -export interface Tracing { - /** - * Provides configuration for the HTTP tracer. - */ - 'http'?: (_envoy_config_trace_v2_Tracing_Http); -} - -/** - * The tracing configuration specifies settings for an HTTP tracer provider used by Envoy. - * - * Envoy may support other tracers in the future, but right now the HTTP tracer is the only one - * supported. - * - * .. attention:: - * - * Use of this message type has been deprecated in favor of direct use of - * :ref:`Tracing.Http `. - */ -export interface Tracing__Output { - /** - * Provides configuration for the HTTP tracer. - */ - 'http'?: (_envoy_config_trace_v2_Tracing_Http__Output); -} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/trace/v3/Tracing.ts b/packages/grpc-js-xds/src/generated/envoy/config/trace/v3/Tracing.ts new file mode 100644 index 000000000..9b9859bc5 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/config/trace/v3/Tracing.ts @@ -0,0 +1,85 @@ +// Original file: deps/envoy-api/envoy/config/trace/v3/http_tracer.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; + +/** + * Configuration for an HTTP tracer provider used by Envoy. + * + * The configuration is defined by the + * :ref:`HttpConnectionManager.Tracing ` + * :ref:`provider ` + * field. + */ +export interface _envoy_config_trace_v3_Tracing_Http { + /** + * The name of the HTTP trace driver to instantiate. The name must match a + * supported HTTP trace driver. + * See the :ref:`extensions listed in typed_config below ` for the default list of the HTTP trace driver. + */ + 'name'?: (string); + 'typed_config'?: (_google_protobuf_Any | null); + /** + * Trace driver specific configuration which must be set according to the driver being instantiated. + * [#extension-category: envoy.tracers] + */ + 'config_type'?: "typed_config"; +} + +/** + * Configuration for an HTTP tracer provider used by Envoy. + * + * The configuration is defined by the + * :ref:`HttpConnectionManager.Tracing ` + * :ref:`provider ` + * field. + */ +export interface _envoy_config_trace_v3_Tracing_Http__Output { + /** + * The name of the HTTP trace driver to instantiate. The name must match a + * supported HTTP trace driver. + * See the :ref:`extensions listed in typed_config below ` for the default list of the HTTP trace driver. + */ + 'name': (string); + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * Trace driver specific configuration which must be set according to the driver being instantiated. + * [#extension-category: envoy.tracers] + */ + 'config_type': "typed_config"; +} + +/** + * The tracing configuration specifies settings for an HTTP tracer provider used by Envoy. + * + * Envoy may support other tracers in the future, but right now the HTTP tracer is the only one + * supported. + * + * .. attention:: + * + * Use of this message type has been deprecated in favor of direct use of + * :ref:`Tracing.Http `. + */ +export interface Tracing { + /** + * Provides configuration for the HTTP tracer. + */ + 'http'?: (_envoy_config_trace_v3_Tracing_Http | null); +} + +/** + * The tracing configuration specifies settings for an HTTP tracer provider used by Envoy. + * + * Envoy may support other tracers in the future, but right now the HTTP tracer is the only one + * supported. + * + * .. attention:: + * + * Use of this message type has been deprecated in favor of direct use of + * :ref:`Tracing.Http `. + */ +export interface Tracing__Output { + /** + * Provides configuration for the HTTP tracer. + */ + 'http': (_envoy_config_trace_v3_Tracing_Http__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/common/fault/v3/FaultDelay.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/common/fault/v3/FaultDelay.ts new file mode 100644 index 000000000..bec0403e4 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/common/fault/v3/FaultDelay.ts @@ -0,0 +1,79 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/common/fault/v3/fault.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../../../google/protobuf/Duration'; +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../../../envoy/type/v3/FractionalPercent'; + +// Original file: deps/envoy-api/envoy/extensions/filters/common/fault/v3/fault.proto + +export enum _envoy_extensions_filters_common_fault_v3_FaultDelay_FaultDelayType { + /** + * Unused and deprecated. + */ + FIXED = 0, +} + +/** + * Fault delays are controlled via an HTTP header (if applicable). See the + * :ref:`HTTP fault filter ` documentation for + * more information. + */ +export interface _envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay { +} + +/** + * Fault delays are controlled via an HTTP header (if applicable). See the + * :ref:`HTTP fault filter ` documentation for + * more information. + */ +export interface _envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay__Output { +} + +/** + * Delay specification is used to inject latency into the + * HTTP/Mongo operation. + * [#next-free-field: 6] + */ +export interface FaultDelay { + /** + * Add a fixed delay before forwarding the operation upstream. See + * https://developers.google.com/protocol-buffers/docs/proto3#json for + * the JSON/YAML Duration mapping. For HTTP/Mongo, the specified + * delay will be injected before a new request/operation. + * This is required if type is FIXED. + */ + 'fixed_delay'?: (_google_protobuf_Duration | null); + /** + * The percentage of operations/connections/requests on which the delay will be injected. + */ + 'percentage'?: (_envoy_type_v3_FractionalPercent | null); + /** + * Fault delays are controlled via an HTTP header (if applicable). + */ + 'header_delay'?: (_envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay | null); + 'fault_delay_secifier'?: "fixed_delay"|"header_delay"; +} + +/** + * Delay specification is used to inject latency into the + * HTTP/Mongo operation. + * [#next-free-field: 6] + */ +export interface FaultDelay__Output { + /** + * Add a fixed delay before forwarding the operation upstream. See + * https://developers.google.com/protocol-buffers/docs/proto3#json for + * the JSON/YAML Duration mapping. For HTTP/Mongo, the specified + * delay will be injected before a new request/operation. + * This is required if type is FIXED. + */ + 'fixed_delay'?: (_google_protobuf_Duration__Output | null); + /** + * The percentage of operations/connections/requests on which the delay will be injected. + */ + 'percentage': (_envoy_type_v3_FractionalPercent__Output | null); + /** + * Fault delays are controlled via an HTTP header (if applicable). + */ + 'header_delay'?: (_envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay__Output | null); + 'fault_delay_secifier': "fixed_delay"|"header_delay"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/common/fault/v3/FaultRateLimit.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/common/fault/v3/FaultRateLimit.ts new file mode 100644 index 000000000..4df7395bb --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/common/fault/v3/FaultRateLimit.ts @@ -0,0 +1,78 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/common/fault/v3/fault.proto + +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../../../envoy/type/v3/FractionalPercent'; +import type { Long } from '@grpc/proto-loader'; + +/** + * Describes a fixed/constant rate limit. + */ +export interface _envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit { + /** + * The limit supplied in KiB/s. + */ + 'limit_kbps'?: (number | string | Long); +} + +/** + * Describes a fixed/constant rate limit. + */ +export interface _envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit__Output { + /** + * The limit supplied in KiB/s. + */ + 'limit_kbps': (string); +} + +/** + * Rate limits are controlled via an HTTP header (if applicable). See the + * :ref:`HTTP fault filter ` documentation for + * more information. + */ +export interface _envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit { +} + +/** + * Rate limits are controlled via an HTTP header (if applicable). See the + * :ref:`HTTP fault filter ` documentation for + * more information. + */ +export interface _envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit__Output { +} + +/** + * Describes a rate limit to be applied. + */ +export interface FaultRateLimit { + /** + * A fixed rate limit. + */ + 'fixed_limit'?: (_envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit | null); + /** + * The percentage of operations/connections/requests on which the rate limit will be injected. + */ + 'percentage'?: (_envoy_type_v3_FractionalPercent | null); + /** + * Rate limits are controlled via an HTTP header (if applicable). + */ + 'header_limit'?: (_envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit | null); + 'limit_type'?: "fixed_limit"|"header_limit"; +} + +/** + * Describes a rate limit to be applied. + */ +export interface FaultRateLimit__Output { + /** + * A fixed rate limit. + */ + 'fixed_limit'?: (_envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit__Output | null); + /** + * The percentage of operations/connections/requests on which the rate limit will be injected. + */ + 'percentage': (_envoy_type_v3_FractionalPercent__Output | null); + /** + * Rate limits are controlled via an HTTP header (if applicable). + */ + 'header_limit'?: (_envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit__Output | null); + 'limit_type': "fixed_limit"|"header_limit"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/http/fault/v3/FaultAbort.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/http/fault/v3/FaultAbort.ts new file mode 100644 index 000000000..823706cb7 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/http/fault/v3/FaultAbort.ts @@ -0,0 +1,67 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/http/fault/v3/fault.proto + +import type { FractionalPercent as _envoy_type_v3_FractionalPercent, FractionalPercent__Output as _envoy_type_v3_FractionalPercent__Output } from '../../../../../../envoy/type/v3/FractionalPercent'; + +/** + * Fault aborts are controlled via an HTTP header (if applicable). See the + * :ref:`HTTP fault filter ` documentation for + * more information. + */ +export interface _envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort { +} + +/** + * Fault aborts are controlled via an HTTP header (if applicable). See the + * :ref:`HTTP fault filter ` documentation for + * more information. + */ +export interface _envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort__Output { +} + +/** + * [#next-free-field: 6] + */ +export interface FaultAbort { + /** + * HTTP status code to use to abort the HTTP request. + */ + 'http_status'?: (number); + /** + * The percentage of requests/operations/connections that will be aborted with the error code + * provided. + */ + 'percentage'?: (_envoy_type_v3_FractionalPercent | null); + /** + * Fault aborts are controlled via an HTTP header (if applicable). + */ + 'header_abort'?: (_envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort | null); + /** + * gRPC status code to use to abort the gRPC request. + */ + 'grpc_status'?: (number); + 'error_type'?: "http_status"|"grpc_status"|"header_abort"; +} + +/** + * [#next-free-field: 6] + */ +export interface FaultAbort__Output { + /** + * HTTP status code to use to abort the HTTP request. + */ + 'http_status'?: (number); + /** + * The percentage of requests/operations/connections that will be aborted with the error code + * provided. + */ + 'percentage': (_envoy_type_v3_FractionalPercent__Output | null); + /** + * Fault aborts are controlled via an HTTP header (if applicable). + */ + 'header_abort'?: (_envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort__Output | null); + /** + * gRPC status code to use to abort the gRPC request. + */ + 'grpc_status'?: (number); + 'error_type': "http_status"|"grpc_status"|"header_abort"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/http/fault/v3/HTTPFault.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/http/fault/v3/HTTPFault.ts new file mode 100644 index 000000000..d78bd9e4a --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/http/fault/v3/HTTPFault.ts @@ -0,0 +1,227 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/http/fault/v3/fault.proto + +import type { FaultDelay as _envoy_extensions_filters_common_fault_v3_FaultDelay, FaultDelay__Output as _envoy_extensions_filters_common_fault_v3_FaultDelay__Output } from '../../../../../../envoy/extensions/filters/common/fault/v3/FaultDelay'; +import type { FaultAbort as _envoy_extensions_filters_http_fault_v3_FaultAbort, FaultAbort__Output as _envoy_extensions_filters_http_fault_v3_FaultAbort__Output } from '../../../../../../envoy/extensions/filters/http/fault/v3/FaultAbort'; +import type { HeaderMatcher as _envoy_config_route_v3_HeaderMatcher, HeaderMatcher__Output as _envoy_config_route_v3_HeaderMatcher__Output } from '../../../../../../envoy/config/route/v3/HeaderMatcher'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../../../google/protobuf/UInt32Value'; +import type { FaultRateLimit as _envoy_extensions_filters_common_fault_v3_FaultRateLimit, FaultRateLimit__Output as _envoy_extensions_filters_common_fault_v3_FaultRateLimit__Output } from '../../../../../../envoy/extensions/filters/common/fault/v3/FaultRateLimit'; + +/** + * [#next-free-field: 16] + */ +export interface HTTPFault { + /** + * If specified, the filter will inject delays based on the values in the + * object. + */ + 'delay'?: (_envoy_extensions_filters_common_fault_v3_FaultDelay | null); + /** + * If specified, the filter will abort requests based on the values in + * the object. At least *abort* or *delay* must be specified. + */ + 'abort'?: (_envoy_extensions_filters_http_fault_v3_FaultAbort | null); + /** + * Specifies the name of the (destination) upstream cluster that the + * filter should match on. Fault injection will be restricted to requests + * bound to the specific upstream cluster. + */ + 'upstream_cluster'?: (string); + /** + * Specifies a set of headers that the filter should match on. The fault + * injection filter can be applied selectively to requests that match a set of + * headers specified in the fault filter config. The chances of actual fault + * injection further depend on the value of the :ref:`percentage + * ` field. + * The filter will check the request's headers against all the specified + * headers in the filter config. A match will happen if all the headers in the + * config are present in the request with the same values (or based on + * presence if the *value* field is not in the config). + */ + 'headers'?: (_envoy_config_route_v3_HeaderMatcher)[]; + /** + * Faults are injected for the specified list of downstream hosts. If this + * setting is not set, faults are injected for all downstream nodes. + * Downstream node name is taken from :ref:`the HTTP + * x-envoy-downstream-service-node + * ` header and compared + * against downstream_nodes list. + */ + 'downstream_nodes'?: (string)[]; + /** + * The maximum number of faults that can be active at a single time via the configured fault + * filter. Note that because this setting can be overridden at the route level, it's possible + * for the number of active faults to be greater than this value (if injected via a different + * route). If not specified, defaults to unlimited. This setting can be overridden via + * `runtime ` and any faults that are not injected + * due to overflow will be indicated via the `faults_overflow + * ` stat. + * + * .. attention:: + * Like other :ref:`circuit breakers ` in Envoy, this is a fuzzy + * limit. It's possible for the number of active faults to rise slightly above the configured + * amount due to the implementation details. + */ + 'max_active_faults'?: (_google_protobuf_UInt32Value | null); + /** + * The response rate limit to be applied to the response body of the stream. When configured, + * the percentage can be overridden by the :ref:`fault.http.rate_limit.response_percent + * ` runtime key. + * + * .. attention:: + * This is a per-stream limit versus a connection level limit. This means that concurrent streams + * will each get an independent limit. + */ + 'response_rate_limit'?: (_envoy_extensions_filters_common_fault_v3_FaultRateLimit | null); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.delay.fixed_delay_percent + */ + 'delay_percent_runtime'?: (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.abort.abort_percent + */ + 'abort_percent_runtime'?: (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.delay.fixed_duration_ms + */ + 'delay_duration_runtime'?: (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.abort.http_status + */ + 'abort_http_status_runtime'?: (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.max_active_faults + */ + 'max_active_faults_runtime'?: (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.rate_limit.response_percent + */ + 'response_rate_limit_percent_runtime'?: (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.abort.grpc_status + */ + 'abort_grpc_status_runtime'?: (string); + /** + * To control whether stats storage is allocated dynamically for each downstream server. + * If set to true, "x-envoy-downstream-service-cluster" field of header will be ignored by this filter. + * If set to false, dynamic stats storage will be allocated for the downstream cluster name. + * Default value is false. + */ + 'disable_downstream_cluster_stats'?: (boolean); +} + +/** + * [#next-free-field: 16] + */ +export interface HTTPFault__Output { + /** + * If specified, the filter will inject delays based on the values in the + * object. + */ + 'delay': (_envoy_extensions_filters_common_fault_v3_FaultDelay__Output | null); + /** + * If specified, the filter will abort requests based on the values in + * the object. At least *abort* or *delay* must be specified. + */ + 'abort': (_envoy_extensions_filters_http_fault_v3_FaultAbort__Output | null); + /** + * Specifies the name of the (destination) upstream cluster that the + * filter should match on. Fault injection will be restricted to requests + * bound to the specific upstream cluster. + */ + 'upstream_cluster': (string); + /** + * Specifies a set of headers that the filter should match on. The fault + * injection filter can be applied selectively to requests that match a set of + * headers specified in the fault filter config. The chances of actual fault + * injection further depend on the value of the :ref:`percentage + * ` field. + * The filter will check the request's headers against all the specified + * headers in the filter config. A match will happen if all the headers in the + * config are present in the request with the same values (or based on + * presence if the *value* field is not in the config). + */ + 'headers': (_envoy_config_route_v3_HeaderMatcher__Output)[]; + /** + * Faults are injected for the specified list of downstream hosts. If this + * setting is not set, faults are injected for all downstream nodes. + * Downstream node name is taken from :ref:`the HTTP + * x-envoy-downstream-service-node + * ` header and compared + * against downstream_nodes list. + */ + 'downstream_nodes': (string)[]; + /** + * The maximum number of faults that can be active at a single time via the configured fault + * filter. Note that because this setting can be overridden at the route level, it's possible + * for the number of active faults to be greater than this value (if injected via a different + * route). If not specified, defaults to unlimited. This setting can be overridden via + * `runtime ` and any faults that are not injected + * due to overflow will be indicated via the `faults_overflow + * ` stat. + * + * .. attention:: + * Like other :ref:`circuit breakers ` in Envoy, this is a fuzzy + * limit. It's possible for the number of active faults to rise slightly above the configured + * amount due to the implementation details. + */ + 'max_active_faults': (_google_protobuf_UInt32Value__Output | null); + /** + * The response rate limit to be applied to the response body of the stream. When configured, + * the percentage can be overridden by the :ref:`fault.http.rate_limit.response_percent + * ` runtime key. + * + * .. attention:: + * This is a per-stream limit versus a connection level limit. This means that concurrent streams + * will each get an independent limit. + */ + 'response_rate_limit': (_envoy_extensions_filters_common_fault_v3_FaultRateLimit__Output | null); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.delay.fixed_delay_percent + */ + 'delay_percent_runtime': (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.abort.abort_percent + */ + 'abort_percent_runtime': (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.delay.fixed_duration_ms + */ + 'delay_duration_runtime': (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.abort.http_status + */ + 'abort_http_status_runtime': (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.max_active_faults + */ + 'max_active_faults_runtime': (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.rate_limit.response_percent + */ + 'response_rate_limit_percent_runtime': (string); + /** + * The runtime key to override the :ref:`default ` + * runtime. The default is: fault.http.abort.grpc_status + */ + 'abort_grpc_status_runtime': (string); + /** + * To control whether stats storage is allocated dynamically for each downstream server. + * If set to true, "x-envoy-downstream-service-cluster" field of header will be ignored by this filter. + * If set to false, dynamic stats storage will be allocated for the downstream cluster name. + * Default value is false. + */ + 'disable_downstream_cluster_stats': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/EnvoyMobileHttpConnectionManager.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/EnvoyMobileHttpConnectionManager.ts new file mode 100644 index 000000000..eb73721c3 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/EnvoyMobileHttpConnectionManager.ts @@ -0,0 +1,29 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +import type { HttpConnectionManager as _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager, HttpConnectionManager__Output as _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager'; + +/** + * [#protodoc-title: Envoy Mobile HTTP connection manager] + * HTTP connection manager for use in Envoy mobile. + * [#extension: envoy.filters.network.envoy_mobile_http_connection_manager] + */ +export interface EnvoyMobileHttpConnectionManager { + /** + * The configuration for the underlying HttpConnectionManager which will be + * instantiated for Envoy mobile. + */ + 'config'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager | null); +} + +/** + * [#protodoc-title: Envoy Mobile HTTP connection manager] + * HTTP connection manager for use in Envoy mobile. + * [#extension: envoy.filters.network.envoy_mobile_http_connection_manager] + */ +export interface EnvoyMobileHttpConnectionManager__Output { + /** + * The configuration for the underlying HttpConnectionManager which will be + * instantiated for Envoy mobile. + */ + 'config': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager.ts new file mode 100644 index 000000000..fdf7084fe --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager.ts @@ -0,0 +1,1378 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +import type { Rds as _envoy_extensions_filters_network_http_connection_manager_v3_Rds, Rds__Output as _envoy_extensions_filters_network_http_connection_manager_v3_Rds__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/Rds'; +import type { RouteConfiguration as _envoy_config_route_v3_RouteConfiguration, RouteConfiguration__Output as _envoy_config_route_v3_RouteConfiguration__Output } from '../../../../../../envoy/config/route/v3/RouteConfiguration'; +import type { HttpFilter as _envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter, HttpFilter__Output as _envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/HttpFilter'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../../../google/protobuf/BoolValue'; +import type { Http1ProtocolOptions as _envoy_config_core_v3_Http1ProtocolOptions, Http1ProtocolOptions__Output as _envoy_config_core_v3_Http1ProtocolOptions__Output } from '../../../../../../envoy/config/core/v3/Http1ProtocolOptions'; +import type { Http2ProtocolOptions as _envoy_config_core_v3_Http2ProtocolOptions, Http2ProtocolOptions__Output as _envoy_config_core_v3_Http2ProtocolOptions__Output } from '../../../../../../envoy/config/core/v3/Http2ProtocolOptions'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../../../google/protobuf/Duration'; +import type { AccessLog as _envoy_config_accesslog_v3_AccessLog, AccessLog__Output as _envoy_config_accesslog_v3_AccessLog__Output } from '../../../../../../envoy/config/accesslog/v3/AccessLog'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../../../google/protobuf/UInt32Value'; +import type { ScopedRoutes as _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes, ScopedRoutes__Output as _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/ScopedRoutes'; +import type { HttpProtocolOptions as _envoy_config_core_v3_HttpProtocolOptions, HttpProtocolOptions__Output as _envoy_config_core_v3_HttpProtocolOptions__Output } from '../../../../../../envoy/config/core/v3/HttpProtocolOptions'; +import type { RequestIDExtension as _envoy_extensions_filters_network_http_connection_manager_v3_RequestIDExtension, RequestIDExtension__Output as _envoy_extensions_filters_network_http_connection_manager_v3_RequestIDExtension__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/RequestIDExtension'; +import type { LocalReplyConfig as _envoy_extensions_filters_network_http_connection_manager_v3_LocalReplyConfig, LocalReplyConfig__Output as _envoy_extensions_filters_network_http_connection_manager_v3_LocalReplyConfig__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/LocalReplyConfig'; +import type { Http3ProtocolOptions as _envoy_config_core_v3_Http3ProtocolOptions, Http3ProtocolOptions__Output as _envoy_config_core_v3_Http3ProtocolOptions__Output } from '../../../../../../envoy/config/core/v3/Http3ProtocolOptions'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../../../envoy/config/core/v3/TypedExtensionConfig'; +import type { SchemeHeaderTransformation as _envoy_config_core_v3_SchemeHeaderTransformation, SchemeHeaderTransformation__Output as _envoy_config_core_v3_SchemeHeaderTransformation__Output } from '../../../../../../envoy/config/core/v3/SchemeHeaderTransformation'; +import type { Percent as _envoy_type_v3_Percent, Percent__Output as _envoy_type_v3_Percent__Output } from '../../../../../../envoy/type/v3/Percent'; +import type { CustomTag as _envoy_type_tracing_v3_CustomTag, CustomTag__Output as _envoy_type_tracing_v3_CustomTag__Output } from '../../../../../../envoy/type/tracing/v3/CustomTag'; +import type { _envoy_config_trace_v3_Tracing_Http, _envoy_config_trace_v3_Tracing_Http__Output } from '../../../../../../envoy/config/trace/v3/Tracing'; +import type { PathTransformation as _envoy_type_http_v3_PathTransformation, PathTransformation__Output as _envoy_type_http_v3_PathTransformation__Output } from '../../../../../../envoy/type/http/v3/PathTransformation'; + +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +export enum _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_CodecType { + /** + * For every new connection, the connection manager will determine which + * codec to use. This mode supports both ALPN for TLS listeners as well as + * protocol inference for plaintext listeners. If ALPN data is available, it + * is preferred, otherwise protocol inference is used. In almost all cases, + * this is the right option to choose for this setting. + */ + AUTO = 0, + /** + * The connection manager will assume that the client is speaking HTTP/1.1. + */ + HTTP1 = 1, + /** + * The connection manager will assume that the client is speaking HTTP/2 + * (Envoy does not require HTTP/2 to take place over TLS or to use ALPN. + * Prior knowledge is allowed). + */ + HTTP2 = 2, + /** + * [#not-implemented-hide:] QUIC implementation is not production ready yet. Use this enum with + * caution to prevent accidental execution of QUIC code. I.e. `!= HTTP2` is no longer sufficient + * to distinguish HTTP1 and HTTP2 traffic. + */ + HTTP3 = 3, +} + +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +/** + * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP + * header. + */ +export enum _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ForwardClientCertDetails { + /** + * Do not send the XFCC header to the next hop. This is the default value. + */ + SANITIZE = 0, + /** + * When the client connection is mTLS (Mutual TLS), forward the XFCC header + * in the request. + */ + FORWARD_ONLY = 1, + /** + * When the client connection is mTLS, append the client certificate + * information to the request’s XFCC header and forward it. + */ + APPEND_FORWARD = 2, + /** + * When the client connection is mTLS, reset the XFCC header with the client + * certificate information and send it to the next hop. + */ + SANITIZE_SET = 3, + /** + * Always forward the XFCC header in the request, regardless of whether the + * client connection is mTLS. + */ + ALWAYS_FORWARD_ONLY = 4, +} + +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_InternalAddressConfig { + /** + * Whether unix socket addresses should be considered internal. + */ + 'unix_sockets'?: (boolean); +} + +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_InternalAddressConfig__Output { + /** + * Whether unix socket addresses should be considered internal. + */ + 'unix_sockets': (boolean); +} + +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +export enum _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_Tracing_OperationName { + /** + * The HTTP listener is used for ingress/incoming requests. + */ + INGRESS = 0, + /** + * The HTTP listener is used for egress/outgoing requests. + */ + EGRESS = 1, +} + +/** + * [#not-implemented-hide:] Transformations that apply to path headers. Transformations are applied + * before any processing of requests by HTTP filters, routing, and matching. Only the normalized + * path will be visible internally if a transformation is enabled. Any path rewrites that the + * router performs (e.g. :ref:`regex_rewrite + * ` or :ref:`prefix_rewrite + * `) will apply to the *:path* header + * destined for the upstream. + * + * Note: access logging and tracing will show the original *:path* header. + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathNormalizationOptions { + /** + * [#not-implemented-hide:] Normalization applies internally before any processing of requests by + * HTTP filters, routing, and matching *and* will affect the forwarded *:path* header. Defaults + * to :ref:`NormalizePathRFC3986 + * `. When not + * specified, this value may be overridden by the runtime variable + * :ref:`http_connection_manager.normalize_path`. + * Envoy will respond with 400 to paths that are malformed (e.g. for paths that fail RFC 3986 + * normalization due to disallowed characters.) + */ + 'forwarding_transformation'?: (_envoy_type_http_v3_PathTransformation | null); + /** + * [#not-implemented-hide:] Normalization only applies internally before any processing of + * requests by HTTP filters, routing, and matching. These will be applied after full + * transformation is applied. The *:path* header before this transformation will be restored in + * the router filter and sent upstream unless it was mutated by a filter. Defaults to no + * transformations. + * Multiple actions can be applied in the same Transformation, forming a sequential + * pipeline. The transformations will be performed in the order that they appear. Envoy will + * respond with 400 to paths that are malformed (e.g. for paths that fail RFC 3986 + * normalization due to disallowed characters.) + */ + 'http_filter_transformation'?: (_envoy_type_http_v3_PathTransformation | null); +} + +/** + * [#not-implemented-hide:] Transformations that apply to path headers. Transformations are applied + * before any processing of requests by HTTP filters, routing, and matching. Only the normalized + * path will be visible internally if a transformation is enabled. Any path rewrites that the + * router performs (e.g. :ref:`regex_rewrite + * ` or :ref:`prefix_rewrite + * `) will apply to the *:path* header + * destined for the upstream. + * + * Note: access logging and tracing will show the original *:path* header. + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathNormalizationOptions__Output { + /** + * [#not-implemented-hide:] Normalization applies internally before any processing of requests by + * HTTP filters, routing, and matching *and* will affect the forwarded *:path* header. Defaults + * to :ref:`NormalizePathRFC3986 + * `. When not + * specified, this value may be overridden by the runtime variable + * :ref:`http_connection_manager.normalize_path`. + * Envoy will respond with 400 to paths that are malformed (e.g. for paths that fail RFC 3986 + * normalization due to disallowed characters.) + */ + 'forwarding_transformation': (_envoy_type_http_v3_PathTransformation__Output | null); + /** + * [#not-implemented-hide:] Normalization only applies internally before any processing of + * requests by HTTP filters, routing, and matching. These will be applied after full + * transformation is applied. The *:path* header before this transformation will be restored in + * the router filter and sent upstream unless it was mutated by a filter. Defaults to no + * transformations. + * Multiple actions can be applied in the same Transformation, forming a sequential + * pipeline. The transformations will be performed in the order that they appear. Envoy will + * respond with 400 to paths that are malformed (e.g. for paths that fail RFC 3986 + * normalization due to disallowed characters.) + */ + 'http_filter_transformation': (_envoy_type_http_v3_PathTransformation__Output | null); +} + +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +/** + * Determines the action for request that contain %2F, %2f, %5C or %5c sequences in the URI path. + * This operation occurs before URL normalization and the merge slashes transformations if they were enabled. + */ +export enum _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathWithEscapedSlashesAction { + /** + * Default behavior specific to implementation (i.e. Envoy) of this configuration option. + * Envoy, by default, takes the KEEP_UNCHANGED action. + * NOTE: the implementation may change the default behavior at-will. + */ + IMPLEMENTATION_SPECIFIC_DEFAULT = 0, + /** + * Keep escaped slashes. + */ + KEEP_UNCHANGED = 1, + /** + * Reject client request with the 400 status. gRPC requests will be rejected with the INTERNAL (13) error code. + * The "httpN.downstream_rq_failed_path_normalization" counter is incremented for each rejected request. + */ + REJECT_REQUEST = 2, + /** + * Unescape %2F and %5C sequences and redirect request to the new path if these sequences were present. + * Redirect occurs after path normalization and merge slashes transformations if they were configured. + * NOTE: gRPC requests will be rejected with the INTERNAL (13) error code. + * This option minimizes possibility of path confusion exploits by forcing request with unescaped slashes to + * traverse all parties: downstream client, intermediate proxies, Envoy and upstream server. + * The "httpN.downstream_rq_redirected_with_normalized_path" counter is incremented for each + * redirected request. + */ + UNESCAPE_AND_REDIRECT = 3, + /** + * Unescape %2F and %5C sequences. + * Note: this option should not be enabled if intermediaries perform path based access control as + * it may lead to path confusion vulnerabilities. + */ + UNESCAPE_AND_FORWARD = 4, +} + +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +export enum _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ServerHeaderTransformation { + /** + * Overwrite any Server header with the contents of server_name. + */ + OVERWRITE = 0, + /** + * If no Server header is present, append Server server_name + * If a Server header is present, pass it through. + */ + APPEND_IF_ABSENT = 1, + /** + * Pass through the value of the server header, and do not append a header + * if none is present. + */ + PASS_THROUGH = 2, +} + +/** + * [#next-free-field: 7] + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_SetCurrentClientCertDetails { + /** + * Whether to forward the subject of the client cert. Defaults to false. + */ + 'subject'?: (_google_protobuf_BoolValue | null); + /** + * Whether to forward the entire client cert in URL encoded PEM format. This will appear in the + * XFCC header comma separated from other values with the value Cert="PEM". + * Defaults to false. + */ + 'cert'?: (boolean); + /** + * Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM + * format. This will appear in the XFCC header comma separated from other values with the value + * Chain="PEM". + * Defaults to false. + */ + 'chain'?: (boolean); + /** + * Whether to forward the DNS type Subject Alternative Names of the client cert. + * Defaults to false. + */ + 'dns'?: (boolean); + /** + * Whether to forward the URI type Subject Alternative Name of the client cert. Defaults to + * false. + */ + 'uri'?: (boolean); +} + +/** + * [#next-free-field: 7] + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_SetCurrentClientCertDetails__Output { + /** + * Whether to forward the subject of the client cert. Defaults to false. + */ + 'subject': (_google_protobuf_BoolValue__Output | null); + /** + * Whether to forward the entire client cert in URL encoded PEM format. This will appear in the + * XFCC header comma separated from other values with the value Cert="PEM". + * Defaults to false. + */ + 'cert': (boolean); + /** + * Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM + * format. This will appear in the XFCC header comma separated from other values with the value + * Chain="PEM". + * Defaults to false. + */ + 'chain': (boolean); + /** + * Whether to forward the DNS type Subject Alternative Names of the client cert. + * Defaults to false. + */ + 'dns': (boolean); + /** + * Whether to forward the URI type Subject Alternative Name of the client cert. Defaults to + * false. + */ + 'uri': (boolean); +} + +/** + * [#next-free-field: 10] + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_Tracing { + /** + * Target percentage of requests managed by this HTTP connection manager that will be force + * traced if the :ref:`x-client-trace-id ` + * header is set. This field is a direct analog for the runtime variable + * 'tracing.client_sampling' in the :ref:`HTTP Connection Manager + * `. + * Default: 100% + */ + 'client_sampling'?: (_envoy_type_v3_Percent | null); + /** + * Target percentage of requests managed by this HTTP connection manager that will be randomly + * selected for trace generation, if not requested by the client or not forced. This field is + * a direct analog for the runtime variable 'tracing.random_sampling' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'random_sampling'?: (_envoy_type_v3_Percent | null); + /** + * Target percentage of requests managed by this HTTP connection manager that will be traced + * after all other sampling checks have been applied (client-directed, force tracing, random + * sampling). This field functions as an upper limit on the total configured sampling rate. For + * instance, setting client_sampling to 100% but overall_sampling to 1% will result in only 1% + * of client requests with the appropriate headers to be force traced. This field is a direct + * analog for the runtime variable 'tracing.global_enabled' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'overall_sampling'?: (_envoy_type_v3_Percent | null); + /** + * Whether to annotate spans with additional data. If true, spans will include logs for stream + * events. + */ + 'verbose'?: (boolean); + /** + * Maximum length of the request path to extract and include in the HttpUrl tag. Used to + * truncate lengthy request paths to meet the needs of a tracing backend. + * Default: 256 + */ + 'max_path_tag_length'?: (_google_protobuf_UInt32Value | null); + /** + * A list of custom tags with unique tag name to create tags for the active span. + */ + 'custom_tags'?: (_envoy_type_tracing_v3_CustomTag)[]; + /** + * Configuration for an external tracing provider. + * If not specified, no tracing will be performed. + * + * .. attention:: + * Please be aware that *envoy.tracers.opencensus* provider can only be configured once + * in Envoy lifetime. + * Any attempts to reconfigure it or to use different configurations for different HCM filters + * will be rejected. + * Such a constraint is inherent to OpenCensus itself. It cannot be overcome without changes + * on OpenCensus side. + */ + 'provider'?: (_envoy_config_trace_v3_Tracing_Http | null); +} + +/** + * [#next-free-field: 10] + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_Tracing__Output { + /** + * Target percentage of requests managed by this HTTP connection manager that will be force + * traced if the :ref:`x-client-trace-id ` + * header is set. This field is a direct analog for the runtime variable + * 'tracing.client_sampling' in the :ref:`HTTP Connection Manager + * `. + * Default: 100% + */ + 'client_sampling': (_envoy_type_v3_Percent__Output | null); + /** + * Target percentage of requests managed by this HTTP connection manager that will be randomly + * selected for trace generation, if not requested by the client or not forced. This field is + * a direct analog for the runtime variable 'tracing.random_sampling' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'random_sampling': (_envoy_type_v3_Percent__Output | null); + /** + * Target percentage of requests managed by this HTTP connection manager that will be traced + * after all other sampling checks have been applied (client-directed, force tracing, random + * sampling). This field functions as an upper limit on the total configured sampling rate. For + * instance, setting client_sampling to 100% but overall_sampling to 1% will result in only 1% + * of client requests with the appropriate headers to be force traced. This field is a direct + * analog for the runtime variable 'tracing.global_enabled' in the + * :ref:`HTTP Connection Manager `. + * Default: 100% + */ + 'overall_sampling': (_envoy_type_v3_Percent__Output | null); + /** + * Whether to annotate spans with additional data. If true, spans will include logs for stream + * events. + */ + 'verbose': (boolean); + /** + * Maximum length of the request path to extract and include in the HttpUrl tag. Used to + * truncate lengthy request paths to meet the needs of a tracing backend. + * Default: 256 + */ + 'max_path_tag_length': (_google_protobuf_UInt32Value__Output | null); + /** + * A list of custom tags with unique tag name to create tags for the active span. + */ + 'custom_tags': (_envoy_type_tracing_v3_CustomTag__Output)[]; + /** + * Configuration for an external tracing provider. + * If not specified, no tracing will be performed. + * + * .. attention:: + * Please be aware that *envoy.tracers.opencensus* provider can only be configured once + * in Envoy lifetime. + * Any attempts to reconfigure it or to use different configurations for different HCM filters + * will be rejected. + * Such a constraint is inherent to OpenCensus itself. It cannot be overcome without changes + * on OpenCensus side. + */ + 'provider': (_envoy_config_trace_v3_Tracing_Http__Output | null); +} + +/** + * The configuration for HTTP upgrades. + * For each upgrade type desired, an UpgradeConfig must be added. + * + * .. warning:: + * + * The current implementation of upgrade headers does not handle + * multi-valued upgrade headers. Support for multi-valued headers may be + * added in the future if needed. + * + * .. warning:: + * The current implementation of upgrade headers does not work with HTTP/2 + * upstreams. + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_UpgradeConfig { + /** + * The case-insensitive name of this upgrade, e.g. "websocket". + * For each upgrade type present in upgrade_configs, requests with + * Upgrade: [upgrade_type] + * will be proxied upstream. + */ + 'upgrade_type'?: (string); + /** + * If present, this represents the filter chain which will be created for + * this type of upgrade. If no filters are present, the filter chain for + * HTTP connections will be used for this upgrade type. + */ + 'filters'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter)[]; + /** + * Determines if upgrades are enabled or disabled by default. Defaults to true. + * This can be overridden on a per-route basis with :ref:`cluster + * ` as documented in the + * :ref:`upgrade documentation `. + */ + 'enabled'?: (_google_protobuf_BoolValue | null); +} + +/** + * The configuration for HTTP upgrades. + * For each upgrade type desired, an UpgradeConfig must be added. + * + * .. warning:: + * + * The current implementation of upgrade headers does not handle + * multi-valued upgrade headers. Support for multi-valued headers may be + * added in the future if needed. + * + * .. warning:: + * The current implementation of upgrade headers does not work with HTTP/2 + * upstreams. + */ +export interface _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_UpgradeConfig__Output { + /** + * The case-insensitive name of this upgrade, e.g. "websocket". + * For each upgrade type present in upgrade_configs, requests with + * Upgrade: [upgrade_type] + * will be proxied upstream. + */ + 'upgrade_type': (string); + /** + * If present, this represents the filter chain which will be created for + * this type of upgrade. If no filters are present, the filter chain for + * HTTP connections will be used for this upgrade type. + */ + 'filters': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter__Output)[]; + /** + * Determines if upgrades are enabled or disabled by default. Defaults to true. + * This can be overridden on a per-route basis with :ref:`cluster + * ` as documented in the + * :ref:`upgrade documentation `. + */ + 'enabled': (_google_protobuf_BoolValue__Output | null); +} + +/** + * [#next-free-field: 49] + */ +export interface HttpConnectionManager { + /** + * Supplies the type of codec that the connection manager should use. + */ + 'codec_type'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_CodecType | keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_CodecType); + /** + * The human readable prefix to use when emitting statistics for the + * connection manager. See the :ref:`statistics documentation ` for + * more information. + */ + 'stat_prefix'?: (string); + /** + * The connection manager’s route table will be dynamically loaded via the RDS API. + */ + 'rds'?: (_envoy_extensions_filters_network_http_connection_manager_v3_Rds | null); + /** + * The route table for the connection manager is static and is specified in this property. + */ + 'route_config'?: (_envoy_config_route_v3_RouteConfiguration | null); + /** + * A list of individual HTTP filters that make up the filter chain for + * requests made to the connection manager. :ref:`Order matters ` + * as the filters are processed sequentially as request events happen. + */ + 'http_filters'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter)[]; + /** + * Whether the connection manager manipulates the :ref:`config_http_conn_man_headers_user-agent` + * and :ref:`config_http_conn_man_headers_downstream-service-cluster` headers. See the linked + * documentation for more information. Defaults to false. + */ + 'add_user_agent'?: (_google_protobuf_BoolValue | null); + /** + * Presence of the object defines whether the connection manager + * emits :ref:`tracing ` data to the :ref:`configured tracing provider + * `. + */ + 'tracing'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_Tracing | null); + /** + * Additional HTTP/1 settings that are passed to the HTTP/1 codec. + */ + 'http_protocol_options'?: (_envoy_config_core_v3_Http1ProtocolOptions | null); + /** + * Additional HTTP/2 settings that are passed directly to the HTTP/2 codec. + */ + 'http2_protocol_options'?: (_envoy_config_core_v3_Http2ProtocolOptions | null); + /** + * An optional override that the connection manager will write to the server + * header in responses. If not set, the default is *envoy*. + */ + 'server_name'?: (string); + /** + * The time that Envoy will wait between sending an HTTP/2 “shutdown + * notification” (GOAWAY frame with max stream ID) and a final GOAWAY frame. + * This is used so that Envoy provides a grace period for new streams that + * race with the final GOAWAY frame. During this grace period, Envoy will + * continue to accept new streams. After the grace period, a final GOAWAY + * frame is sent and Envoy will start refusing new streams. Draining occurs + * both when a connection hits the idle timeout or during general server + * draining. The default grace period is 5000 milliseconds (5 seconds) if this + * option is not specified. + */ + 'drain_timeout'?: (_google_protobuf_Duration | null); + /** + * Configuration for :ref:`HTTP access logs ` + * emitted by the connection manager. + */ + 'access_log'?: (_envoy_config_accesslog_v3_AccessLog)[]; + /** + * If set to true, the connection manager will use the real remote address + * of the client connection when determining internal versus external origin and manipulating + * various headers. If set to false or absent, the connection manager will use the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for`, + * :ref:`config_http_conn_man_headers_x-envoy-internal`, and + * :ref:`config_http_conn_man_headers_x-envoy-external-address` for more information. + */ + 'use_remote_address'?: (_google_protobuf_BoolValue | null); + /** + * Whether the connection manager will generate the :ref:`x-request-id + * ` header if it does not exist. This defaults to + * true. Generating a random UUID4 is expensive so in high throughput scenarios where this feature + * is not desired it can be disabled. + */ + 'generate_request_id'?: (_google_protobuf_BoolValue | null); + /** + * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP + * header. + */ + 'forward_client_cert_details'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ForwardClientCertDetails | keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ForwardClientCertDetails); + /** + * This field is valid only when :ref:`forward_client_cert_details + * ` + * is APPEND_FORWARD or SANITIZE_SET and the client connection is mTLS. It specifies the fields in + * the client certificate to be forwarded. Note that in the + * :ref:`config_http_conn_man_headers_x-forwarded-client-cert` header, *Hash* is always set, and + * *By* is always set when the client certificate presents the URI type Subject Alternative Name + * value. + */ + 'set_current_client_cert_details'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_SetCurrentClientCertDetails | null); + /** + * If proxy_100_continue is true, Envoy will proxy incoming "Expect: + * 100-continue" headers upstream, and forward "100 Continue" responses + * downstream. If this is false or not set, Envoy will instead strip the + * "Expect: 100-continue" header, and send a "100 Continue" response itself. + */ + 'proxy_100_continue'?: (boolean); + /** + * The number of additional ingress proxy hops from the right side of the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header to trust when + * determining the origin client's IP address. The default is zero if this option + * is not specified. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for` for more information. + */ + 'xff_num_trusted_hops'?: (number); + /** + * If + * :ref:`use_remote_address + * ` + * is true and represent_ipv4_remote_address_as_ipv4_mapped_ipv6 is true and the remote address is + * an IPv4 address, the address will be mapped to IPv6 before it is appended to *x-forwarded-for*. + * This is useful for testing compatibility of upstream services that parse the header value. For + * example, 50.0.0.1 is represented as ::FFFF:50.0.0.1. See `IPv4-Mapped IPv6 Addresses + * `_ for details. This will also affect the + * :ref:`config_http_conn_man_headers_x-envoy-external-address` header. See + * :ref:`http_connection_manager.represent_ipv4_remote_address_as_ipv4_mapped_ipv6 + * ` for runtime + * control. + * [#not-implemented-hide:] + */ + 'represent_ipv4_remote_address_as_ipv4_mapped_ipv6'?: (boolean); + /** + * If set, Envoy will not append the remote address to the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. This may be used in + * conjunction with HTTP filters that explicitly manipulate XFF after the HTTP connection manager + * has mutated the request headers. While :ref:`use_remote_address + * ` + * will also suppress XFF addition, it has consequences for logging and other + * Envoy uses of the remote address, so *skip_xff_append* should be used + * when only an elision of XFF addition is intended. + */ + 'skip_xff_append'?: (boolean); + /** + * Via header value to append to request and response headers. If this is + * empty, no via header will be appended. + */ + 'via'?: (string); + 'upgrade_configs'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_UpgradeConfig)[]; + /** + * The stream idle timeout for connections managed by the connection manager. + * If not specified, this defaults to 5 minutes. The default value was selected + * so as not to interfere with any smaller configured timeouts that may have + * existed in configurations prior to the introduction of this feature, while + * introducing robustness to TCP connections that terminate without a FIN. + * + * This idle timeout applies to new streams and is overridable by the + * :ref:`route-level idle_timeout + * `. Even on a stream in + * which the override applies, prior to receipt of the initial request + * headers, the :ref:`stream_idle_timeout + * ` + * applies. Each time an encode/decode event for headers or data is processed + * for the stream, the timer will be reset. If the timeout fires, the stream + * is terminated with a 408 Request Timeout error code if no upstream response + * header has been received, otherwise a stream reset occurs. + * + * This timeout also specifies the amount of time that Envoy will wait for the peer to open enough + * window to write any remaining stream data once the entirety of stream data (local end stream is + * true) has been buffered pending available window. In other words, this timeout defends against + * a peer that does not release enough window to completely write the stream, even though all + * data has been proxied within available flow control windows. If the timeout is hit in this + * case, the :ref:`tx_flush_timeout ` counter will be + * incremented. Note that :ref:`max_stream_duration + * ` does not apply to + * this corner case. + * + * If the :ref:`overload action ` "envoy.overload_actions.reduce_timeouts" + * is configured, this timeout is scaled according to the value for + * :ref:`HTTP_DOWNSTREAM_STREAM_IDLE `. + * + * Note that it is possible to idle timeout even if the wire traffic for a stream is non-idle, due + * to the granularity of events presented to the connection manager. For example, while receiving + * very large request headers, it may be the case that there is traffic regularly arriving on the + * wire while the connection manage is only able to observe the end-of-headers event, hence the + * stream may still idle timeout. + * + * A value of 0 will completely disable the connection manager stream idle + * timeout, although per-route idle timeout overrides will continue to apply. + */ + 'stream_idle_timeout'?: (_google_protobuf_Duration | null); + /** + * Configures what network addresses are considered internal for stats and header sanitation + * purposes. If unspecified, only RFC1918 IP addresses will be considered internal. + * See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more + * information about internal/external addresses. + */ + 'internal_address_config'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_InternalAddressConfig | null); + /** + * The delayed close timeout is for downstream connections managed by the HTTP connection manager. + * It is defined as a grace period after connection close processing has been locally initiated + * during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy + * from the downstream connection) prior to Envoy closing the socket associated with that + * connection. + * NOTE: This timeout is enforced even when the socket associated with the downstream connection + * is pending a flush of the write buffer. However, any progress made writing data to the socket + * will restart the timer associated with this timeout. This means that the total grace period for + * a socket in this state will be + * +. + * + * Delaying Envoy's connection close and giving the peer the opportunity to initiate the close + * sequence mitigates a race condition that exists when downstream clients do not drain/process + * data in a connection's receive buffer after a remote close has been detected via a socket + * write(). This race leads to such clients failing to process the response code sent by Envoy, + * which could result in erroneous downstream processing. + * + * If the timeout triggers, Envoy will close the connection's socket. + * + * The default timeout is 1000 ms if this option is not specified. + * + * .. NOTE:: + * To be useful in avoiding the race condition described above, this timeout must be set + * to *at least* +<100ms to account for + * a reasonable "worst" case processing time for a full iteration of Envoy's event loop>. + * + * .. WARNING:: + * A value of 0 will completely disable delayed close processing. When disabled, the downstream + * connection's socket will be closed immediately after the write flush is completed or will + * never close if the write flush does not complete. + */ + 'delayed_close_timeout'?: (_google_protobuf_Duration | null); + /** + * The amount of time that Envoy will wait for the entire request to be received. + * The timer is activated when the request is initiated, and is disarmed when the last byte of the + * request is sent upstream (i.e. all decoding filters have processed the request), OR when the + * response is initiated. If not specified or set to 0, this timeout is disabled. + */ + 'request_timeout'?: (_google_protobuf_Duration | null); + /** + * The maximum request headers size for incoming connections. + * If unconfigured, the default max request headers allowed is 60 KiB. + * Requests that exceed this limit will receive a 431 response. + */ + 'max_request_headers_kb'?: (_google_protobuf_UInt32Value | null); + /** + * Should paths be normalized according to RFC 3986 before any processing of + * requests by HTTP filters or routing? This affects the upstream *:path* header + * as well. For paths that fail this check, Envoy will respond with 400 to + * paths that are malformed. This defaults to false currently but will default + * true in the future. When not specified, this value may be overridden by the + * runtime variable + * :ref:`http_connection_manager.normalize_path`. + * See `Normalization and Comparison `_ + * for details of normalization. + * Note that Envoy does not perform + * `case normalization `_ + */ + 'normalize_path'?: (_google_protobuf_BoolValue | null); + /** + * A route table will be dynamically assigned to each request based on request attributes + * (e.g., the value of a header). The "routing scopes" (i.e., route tables) and "scope keys" are + * specified in this message. + */ + 'scoped_routes'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes | null); + /** + * Whether the connection manager will keep the :ref:`x-request-id + * ` header if passed for a request that is edge + * (Edge request is the request from external clients to front Envoy) and not reset it, which + * is the current Envoy behaviour. This defaults to false. + */ + 'preserve_external_request_id'?: (boolean); + /** + * Determines if adjacent slashes in the path are merged into one before any processing of + * requests by HTTP filters or routing. This affects the upstream *:path* header as well. Without + * setting this option, incoming requests with path `//dir///file` will not match against route + * with `prefix` match set to `/dir`. Defaults to `false`. Note that slash merging is not part of + * `HTTP spec `_ and is provided for convenience. + */ + 'merge_slashes'?: (boolean); + /** + * Defines the action to be applied to the Server header on the response path. + * By default, Envoy will overwrite the header with the value specified in + * server_name. + */ + 'server_header_transformation'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ServerHeaderTransformation | keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ServerHeaderTransformation); + /** + * Additional settings for HTTP requests handled by the connection manager. These will be + * applicable to both HTTP1 and HTTP2 requests. + */ + 'common_http_protocol_options'?: (_envoy_config_core_v3_HttpProtocolOptions | null); + /** + * The configuration of the request ID extension. This includes operations such as + * generation, validation, and associated tracing operations. If empty, the + * :ref:`UuidRequestIdConfig ` + * default extension is used with default parameters. See the documentation for that extension + * for details on what it does. Customizing the configuration for the default extension can be + * achieved by configuring it explicitly here. For example, to disable trace reason packing, + * the following configuration can be used: + * + * .. validated-code-block:: yaml + * :type-name: envoy.extensions.filters.network.http_connection_manager.v3.RequestIDExtension + * + * typed_config: + * "@type": type.googleapis.com/envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig + * pack_trace_reason: false + * + * [#extension-category: envoy.request_id] + */ + 'request_id_extension'?: (_envoy_extensions_filters_network_http_connection_manager_v3_RequestIDExtension | null); + /** + * If set, Envoy will always set :ref:`x-request-id ` header in response. + * If this is false or not set, the request ID is returned in responses only if tracing is forced using + * :ref:`x-envoy-force-trace ` header. + */ + 'always_set_request_id_in_response'?: (boolean); + /** + * The configuration to customize local reply returned by Envoy. It can customize status code, + * body text and response content type. If not specified, status code and text body are hard + * coded in Envoy, the response content type is plain text. + */ + 'local_reply_config'?: (_envoy_extensions_filters_network_http_connection_manager_v3_LocalReplyConfig | null); + /** + * Determines if the port part should be removed from host/authority header before any processing + * of request by HTTP filters or routing. The port would be removed only if it is equal to the :ref:`listener's` + * local port. This affects the upstream host header unless the method is + * CONNECT in which case if no filter adds a port the original port will be restored before headers are + * sent upstream. + * Without setting this option, incoming requests with host `example:443` will not match against + * route with :ref:`domains` match set to `example`. Defaults to `false`. Note that port removal is not part + * of `HTTP spec `_ and is provided for convenience. + * Only one of `strip_matching_host_port` or `strip_any_host_port` can be set. + */ + 'strip_matching_host_port'?: (boolean); + /** + * Governs Envoy's behavior when receiving invalid HTTP from downstream. + * If this option is false (default), Envoy will err on the conservative side handling HTTP + * errors, terminating both HTTP/1.1 and HTTP/2 connections when receiving an invalid request. + * If this option is set to true, Envoy will be more permissive, only resetting the invalid + * stream in the case of HTTP/2 and leaving the connection open where possible (if the entire + * request is read for HTTP/1.1) + * In general this should be true for deployments receiving trusted traffic (L2 Envoys, + * company-internal mesh) and false when receiving untrusted traffic (edge deployments). + * + * If different behaviors for invalid_http_message for HTTP/1 and HTTP/2 are + * desired, one should use the new HTTP/1 option :ref:`override_stream_error_on_invalid_http_message + * ` or the new HTTP/2 option + * :ref:`override_stream_error_on_invalid_http_message + * ` + * *not* the deprecated but similarly named :ref:`stream_error_on_invalid_http_messaging + * ` + */ + 'stream_error_on_invalid_http_message'?: (_google_protobuf_BoolValue | null); + /** + * The amount of time that Envoy will wait for the request headers to be received. The timer is + * activated when the first byte of the headers is received, and is disarmed when the last byte of + * the headers has been received. If not specified or set to 0, this timeout is disabled. + */ + 'request_headers_timeout'?: (_google_protobuf_Duration | null); + /** + * Determines if the port part should be removed from host/authority header before any processing + * of request by HTTP filters or routing. + * This affects the upstream host header unless the method is CONNECT in + * which case if no filter adds a port the original port will be restored before headers are sent upstream. + * Without setting this option, incoming requests with host `example:443` will not match against + * route with :ref:`domains` match set to `example`. Defaults to `false`. Note that port removal is not part + * of `HTTP spec `_ and is provided for convenience. + * Only one of `strip_matching_host_port` or `strip_any_host_port` can be set. + */ + 'strip_any_host_port'?: (boolean); + /** + * [#not-implemented-hide:] Path normalization configuration. This includes + * configurations for transformations (e.g. RFC 3986 normalization or merge + * adjacent slashes) and the policy to apply them. The policy determines + * whether transformations affect the forwarded *:path* header. RFC 3986 path + * normalization is enabled by default and the default policy is that the + * normalized header will be forwarded. See :ref:`PathNormalizationOptions + * ` + * for details. + */ + 'path_normalization_options'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathNormalizationOptions | null); + /** + * Additional HTTP/3 settings that are passed directly to the HTTP/3 codec. + * [#not-implemented-hide:] + */ + 'http3_protocol_options'?: (_envoy_config_core_v3_Http3ProtocolOptions | null); + /** + * Action to take when request URL path contains escaped slash sequences (%2F, %2f, %5C and %5c). + * The default value can be overridden by the :ref:`http_connection_manager.path_with_escaped_slashes_action` + * runtime variable. + * The :ref:`http_connection_manager.path_with_escaped_slashes_action_sampling` runtime + * variable can be used to apply the action to a portion of all requests. + */ + 'path_with_escaped_slashes_action'?: (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathWithEscapedSlashesAction | keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathWithEscapedSlashesAction); + /** + * The configuration for the original IP detection extensions. + * + * When configured the extensions will be called along with the request headers + * and information about the downstream connection, such as the directly connected address. + * Each extension will then use these parameters to decide the request's effective remote address. + * If an extension fails to detect the original IP address and isn't configured to reject + * the request, the HCM will try the remaining extensions until one succeeds or rejects + * the request. If the request isn't rejected nor any extension succeeds, the HCM will + * fallback to using the remote address. + * + * .. WARNING:: + * Extensions cannot be used in conjunction with :ref:`use_remote_address + * ` + * nor :ref:`xff_num_trusted_hops + * `. + * + * [#extension-category: envoy.http.original_ip_detection] + */ + 'original_ip_detection_extensions'?: (_envoy_config_core_v3_TypedExtensionConfig)[]; + /** + * Determines if trailing dot of the host should be removed from host/authority header before any + * processing of request by HTTP filters or routing. + * This affects the upstream host header. + * Without setting this option, incoming requests with host `example.com.` will not match against + * route with :ref:`domains` match set to `example.com`. Defaults to `false`. + * When the incoming request contains a host/authority header that includes a port number, + * setting this option will strip a trailing dot, if present, from the host section, + * leaving the port as is (e.g. host value `example.com.:443` will be updated to `example.com:443`). + */ + 'strip_trailing_host_dot'?: (boolean); + /** + * Allows for explicit transformation of the :scheme header on the request path. + * If not set, Envoy's default :ref:`scheme ` + * handling applies. + */ + 'scheme_header_transformation'?: (_envoy_config_core_v3_SchemeHeaderTransformation | null); + 'route_specifier'?: "rds"|"route_config"|"scoped_routes"; + 'strip_port_mode'?: "strip_any_host_port"; +} + +/** + * [#next-free-field: 49] + */ +export interface HttpConnectionManager__Output { + /** + * Supplies the type of codec that the connection manager should use. + */ + 'codec_type': (keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_CodecType); + /** + * The human readable prefix to use when emitting statistics for the + * connection manager. See the :ref:`statistics documentation ` for + * more information. + */ + 'stat_prefix': (string); + /** + * The connection manager’s route table will be dynamically loaded via the RDS API. + */ + 'rds'?: (_envoy_extensions_filters_network_http_connection_manager_v3_Rds__Output | null); + /** + * The route table for the connection manager is static and is specified in this property. + */ + 'route_config'?: (_envoy_config_route_v3_RouteConfiguration__Output | null); + /** + * A list of individual HTTP filters that make up the filter chain for + * requests made to the connection manager. :ref:`Order matters ` + * as the filters are processed sequentially as request events happen. + */ + 'http_filters': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter__Output)[]; + /** + * Whether the connection manager manipulates the :ref:`config_http_conn_man_headers_user-agent` + * and :ref:`config_http_conn_man_headers_downstream-service-cluster` headers. See the linked + * documentation for more information. Defaults to false. + */ + 'add_user_agent': (_google_protobuf_BoolValue__Output | null); + /** + * Presence of the object defines whether the connection manager + * emits :ref:`tracing ` data to the :ref:`configured tracing provider + * `. + */ + 'tracing': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_Tracing__Output | null); + /** + * Additional HTTP/1 settings that are passed to the HTTP/1 codec. + */ + 'http_protocol_options': (_envoy_config_core_v3_Http1ProtocolOptions__Output | null); + /** + * Additional HTTP/2 settings that are passed directly to the HTTP/2 codec. + */ + 'http2_protocol_options': (_envoy_config_core_v3_Http2ProtocolOptions__Output | null); + /** + * An optional override that the connection manager will write to the server + * header in responses. If not set, the default is *envoy*. + */ + 'server_name': (string); + /** + * The time that Envoy will wait between sending an HTTP/2 “shutdown + * notification” (GOAWAY frame with max stream ID) and a final GOAWAY frame. + * This is used so that Envoy provides a grace period for new streams that + * race with the final GOAWAY frame. During this grace period, Envoy will + * continue to accept new streams. After the grace period, a final GOAWAY + * frame is sent and Envoy will start refusing new streams. Draining occurs + * both when a connection hits the idle timeout or during general server + * draining. The default grace period is 5000 milliseconds (5 seconds) if this + * option is not specified. + */ + 'drain_timeout': (_google_protobuf_Duration__Output | null); + /** + * Configuration for :ref:`HTTP access logs ` + * emitted by the connection manager. + */ + 'access_log': (_envoy_config_accesslog_v3_AccessLog__Output)[]; + /** + * If set to true, the connection manager will use the real remote address + * of the client connection when determining internal versus external origin and manipulating + * various headers. If set to false or absent, the connection manager will use the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for`, + * :ref:`config_http_conn_man_headers_x-envoy-internal`, and + * :ref:`config_http_conn_man_headers_x-envoy-external-address` for more information. + */ + 'use_remote_address': (_google_protobuf_BoolValue__Output | null); + /** + * Whether the connection manager will generate the :ref:`x-request-id + * ` header if it does not exist. This defaults to + * true. Generating a random UUID4 is expensive so in high throughput scenarios where this feature + * is not desired it can be disabled. + */ + 'generate_request_id': (_google_protobuf_BoolValue__Output | null); + /** + * How to handle the :ref:`config_http_conn_man_headers_x-forwarded-client-cert` (XFCC) HTTP + * header. + */ + 'forward_client_cert_details': (keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ForwardClientCertDetails); + /** + * This field is valid only when :ref:`forward_client_cert_details + * ` + * is APPEND_FORWARD or SANITIZE_SET and the client connection is mTLS. It specifies the fields in + * the client certificate to be forwarded. Note that in the + * :ref:`config_http_conn_man_headers_x-forwarded-client-cert` header, *Hash* is always set, and + * *By* is always set when the client certificate presents the URI type Subject Alternative Name + * value. + */ + 'set_current_client_cert_details': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_SetCurrentClientCertDetails__Output | null); + /** + * If proxy_100_continue is true, Envoy will proxy incoming "Expect: + * 100-continue" headers upstream, and forward "100 Continue" responses + * downstream. If this is false or not set, Envoy will instead strip the + * "Expect: 100-continue" header, and send a "100 Continue" response itself. + */ + 'proxy_100_continue': (boolean); + /** + * The number of additional ingress proxy hops from the right side of the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header to trust when + * determining the origin client's IP address. The default is zero if this option + * is not specified. See the documentation for + * :ref:`config_http_conn_man_headers_x-forwarded-for` for more information. + */ + 'xff_num_trusted_hops': (number); + /** + * If + * :ref:`use_remote_address + * ` + * is true and represent_ipv4_remote_address_as_ipv4_mapped_ipv6 is true and the remote address is + * an IPv4 address, the address will be mapped to IPv6 before it is appended to *x-forwarded-for*. + * This is useful for testing compatibility of upstream services that parse the header value. For + * example, 50.0.0.1 is represented as ::FFFF:50.0.0.1. See `IPv4-Mapped IPv6 Addresses + * `_ for details. This will also affect the + * :ref:`config_http_conn_man_headers_x-envoy-external-address` header. See + * :ref:`http_connection_manager.represent_ipv4_remote_address_as_ipv4_mapped_ipv6 + * ` for runtime + * control. + * [#not-implemented-hide:] + */ + 'represent_ipv4_remote_address_as_ipv4_mapped_ipv6': (boolean); + /** + * If set, Envoy will not append the remote address to the + * :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header. This may be used in + * conjunction with HTTP filters that explicitly manipulate XFF after the HTTP connection manager + * has mutated the request headers. While :ref:`use_remote_address + * ` + * will also suppress XFF addition, it has consequences for logging and other + * Envoy uses of the remote address, so *skip_xff_append* should be used + * when only an elision of XFF addition is intended. + */ + 'skip_xff_append': (boolean); + /** + * Via header value to append to request and response headers. If this is + * empty, no via header will be appended. + */ + 'via': (string); + 'upgrade_configs': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_UpgradeConfig__Output)[]; + /** + * The stream idle timeout for connections managed by the connection manager. + * If not specified, this defaults to 5 minutes. The default value was selected + * so as not to interfere with any smaller configured timeouts that may have + * existed in configurations prior to the introduction of this feature, while + * introducing robustness to TCP connections that terminate without a FIN. + * + * This idle timeout applies to new streams and is overridable by the + * :ref:`route-level idle_timeout + * `. Even on a stream in + * which the override applies, prior to receipt of the initial request + * headers, the :ref:`stream_idle_timeout + * ` + * applies. Each time an encode/decode event for headers or data is processed + * for the stream, the timer will be reset. If the timeout fires, the stream + * is terminated with a 408 Request Timeout error code if no upstream response + * header has been received, otherwise a stream reset occurs. + * + * This timeout also specifies the amount of time that Envoy will wait for the peer to open enough + * window to write any remaining stream data once the entirety of stream data (local end stream is + * true) has been buffered pending available window. In other words, this timeout defends against + * a peer that does not release enough window to completely write the stream, even though all + * data has been proxied within available flow control windows. If the timeout is hit in this + * case, the :ref:`tx_flush_timeout ` counter will be + * incremented. Note that :ref:`max_stream_duration + * ` does not apply to + * this corner case. + * + * If the :ref:`overload action ` "envoy.overload_actions.reduce_timeouts" + * is configured, this timeout is scaled according to the value for + * :ref:`HTTP_DOWNSTREAM_STREAM_IDLE `. + * + * Note that it is possible to idle timeout even if the wire traffic for a stream is non-idle, due + * to the granularity of events presented to the connection manager. For example, while receiving + * very large request headers, it may be the case that there is traffic regularly arriving on the + * wire while the connection manage is only able to observe the end-of-headers event, hence the + * stream may still idle timeout. + * + * A value of 0 will completely disable the connection manager stream idle + * timeout, although per-route idle timeout overrides will continue to apply. + */ + 'stream_idle_timeout': (_google_protobuf_Duration__Output | null); + /** + * Configures what network addresses are considered internal for stats and header sanitation + * purposes. If unspecified, only RFC1918 IP addresses will be considered internal. + * See the documentation for :ref:`config_http_conn_man_headers_x-envoy-internal` for more + * information about internal/external addresses. + */ + 'internal_address_config': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_InternalAddressConfig__Output | null); + /** + * The delayed close timeout is for downstream connections managed by the HTTP connection manager. + * It is defined as a grace period after connection close processing has been locally initiated + * during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy + * from the downstream connection) prior to Envoy closing the socket associated with that + * connection. + * NOTE: This timeout is enforced even when the socket associated with the downstream connection + * is pending a flush of the write buffer. However, any progress made writing data to the socket + * will restart the timer associated with this timeout. This means that the total grace period for + * a socket in this state will be + * +. + * + * Delaying Envoy's connection close and giving the peer the opportunity to initiate the close + * sequence mitigates a race condition that exists when downstream clients do not drain/process + * data in a connection's receive buffer after a remote close has been detected via a socket + * write(). This race leads to such clients failing to process the response code sent by Envoy, + * which could result in erroneous downstream processing. + * + * If the timeout triggers, Envoy will close the connection's socket. + * + * The default timeout is 1000 ms if this option is not specified. + * + * .. NOTE:: + * To be useful in avoiding the race condition described above, this timeout must be set + * to *at least* +<100ms to account for + * a reasonable "worst" case processing time for a full iteration of Envoy's event loop>. + * + * .. WARNING:: + * A value of 0 will completely disable delayed close processing. When disabled, the downstream + * connection's socket will be closed immediately after the write flush is completed or will + * never close if the write flush does not complete. + */ + 'delayed_close_timeout': (_google_protobuf_Duration__Output | null); + /** + * The amount of time that Envoy will wait for the entire request to be received. + * The timer is activated when the request is initiated, and is disarmed when the last byte of the + * request is sent upstream (i.e. all decoding filters have processed the request), OR when the + * response is initiated. If not specified or set to 0, this timeout is disabled. + */ + 'request_timeout': (_google_protobuf_Duration__Output | null); + /** + * The maximum request headers size for incoming connections. + * If unconfigured, the default max request headers allowed is 60 KiB. + * Requests that exceed this limit will receive a 431 response. + */ + 'max_request_headers_kb': (_google_protobuf_UInt32Value__Output | null); + /** + * Should paths be normalized according to RFC 3986 before any processing of + * requests by HTTP filters or routing? This affects the upstream *:path* header + * as well. For paths that fail this check, Envoy will respond with 400 to + * paths that are malformed. This defaults to false currently but will default + * true in the future. When not specified, this value may be overridden by the + * runtime variable + * :ref:`http_connection_manager.normalize_path`. + * See `Normalization and Comparison `_ + * for details of normalization. + * Note that Envoy does not perform + * `case normalization `_ + */ + 'normalize_path': (_google_protobuf_BoolValue__Output | null); + /** + * A route table will be dynamically assigned to each request based on request attributes + * (e.g., the value of a header). The "routing scopes" (i.e., route tables) and "scope keys" are + * specified in this message. + */ + 'scoped_routes'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes__Output | null); + /** + * Whether the connection manager will keep the :ref:`x-request-id + * ` header if passed for a request that is edge + * (Edge request is the request from external clients to front Envoy) and not reset it, which + * is the current Envoy behaviour. This defaults to false. + */ + 'preserve_external_request_id': (boolean); + /** + * Determines if adjacent slashes in the path are merged into one before any processing of + * requests by HTTP filters or routing. This affects the upstream *:path* header as well. Without + * setting this option, incoming requests with path `//dir///file` will not match against route + * with `prefix` match set to `/dir`. Defaults to `false`. Note that slash merging is not part of + * `HTTP spec `_ and is provided for convenience. + */ + 'merge_slashes': (boolean); + /** + * Defines the action to be applied to the Server header on the response path. + * By default, Envoy will overwrite the header with the value specified in + * server_name. + */ + 'server_header_transformation': (keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ServerHeaderTransformation); + /** + * Additional settings for HTTP requests handled by the connection manager. These will be + * applicable to both HTTP1 and HTTP2 requests. + */ + 'common_http_protocol_options': (_envoy_config_core_v3_HttpProtocolOptions__Output | null); + /** + * The configuration of the request ID extension. This includes operations such as + * generation, validation, and associated tracing operations. If empty, the + * :ref:`UuidRequestIdConfig ` + * default extension is used with default parameters. See the documentation for that extension + * for details on what it does. Customizing the configuration for the default extension can be + * achieved by configuring it explicitly here. For example, to disable trace reason packing, + * the following configuration can be used: + * + * .. validated-code-block:: yaml + * :type-name: envoy.extensions.filters.network.http_connection_manager.v3.RequestIDExtension + * + * typed_config: + * "@type": type.googleapis.com/envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig + * pack_trace_reason: false + * + * [#extension-category: envoy.request_id] + */ + 'request_id_extension': (_envoy_extensions_filters_network_http_connection_manager_v3_RequestIDExtension__Output | null); + /** + * If set, Envoy will always set :ref:`x-request-id ` header in response. + * If this is false or not set, the request ID is returned in responses only if tracing is forced using + * :ref:`x-envoy-force-trace ` header. + */ + 'always_set_request_id_in_response': (boolean); + /** + * The configuration to customize local reply returned by Envoy. It can customize status code, + * body text and response content type. If not specified, status code and text body are hard + * coded in Envoy, the response content type is plain text. + */ + 'local_reply_config': (_envoy_extensions_filters_network_http_connection_manager_v3_LocalReplyConfig__Output | null); + /** + * Determines if the port part should be removed from host/authority header before any processing + * of request by HTTP filters or routing. The port would be removed only if it is equal to the :ref:`listener's` + * local port. This affects the upstream host header unless the method is + * CONNECT in which case if no filter adds a port the original port will be restored before headers are + * sent upstream. + * Without setting this option, incoming requests with host `example:443` will not match against + * route with :ref:`domains` match set to `example`. Defaults to `false`. Note that port removal is not part + * of `HTTP spec `_ and is provided for convenience. + * Only one of `strip_matching_host_port` or `strip_any_host_port` can be set. + */ + 'strip_matching_host_port': (boolean); + /** + * Governs Envoy's behavior when receiving invalid HTTP from downstream. + * If this option is false (default), Envoy will err on the conservative side handling HTTP + * errors, terminating both HTTP/1.1 and HTTP/2 connections when receiving an invalid request. + * If this option is set to true, Envoy will be more permissive, only resetting the invalid + * stream in the case of HTTP/2 and leaving the connection open where possible (if the entire + * request is read for HTTP/1.1) + * In general this should be true for deployments receiving trusted traffic (L2 Envoys, + * company-internal mesh) and false when receiving untrusted traffic (edge deployments). + * + * If different behaviors for invalid_http_message for HTTP/1 and HTTP/2 are + * desired, one should use the new HTTP/1 option :ref:`override_stream_error_on_invalid_http_message + * ` or the new HTTP/2 option + * :ref:`override_stream_error_on_invalid_http_message + * ` + * *not* the deprecated but similarly named :ref:`stream_error_on_invalid_http_messaging + * ` + */ + 'stream_error_on_invalid_http_message': (_google_protobuf_BoolValue__Output | null); + /** + * The amount of time that Envoy will wait for the request headers to be received. The timer is + * activated when the first byte of the headers is received, and is disarmed when the last byte of + * the headers has been received. If not specified or set to 0, this timeout is disabled. + */ + 'request_headers_timeout': (_google_protobuf_Duration__Output | null); + /** + * Determines if the port part should be removed from host/authority header before any processing + * of request by HTTP filters or routing. + * This affects the upstream host header unless the method is CONNECT in + * which case if no filter adds a port the original port will be restored before headers are sent upstream. + * Without setting this option, incoming requests with host `example:443` will not match against + * route with :ref:`domains` match set to `example`. Defaults to `false`. Note that port removal is not part + * of `HTTP spec `_ and is provided for convenience. + * Only one of `strip_matching_host_port` or `strip_any_host_port` can be set. + */ + 'strip_any_host_port'?: (boolean); + /** + * [#not-implemented-hide:] Path normalization configuration. This includes + * configurations for transformations (e.g. RFC 3986 normalization or merge + * adjacent slashes) and the policy to apply them. The policy determines + * whether transformations affect the forwarded *:path* header. RFC 3986 path + * normalization is enabled by default and the default policy is that the + * normalized header will be forwarded. See :ref:`PathNormalizationOptions + * ` + * for details. + */ + 'path_normalization_options': (_envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathNormalizationOptions__Output | null); + /** + * Additional HTTP/3 settings that are passed directly to the HTTP/3 codec. + * [#not-implemented-hide:] + */ + 'http3_protocol_options': (_envoy_config_core_v3_Http3ProtocolOptions__Output | null); + /** + * Action to take when request URL path contains escaped slash sequences (%2F, %2f, %5C and %5c). + * The default value can be overridden by the :ref:`http_connection_manager.path_with_escaped_slashes_action` + * runtime variable. + * The :ref:`http_connection_manager.path_with_escaped_slashes_action_sampling` runtime + * variable can be used to apply the action to a portion of all requests. + */ + 'path_with_escaped_slashes_action': (keyof typeof _envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathWithEscapedSlashesAction); + /** + * The configuration for the original IP detection extensions. + * + * When configured the extensions will be called along with the request headers + * and information about the downstream connection, such as the directly connected address. + * Each extension will then use these parameters to decide the request's effective remote address. + * If an extension fails to detect the original IP address and isn't configured to reject + * the request, the HCM will try the remaining extensions until one succeeds or rejects + * the request. If the request isn't rejected nor any extension succeeds, the HCM will + * fallback to using the remote address. + * + * .. WARNING:: + * Extensions cannot be used in conjunction with :ref:`use_remote_address + * ` + * nor :ref:`xff_num_trusted_hops + * `. + * + * [#extension-category: envoy.http.original_ip_detection] + */ + 'original_ip_detection_extensions': (_envoy_config_core_v3_TypedExtensionConfig__Output)[]; + /** + * Determines if trailing dot of the host should be removed from host/authority header before any + * processing of request by HTTP filters or routing. + * This affects the upstream host header. + * Without setting this option, incoming requests with host `example.com.` will not match against + * route with :ref:`domains` match set to `example.com`. Defaults to `false`. + * When the incoming request contains a host/authority header that includes a port number, + * setting this option will strip a trailing dot, if present, from the host section, + * leaving the port as is (e.g. host value `example.com.:443` will be updated to `example.com:443`). + */ + 'strip_trailing_host_dot': (boolean); + /** + * Allows for explicit transformation of the :scheme header on the request path. + * If not set, Envoy's default :ref:`scheme ` + * handling applies. + */ + 'scheme_header_transformation': (_envoy_config_core_v3_SchemeHeaderTransformation__Output | null); + 'route_specifier': "rds"|"route_config"|"scoped_routes"; + 'strip_port_mode': "strip_any_host_port"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpFilter.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpFilter.ts new file mode 100644 index 000000000..d1c1cbc06 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpFilter.ts @@ -0,0 +1,86 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../../google/protobuf/Any'; +import type { ExtensionConfigSource as _envoy_config_core_v3_ExtensionConfigSource, ExtensionConfigSource__Output as _envoy_config_core_v3_ExtensionConfigSource__Output } from '../../../../../../envoy/config/core/v3/ExtensionConfigSource'; + +/** + * [#next-free-field: 7] + */ +export interface HttpFilter { + /** + * The name of the filter configuration. The name is used as a fallback to + * select an extension if the type of the configuration proto is not + * sufficient. It also serves as a resource name in ExtensionConfigDS. + */ + 'name'?: (string); + /** + * Filter specific configuration which depends on the filter being instantiated. See the supported + * filters for further documentation. + * + * To support configuring a :ref:`match tree `, use an + * :ref:`ExtensionWithMatcher ` + * with the desired HTTP filter. + * [#extension-category: envoy.filters.http] + */ + 'typed_config'?: (_google_protobuf_Any | null); + /** + * Configuration source specifier for an extension configuration discovery service. + * In case of a failure and without the default configuration, the HTTP listener responds with code 500. + * Extension configs delivered through this mechanism are not expected to require warming (see https://github.com/envoyproxy/envoy/issues/12061). + * + * To support configuring a :ref:`match tree `, use an + * :ref:`ExtensionWithMatcher ` + * with the desired HTTP filter. This works for both the default filter configuration as well + * as for filters provided via the API. + */ + 'config_discovery'?: (_envoy_config_core_v3_ExtensionConfigSource | null); + /** + * If true, clients that do not support this filter may ignore the + * filter but otherwise accept the config. + * Otherwise, clients that do not support this filter must reject the config. + * This is also same with typed per filter config. + */ + 'is_optional'?: (boolean); + 'config_type'?: "typed_config"|"config_discovery"; +} + +/** + * [#next-free-field: 7] + */ +export interface HttpFilter__Output { + /** + * The name of the filter configuration. The name is used as a fallback to + * select an extension if the type of the configuration proto is not + * sufficient. It also serves as a resource name in ExtensionConfigDS. + */ + 'name': (string); + /** + * Filter specific configuration which depends on the filter being instantiated. See the supported + * filters for further documentation. + * + * To support configuring a :ref:`match tree `, use an + * :ref:`ExtensionWithMatcher ` + * with the desired HTTP filter. + * [#extension-category: envoy.filters.http] + */ + 'typed_config'?: (_google_protobuf_Any__Output | null); + /** + * Configuration source specifier for an extension configuration discovery service. + * In case of a failure and without the default configuration, the HTTP listener responds with code 500. + * Extension configs delivered through this mechanism are not expected to require warming (see https://github.com/envoyproxy/envoy/issues/12061). + * + * To support configuring a :ref:`match tree `, use an + * :ref:`ExtensionWithMatcher ` + * with the desired HTTP filter. This works for both the default filter configuration as well + * as for filters provided via the API. + */ + 'config_discovery'?: (_envoy_config_core_v3_ExtensionConfigSource__Output | null); + /** + * If true, clients that do not support this filter may ignore the + * filter but otherwise accept the config. + * Otherwise, clients that do not support this filter must reject the config. + * This is also same with typed per filter config. + */ + 'is_optional': (boolean); + 'config_type': "typed_config"|"config_discovery"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/LocalReplyConfig.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/LocalReplyConfig.ts new file mode 100644 index 000000000..04de11fcb --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/LocalReplyConfig.ts @@ -0,0 +1,106 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +import type { ResponseMapper as _envoy_extensions_filters_network_http_connection_manager_v3_ResponseMapper, ResponseMapper__Output as _envoy_extensions_filters_network_http_connection_manager_v3_ResponseMapper__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/ResponseMapper'; +import type { SubstitutionFormatString as _envoy_config_core_v3_SubstitutionFormatString, SubstitutionFormatString__Output as _envoy_config_core_v3_SubstitutionFormatString__Output } from '../../../../../../envoy/config/core/v3/SubstitutionFormatString'; + +/** + * The configuration to customize local reply returned by Envoy. + */ +export interface LocalReplyConfig { + /** + * Configuration of list of mappers which allows to filter and change local response. + * The mappers will be checked by the specified order until one is matched. + */ + 'mappers'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ResponseMapper)[]; + /** + * The configuration to form response body from the :ref:`command operators ` + * and to specify response content type as one of: plain/text or application/json. + * + * Example one: "plain/text" ``body_format``. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * text_format: "%LOCAL_REPLY_BODY%:%RESPONSE_CODE%:path=%REQ(:path)%\n" + * + * The following response body in "plain/text" format will be generated for a request with + * local reply body of "upstream connection error", response_code=503 and path=/foo. + * + * .. code-block:: text + * + * upstream connect error:503:path=/foo + * + * Example two: "application/json" ``body_format``. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * json_format: + * status: "%RESPONSE_CODE%" + * message: "%LOCAL_REPLY_BODY%" + * path: "%REQ(:path)%" + * + * The following response body in "application/json" format would be generated for a request with + * local reply body of "upstream connection error", response_code=503 and path=/foo. + * + * .. code-block:: json + * + * { + * "status": 503, + * "message": "upstream connection error", + * "path": "/foo" + * } + */ + 'body_format'?: (_envoy_config_core_v3_SubstitutionFormatString | null); +} + +/** + * The configuration to customize local reply returned by Envoy. + */ +export interface LocalReplyConfig__Output { + /** + * Configuration of list of mappers which allows to filter and change local response. + * The mappers will be checked by the specified order until one is matched. + */ + 'mappers': (_envoy_extensions_filters_network_http_connection_manager_v3_ResponseMapper__Output)[]; + /** + * The configuration to form response body from the :ref:`command operators ` + * and to specify response content type as one of: plain/text or application/json. + * + * Example one: "plain/text" ``body_format``. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * text_format: "%LOCAL_REPLY_BODY%:%RESPONSE_CODE%:path=%REQ(:path)%\n" + * + * The following response body in "plain/text" format will be generated for a request with + * local reply body of "upstream connection error", response_code=503 and path=/foo. + * + * .. code-block:: text + * + * upstream connect error:503:path=/foo + * + * Example two: "application/json" ``body_format``. + * + * .. validated-code-block:: yaml + * :type-name: envoy.config.core.v3.SubstitutionFormatString + * + * json_format: + * status: "%RESPONSE_CODE%" + * message: "%LOCAL_REPLY_BODY%" + * path: "%REQ(:path)%" + * + * The following response body in "application/json" format would be generated for a request with + * local reply body of "upstream connection error", response_code=503 and path=/foo. + * + * .. code-block:: json + * + * { + * "status": 503, + * "message": "upstream connection error", + * "path": "/foo" + * } + */ + 'body_format': (_envoy_config_core_v3_SubstitutionFormatString__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/Rds.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/Rds.ts similarity index 62% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/Rds.ts rename to packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/Rds.ts index be9c038a6..b99e2f1bd 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/Rds.ts +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/Rds.ts @@ -1,12 +1,12 @@ -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto -import type { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../../../../envoy/api/v2/core/ConfigSource'; +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../../../envoy/config/core/v3/ConfigSource'; export interface Rds { /** * Configuration source specifier for RDS. */ - 'config_source'?: (_envoy_api_v2_core_ConfigSource); + 'config_source'?: (_envoy_config_core_v3_ConfigSource | null); /** * The name of the route configuration. This name will be passed to the RDS * API. This allows an Envoy configuration with multiple HTTP listeners (and @@ -20,7 +20,7 @@ export interface Rds__Output { /** * Configuration source specifier for RDS. */ - 'config_source'?: (_envoy_api_v2_core_ConfigSource__Output); + 'config_source': (_envoy_config_core_v3_ConfigSource__Output | null); /** * The name of the route configuration. This name will be passed to the RDS * API. This allows an Envoy configuration with multiple HTTP listeners (and diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/RequestIDExtension.ts similarity index 60% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension.ts rename to packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/RequestIDExtension.ts index 2f043d4a8..ba1789a80 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/RequestIDExtension.ts +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/RequestIDExtension.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../../google/protobuf/Any'; @@ -6,12 +6,12 @@ export interface RequestIDExtension { /** * Request ID extension specific configuration. */ - 'typed_config'?: (_google_protobuf_Any); + 'typed_config'?: (_google_protobuf_Any | null); } export interface RequestIDExtension__Output { /** * Request ID extension specific configuration. */ - 'typed_config'?: (_google_protobuf_Any__Output); + 'typed_config': (_google_protobuf_Any__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ResponseMapper.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ResponseMapper.ts new file mode 100644 index 000000000..26d14a07d --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ResponseMapper.ts @@ -0,0 +1,67 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +import type { AccessLogFilter as _envoy_config_accesslog_v3_AccessLogFilter, AccessLogFilter__Output as _envoy_config_accesslog_v3_AccessLogFilter__Output } from '../../../../../../envoy/config/accesslog/v3/AccessLogFilter'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../../../google/protobuf/UInt32Value'; +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../../../envoy/config/core/v3/DataSource'; +import type { SubstitutionFormatString as _envoy_config_core_v3_SubstitutionFormatString, SubstitutionFormatString__Output as _envoy_config_core_v3_SubstitutionFormatString__Output } from '../../../../../../envoy/config/core/v3/SubstitutionFormatString'; +import type { HeaderValueOption as _envoy_config_core_v3_HeaderValueOption, HeaderValueOption__Output as _envoy_config_core_v3_HeaderValueOption__Output } from '../../../../../../envoy/config/core/v3/HeaderValueOption'; + +/** + * The configuration to filter and change local response. + * [#next-free-field: 6] + */ +export interface ResponseMapper { + /** + * Filter to determine if this mapper should apply. + */ + 'filter'?: (_envoy_config_accesslog_v3_AccessLogFilter | null); + /** + * The new response status code if specified. + */ + 'status_code'?: (_google_protobuf_UInt32Value | null); + /** + * The new local reply body text if specified. It will be used in the `%LOCAL_REPLY_BODY%` + * command operator in the `body_format`. + */ + 'body'?: (_envoy_config_core_v3_DataSource | null); + /** + * A per mapper `body_format` to override the :ref:`body_format `. + * It will be used when this mapper is matched. + */ + 'body_format_override'?: (_envoy_config_core_v3_SubstitutionFormatString | null); + /** + * HTTP headers to add to a local reply. This allows the response mapper to append, to add + * or to override headers of any local reply before it is sent to a downstream client. + */ + 'headers_to_add'?: (_envoy_config_core_v3_HeaderValueOption)[]; +} + +/** + * The configuration to filter and change local response. + * [#next-free-field: 6] + */ +export interface ResponseMapper__Output { + /** + * Filter to determine if this mapper should apply. + */ + 'filter': (_envoy_config_accesslog_v3_AccessLogFilter__Output | null); + /** + * The new response status code if specified. + */ + 'status_code': (_google_protobuf_UInt32Value__Output | null); + /** + * The new local reply body text if specified. It will be used in the `%LOCAL_REPLY_BODY%` + * command operator in the `body_format`. + */ + 'body': (_envoy_config_core_v3_DataSource__Output | null); + /** + * A per mapper `body_format` to override the :ref:`body_format `. + * It will be used when this mapper is matched. + */ + 'body_format_override': (_envoy_config_core_v3_SubstitutionFormatString__Output | null); + /** + * HTTP headers to add to a local reply. This allows the response mapper to append, to add + * or to override headers of any local reply before it is sent to a downstream client. + */ + 'headers_to_add': (_envoy_config_core_v3_HeaderValueOption__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRds.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRds.ts new file mode 100644 index 000000000..5f7d2b6fe --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRds.ts @@ -0,0 +1,27 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../../../envoy/config/core/v3/ConfigSource'; + +export interface ScopedRds { + /** + * Configuration source specifier for scoped RDS. + */ + 'scoped_rds_config_source'?: (_envoy_config_core_v3_ConfigSource | null); + /** + * xdstp:// resource locator for scoped RDS collection. + * [#not-implemented-hide:] + */ + 'srds_resources_locator'?: (string); +} + +export interface ScopedRds__Output { + /** + * Configuration source specifier for scoped RDS. + */ + 'scoped_rds_config_source': (_envoy_config_core_v3_ConfigSource__Output | null); + /** + * xdstp:// resource locator for scoped RDS collection. + * [#not-implemented-hide:] + */ + 'srds_resources_locator': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRouteConfigurationsList.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRouteConfigurationsList.ts new file mode 100644 index 000000000..e7f05e340 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRouteConfigurationsList.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto + +import type { ScopedRouteConfiguration as _envoy_config_route_v3_ScopedRouteConfiguration, ScopedRouteConfiguration__Output as _envoy_config_route_v3_ScopedRouteConfiguration__Output } from '../../../../../../envoy/config/route/v3/ScopedRouteConfiguration'; + +/** + * This message is used to work around the limitations with 'oneof' and repeated fields. + */ +export interface ScopedRouteConfigurationsList { + 'scoped_route_configurations'?: (_envoy_config_route_v3_ScopedRouteConfiguration)[]; +} + +/** + * This message is used to work around the limitations with 'oneof' and repeated fields. + */ +export interface ScopedRouteConfigurationsList__Output { + 'scoped_route_configurations': (_envoy_config_route_v3_ScopedRouteConfiguration__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRoutes.ts similarity index 55% rename from packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes.ts rename to packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRoutes.ts index b9b20d2bf..041af534b 100644 --- a/packages/grpc-js-xds/src/generated/envoy/config/filter/network/http_connection_manager/v2/ScopedRoutes.ts +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/filters/network/http_connection_manager/v3/ScopedRoutes.ts @@ -1,28 +1,28 @@ -// Original file: deps/envoy-api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto +// Original file: deps/envoy-api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto -import type { ConfigSource as _envoy_api_v2_core_ConfigSource, ConfigSource__Output as _envoy_api_v2_core_ConfigSource__Output } from '../../../../../../envoy/api/v2/core/ConfigSource'; -import type { ScopedRouteConfigurationsList as _envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList, ScopedRouteConfigurationsList__Output as _envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/ScopedRouteConfigurationsList'; -import type { ScopedRds as _envoy_config_filter_network_http_connection_manager_v2_ScopedRds, ScopedRds__Output as _envoy_config_filter_network_http_connection_manager_v2_ScopedRds__Output } from '../../../../../../envoy/config/filter/network/http_connection_manager/v2/ScopedRds'; +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../../../envoy/config/core/v3/ConfigSource'; +import type { ScopedRouteConfigurationsList as _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRouteConfigurationsList, ScopedRouteConfigurationsList__Output as _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRouteConfigurationsList__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/ScopedRouteConfigurationsList'; +import type { ScopedRds as _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRds, ScopedRds__Output as _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRds__Output } from '../../../../../../envoy/extensions/filters/network/http_connection_manager/v3/ScopedRds'; /** * Specifies the mechanism for constructing key fragments which are composed into scope keys. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder { /** * Specifies how a header field's value should be extracted. */ - 'header_value_extractor'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor); + 'header_value_extractor'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor | null); 'type'?: "header_value_extractor"; } /** * Specifies the mechanism for constructing key fragments which are composed into scope keys. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder__Output { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder__Output { /** * Specifies how a header field's value should be extracted. */ - 'header_value_extractor'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor__Output); + 'header_value_extractor'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor__Output | null); 'type': "header_value_extractor"; } @@ -45,9 +45,13 @@ export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedR * * Each 'a=b' key-value pair constitutes an 'element' of the header field. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor { /** * The name of the header field to extract the value from. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. */ 'name'?: (string); /** @@ -66,7 +70,7 @@ export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedR /** * Specifies the key value pair to extract the value from. */ - 'element'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement); + 'element'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement | null); 'extract_type'?: "index"|"element"; } @@ -89,9 +93,13 @@ export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedR * * Each 'a=b' key-value pair constitutes an 'element' of the header field. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor__Output { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor__Output { /** * The name of the header field to extract the value from. + * + * .. note:: + * + * If the header appears multiple times only the first value is used. */ 'name': (string); /** @@ -110,14 +118,14 @@ export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedR /** * Specifies the key value pair to extract the value from. */ - 'element'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement__Output); + 'element'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement__Output | null); 'extract_type': "index"|"element"; } /** * Specifies a header field's key value pair to match on. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement { /** * The separator between key and value (e.g., '=' separates 'k=v;...'). * If an element is an empty string, the element is ignored. @@ -135,7 +143,7 @@ export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedR /** * Specifies a header field's key value pair to match on. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement__Output { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder_HeaderValueExtractor_KvElement__Output { /** * The separator between key and value (e.g., '=' separates 'k=v;...'). * If an element is an empty string, the element is ignored. @@ -152,42 +160,42 @@ export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedR /** * Specifies the mechanism for constructing "scope keys" based on HTTP request attributes. These - * keys are matched against a set of :ref:`Key` - * objects assembled from :ref:`ScopedRouteConfiguration` + * keys are matched against a set of :ref:`Key` + * objects assembled from :ref:`ScopedRouteConfiguration` * messages distributed via SRDS (the Scoped Route Discovery Service) or assigned statically via - * :ref:`scoped_route_configurations_list`. + * :ref:`scoped_route_configurations_list`. * * Upon receiving a request's headers, the Router will build a key using the algorithm specified * by this message. This key will be used to look up the routing table (i.e., the - * :ref:`RouteConfiguration`) to use for the request. + * :ref:`RouteConfiguration`) to use for the request. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder { /** * The final(built) scope key consists of the ordered union of these fragments, which are compared in order with the - * fragments of a :ref:`ScopedRouteConfiguration`. + * fragments of a :ref:`ScopedRouteConfiguration`. * A missing fragment during comparison will make the key invalid, i.e., the computed key doesn't match any key. */ - 'fragments'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder)[]; + 'fragments'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder)[]; } /** * Specifies the mechanism for constructing "scope keys" based on HTTP request attributes. These - * keys are matched against a set of :ref:`Key` - * objects assembled from :ref:`ScopedRouteConfiguration` + * keys are matched against a set of :ref:`Key` + * objects assembled from :ref:`ScopedRouteConfiguration` * messages distributed via SRDS (the Scoped Route Discovery Service) or assigned statically via - * :ref:`scoped_route_configurations_list`. + * :ref:`scoped_route_configurations_list`. * * Upon receiving a request's headers, the Router will build a key using the algorithm specified * by this message. This key will be used to look up the routing table (i.e., the - * :ref:`RouteConfiguration`) to use for the request. + * :ref:`RouteConfiguration`) to use for the request. */ -export interface _envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder__Output { +export interface _envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder__Output { /** * The final(built) scope key consists of the ordered union of these fragments, which are compared in order with the - * fragments of a :ref:`ScopedRouteConfiguration`. + * fragments of a :ref:`ScopedRouteConfiguration`. * A missing fragment during comparison will make the key invalid, i.e., the computed key doesn't match any key. */ - 'fragments': (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder__Output)[]; + 'fragments': (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder_FragmentBuilder__Output)[]; } /** @@ -201,29 +209,29 @@ export interface ScopedRoutes { /** * The algorithm to use for constructing a scope key for each request. */ - 'scope_key_builder'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder); + 'scope_key_builder'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder | null); /** * Configuration source specifier for RDS. * This config source is used to subscribe to RouteConfiguration resources specified in * ScopedRouteConfiguration messages. */ - 'rds_config_source'?: (_envoy_api_v2_core_ConfigSource); + 'rds_config_source'?: (_envoy_config_core_v3_ConfigSource | null); /** * The set of routing scopes corresponding to the HCM. A scope is assigned to a request by * matching a key constructed from the request's attributes according to the algorithm specified * by the - * :ref:`ScopeKeyBuilder` + * :ref:`ScopeKeyBuilder` * in this message. */ - 'scoped_route_configurations_list'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList); + 'scoped_route_configurations_list'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRouteConfigurationsList | null); /** * The set of routing scopes associated with the HCM will be dynamically loaded via the SRDS * API. A scope is assigned to a request by matching a key constructed from the request's * attributes according to the algorithm specified by the - * :ref:`ScopeKeyBuilder` + * :ref:`ScopeKeyBuilder` * in this message. */ - 'scoped_rds'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRds); + 'scoped_rds'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRds | null); 'config_specifier'?: "scoped_route_configurations_list"|"scoped_rds"; } @@ -238,28 +246,28 @@ export interface ScopedRoutes__Output { /** * The algorithm to use for constructing a scope key for each request. */ - 'scope_key_builder'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRoutes_ScopeKeyBuilder__Output); + 'scope_key_builder': (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes_ScopeKeyBuilder__Output | null); /** * Configuration source specifier for RDS. * This config source is used to subscribe to RouteConfiguration resources specified in * ScopedRouteConfiguration messages. */ - 'rds_config_source'?: (_envoy_api_v2_core_ConfigSource__Output); + 'rds_config_source': (_envoy_config_core_v3_ConfigSource__Output | null); /** * The set of routing scopes corresponding to the HCM. A scope is assigned to a request by * matching a key constructed from the request's attributes according to the algorithm specified * by the - * :ref:`ScopeKeyBuilder` + * :ref:`ScopeKeyBuilder` * in this message. */ - 'scoped_route_configurations_list'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRouteConfigurationsList__Output); + 'scoped_route_configurations_list'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRouteConfigurationsList__Output | null); /** * The set of routing scopes associated with the HCM will be dynamically loaded via the SRDS * API. A scope is assigned to a request by matching a key constructed from the request's * attributes according to the algorithm specified by the - * :ref:`ScopeKeyBuilder` + * :ref:`ScopeKeyBuilder` * in this message. */ - 'scoped_rds'?: (_envoy_config_filter_network_http_connection_manager_v2_ScopedRds__Output); + 'scoped_rds'?: (_envoy_extensions_filters_network_http_connection_manager_v3_ScopedRds__Output | null); 'config_specifier': "scoped_route_configurations_list"|"scoped_rds"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/CertificateProviderPluginInstance.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/CertificateProviderPluginInstance.ts new file mode 100644 index 000000000..3a3100f55 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/CertificateProviderPluginInstance.ts @@ -0,0 +1,52 @@ +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto + + +/** + * Indicates a certificate to be obtained from a named CertificateProvider plugin instance. + * The plugin instances are defined in the client's bootstrap file. + * The plugin allows certificates to be fetched/refreshed over the network asynchronously with + * respect to the TLS handshake. + * [#not-implemented-hide:] + */ +export interface CertificateProviderPluginInstance { + /** + * Provider instance name. If not present, defaults to "default". + * + * Instance names should generally be defined not in terms of the underlying provider + * implementation (e.g., "file_watcher") but rather in terms of the function of the + * certificates (e.g., "foo_deployment_identity"). + */ + 'instance_name'?: (string); + /** + * Opaque name used to specify certificate instances or types. For example, "ROOTCA" to specify + * a root-certificate (validation context) or "example.com" to specify a certificate for a + * particular domain. Not all provider instances will actually use this field, so the value + * defaults to the empty string. + */ + 'certificate_name'?: (string); +} + +/** + * Indicates a certificate to be obtained from a named CertificateProvider plugin instance. + * The plugin instances are defined in the client's bootstrap file. + * The plugin allows certificates to be fetched/refreshed over the network asynchronously with + * respect to the TLS handshake. + * [#not-implemented-hide:] + */ +export interface CertificateProviderPluginInstance__Output { + /** + * Provider instance name. If not present, defaults to "default". + * + * Instance names should generally be defined not in terms of the underlying provider + * implementation (e.g., "file_watcher") but rather in terms of the function of the + * certificates (e.g., "foo_deployment_identity"). + */ + 'instance_name': (string); + /** + * Opaque name used to specify certificate instances or types. For example, "ROOTCA" to specify + * a root-certificate (validation context) or "example.com" to specify a certificate for a + * particular domain. Not all provider instances will actually use this field, so the value + * defaults to the empty string. + */ + 'certificate_name': (string); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/CertificateValidationContext.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/CertificateValidationContext.ts new file mode 100644 index 000000000..379320086 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/CertificateValidationContext.ts @@ -0,0 +1,372 @@ +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto + +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../../envoy/config/core/v3/DataSource'; +import type { BoolValue as _google_protobuf_BoolValue, BoolValue__Output as _google_protobuf_BoolValue__Output } from '../../../../../google/protobuf/BoolValue'; +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../../envoy/type/matcher/v3/StringMatcher'; +import type { WatchedDirectory as _envoy_config_core_v3_WatchedDirectory, WatchedDirectory__Output as _envoy_config_core_v3_WatchedDirectory__Output } from '../../../../../envoy/config/core/v3/WatchedDirectory'; +import type { TypedExtensionConfig as _envoy_config_core_v3_TypedExtensionConfig, TypedExtensionConfig__Output as _envoy_config_core_v3_TypedExtensionConfig__Output } from '../../../../../envoy/config/core/v3/TypedExtensionConfig'; +import type { CertificateProviderPluginInstance as _envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance, CertificateProviderPluginInstance__Output as _envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance__Output } from '../../../../../envoy/extensions/transport_sockets/tls/v3/CertificateProviderPluginInstance'; + +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto + +/** + * Peer certificate verification mode. + */ +export enum _envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_TrustChainVerification { + /** + * Perform default certificate verification (e.g., against CA / verification lists) + */ + VERIFY_TRUST_CHAIN = 0, + /** + * Connections where the certificate fails verification will be permitted. + * For HTTP connections, the result of certificate verification can be used in route matching. ( + * see :ref:`validated ` ). + */ + ACCEPT_UNTRUSTED = 1, +} + +/** + * [#next-free-field: 14] + */ +export interface CertificateValidationContext { + /** + * TLS certificate data containing certificate authority certificates to use in verifying + * a presented peer certificate (e.g. server certificate for clusters or client certificate + * for listeners). If not specified and a peer certificate is presented it will not be + * verified. By default, a client certificate is optional, unless one of the additional + * options (:ref:`require_client_certificate + * `, + * :ref:`verify_certificate_spki + * `, + * :ref:`verify_certificate_hash + * `, or + * :ref:`match_subject_alt_names + * `) is also + * specified. + * + * It can optionally contain certificate revocation lists, in which case Envoy will verify + * that the presented peer certificate has not been revoked by one of the included CRLs. Note + * that if a CRL is provided for any certificate authority in a trust chain, a CRL must be + * provided for all certificate authorities in that chain. Failure to do so will result in + * verification failure for both revoked and unrevoked certificates from that chain. + * + * See :ref:`the TLS overview ` for a list of common + * system CA locations. + * + * If *trusted_ca* is a filesystem path, a watch will be added to the parent + * directory for any file moves to support rotation. This currently only + * applies to dynamic secrets, when the *CertificateValidationContext* is + * delivered via SDS. + * + * Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + * + * [#next-major-version: This field and watched_directory below should ideally be moved into a + * separate sub-message, since there's no point in specifying the latter field without this one.] + */ + 'trusted_ca'?: (_envoy_config_core_v3_DataSource | null); + /** + * An optional list of hex-encoded SHA-256 hashes. If specified, Envoy will verify that + * the SHA-256 of the DER-encoded presented certificate matches one of the specified values. + * + * A hex-encoded SHA-256 of the certificate can be generated with the following command: + * + * .. code-block:: bash + * + * $ openssl x509 -in path/to/client.crt -outform DER | openssl dgst -sha256 | cut -d" " -f2 + * df6ff72fe9116521268f6f2dd4966f51df479883fe7037b39f75916ac3049d1a + * + * A long hex-encoded and colon-separated SHA-256 (a.k.a. "fingerprint") of the certificate + * can be generated with the following command: + * + * .. code-block:: bash + * + * $ openssl x509 -in path/to/client.crt -noout -fingerprint -sha256 | cut -d"=" -f2 + * DF:6F:F7:2F:E9:11:65:21:26:8F:6F:2D:D4:96:6F:51:DF:47:98:83:FE:70:37:B3:9F:75:91:6A:C3:04:9D:1A + * + * Both of those formats are acceptable. + * + * When both: + * :ref:`verify_certificate_hash + * ` and + * :ref:`verify_certificate_spki + * ` are specified, + * a hash matching value from either of the lists will result in the certificate being accepted. + */ + 'verify_certificate_hash'?: (string)[]; + /** + * An optional list of base64-encoded SHA-256 hashes. If specified, Envoy will verify that the + * SHA-256 of the DER-encoded Subject Public Key Information (SPKI) of the presented certificate + * matches one of the specified values. + * + * A base64-encoded SHA-256 of the Subject Public Key Information (SPKI) of the certificate + * can be generated with the following command: + * + * .. code-block:: bash + * + * $ openssl x509 -in path/to/client.crt -noout -pubkey + * | openssl pkey -pubin -outform DER + * | openssl dgst -sha256 -binary + * | openssl enc -base64 + * NvqYIYSbgK2vCJpQhObf77vv+bQWtc5ek5RIOwPiC9A= + * + * This is the format used in HTTP Public Key Pinning. + * + * When both: + * :ref:`verify_certificate_hash + * ` and + * :ref:`verify_certificate_spki + * ` are specified, + * a hash matching value from either of the lists will result in the certificate being accepted. + * + * .. attention:: + * + * This option is preferred over :ref:`verify_certificate_hash + * `, + * because SPKI is tied to a private key, so it doesn't change when the certificate + * is renewed using the same private key. + */ + 'verify_certificate_spki'?: (string)[]; + /** + * [#not-implemented-hide:] Must present signed certificate time-stamp. + */ + 'require_signed_certificate_timestamp'?: (_google_protobuf_BoolValue | null); + /** + * An optional `certificate revocation list + * `_ + * (in PEM format). If specified, Envoy will verify that the presented peer + * certificate has not been revoked by this CRL. If this DataSource contains + * multiple CRLs, all of them will be used. Note that if a CRL is provided + * for any certificate authority in a trust chain, a CRL must be provided + * for all certificate authorities in that chain. Failure to do so will + * result in verification failure for both revoked and unrevoked certificates + * from that chain. + */ + 'crl'?: (_envoy_config_core_v3_DataSource | null); + /** + * If specified, Envoy will not reject expired certificates. + */ + 'allow_expired_certificate'?: (boolean); + /** + * An optional list of Subject Alternative name matchers. If specified, Envoy will verify that the + * Subject Alternative Name of the presented certificate matches one of the specified matchers. + * + * When a certificate has wildcard DNS SAN entries, to match a specific client, it should be + * configured with exact match type in the :ref:`string matcher `. + * For example if the certificate has "\*.example.com" as DNS SAN entry, to allow only "api.example.com", + * it should be configured as shown below. + * + * .. code-block:: yaml + * + * match_subject_alt_names: + * exact: "api.example.com" + * + * .. attention:: + * + * Subject Alternative Names are easily spoofable and verifying only them is insecure, + * therefore this option must be used together with :ref:`trusted_ca + * `. + */ + 'match_subject_alt_names'?: (_envoy_type_matcher_v3_StringMatcher)[]; + /** + * Certificate trust chain verification mode. + */ + 'trust_chain_verification'?: (_envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_TrustChainVerification | keyof typeof _envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_TrustChainVerification); + /** + * If specified, updates of a file-based *trusted_ca* source will be triggered + * by this watch. This allows explicit control over the path watched, by + * default the parent directory of the filesystem path in *trusted_ca* is + * watched if this field is not specified. This only applies when a + * *CertificateValidationContext* is delivered by SDS with references to + * filesystem paths. See the :ref:`SDS key rotation ` + * documentation for further details. + */ + 'watched_directory'?: (_envoy_config_core_v3_WatchedDirectory | null); + /** + * The configuration of an extension specific certificate validator. + * If specified, all validation is done by the specified validator, + * and the behavior of all other validation settings is defined by the specified validator (and may be entirely ignored, unused, and unvalidated). + * Refer to the documentation for the specified validator. If you do not want a custom validation algorithm, do not set this field. + * [#extension-category: envoy.tls.cert_validator] + */ + 'custom_validator_config'?: (_envoy_config_core_v3_TypedExtensionConfig | null); + /** + * Certificate provider instance for fetching TLS certificates. + * + * Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + * [#not-implemented-hide:] + */ + 'ca_certificate_provider_instance'?: (_envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance | null); +} + +/** + * [#next-free-field: 14] + */ +export interface CertificateValidationContext__Output { + /** + * TLS certificate data containing certificate authority certificates to use in verifying + * a presented peer certificate (e.g. server certificate for clusters or client certificate + * for listeners). If not specified and a peer certificate is presented it will not be + * verified. By default, a client certificate is optional, unless one of the additional + * options (:ref:`require_client_certificate + * `, + * :ref:`verify_certificate_spki + * `, + * :ref:`verify_certificate_hash + * `, or + * :ref:`match_subject_alt_names + * `) is also + * specified. + * + * It can optionally contain certificate revocation lists, in which case Envoy will verify + * that the presented peer certificate has not been revoked by one of the included CRLs. Note + * that if a CRL is provided for any certificate authority in a trust chain, a CRL must be + * provided for all certificate authorities in that chain. Failure to do so will result in + * verification failure for both revoked and unrevoked certificates from that chain. + * + * See :ref:`the TLS overview ` for a list of common + * system CA locations. + * + * If *trusted_ca* is a filesystem path, a watch will be added to the parent + * directory for any file moves to support rotation. This currently only + * applies to dynamic secrets, when the *CertificateValidationContext* is + * delivered via SDS. + * + * Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + * + * [#next-major-version: This field and watched_directory below should ideally be moved into a + * separate sub-message, since there's no point in specifying the latter field without this one.] + */ + 'trusted_ca': (_envoy_config_core_v3_DataSource__Output | null); + /** + * An optional list of hex-encoded SHA-256 hashes. If specified, Envoy will verify that + * the SHA-256 of the DER-encoded presented certificate matches one of the specified values. + * + * A hex-encoded SHA-256 of the certificate can be generated with the following command: + * + * .. code-block:: bash + * + * $ openssl x509 -in path/to/client.crt -outform DER | openssl dgst -sha256 | cut -d" " -f2 + * df6ff72fe9116521268f6f2dd4966f51df479883fe7037b39f75916ac3049d1a + * + * A long hex-encoded and colon-separated SHA-256 (a.k.a. "fingerprint") of the certificate + * can be generated with the following command: + * + * .. code-block:: bash + * + * $ openssl x509 -in path/to/client.crt -noout -fingerprint -sha256 | cut -d"=" -f2 + * DF:6F:F7:2F:E9:11:65:21:26:8F:6F:2D:D4:96:6F:51:DF:47:98:83:FE:70:37:B3:9F:75:91:6A:C3:04:9D:1A + * + * Both of those formats are acceptable. + * + * When both: + * :ref:`verify_certificate_hash + * ` and + * :ref:`verify_certificate_spki + * ` are specified, + * a hash matching value from either of the lists will result in the certificate being accepted. + */ + 'verify_certificate_hash': (string)[]; + /** + * An optional list of base64-encoded SHA-256 hashes. If specified, Envoy will verify that the + * SHA-256 of the DER-encoded Subject Public Key Information (SPKI) of the presented certificate + * matches one of the specified values. + * + * A base64-encoded SHA-256 of the Subject Public Key Information (SPKI) of the certificate + * can be generated with the following command: + * + * .. code-block:: bash + * + * $ openssl x509 -in path/to/client.crt -noout -pubkey + * | openssl pkey -pubin -outform DER + * | openssl dgst -sha256 -binary + * | openssl enc -base64 + * NvqYIYSbgK2vCJpQhObf77vv+bQWtc5ek5RIOwPiC9A= + * + * This is the format used in HTTP Public Key Pinning. + * + * When both: + * :ref:`verify_certificate_hash + * ` and + * :ref:`verify_certificate_spki + * ` are specified, + * a hash matching value from either of the lists will result in the certificate being accepted. + * + * .. attention:: + * + * This option is preferred over :ref:`verify_certificate_hash + * `, + * because SPKI is tied to a private key, so it doesn't change when the certificate + * is renewed using the same private key. + */ + 'verify_certificate_spki': (string)[]; + /** + * [#not-implemented-hide:] Must present signed certificate time-stamp. + */ + 'require_signed_certificate_timestamp': (_google_protobuf_BoolValue__Output | null); + /** + * An optional `certificate revocation list + * `_ + * (in PEM format). If specified, Envoy will verify that the presented peer + * certificate has not been revoked by this CRL. If this DataSource contains + * multiple CRLs, all of them will be used. Note that if a CRL is provided + * for any certificate authority in a trust chain, a CRL must be provided + * for all certificate authorities in that chain. Failure to do so will + * result in verification failure for both revoked and unrevoked certificates + * from that chain. + */ + 'crl': (_envoy_config_core_v3_DataSource__Output | null); + /** + * If specified, Envoy will not reject expired certificates. + */ + 'allow_expired_certificate': (boolean); + /** + * An optional list of Subject Alternative name matchers. If specified, Envoy will verify that the + * Subject Alternative Name of the presented certificate matches one of the specified matchers. + * + * When a certificate has wildcard DNS SAN entries, to match a specific client, it should be + * configured with exact match type in the :ref:`string matcher `. + * For example if the certificate has "\*.example.com" as DNS SAN entry, to allow only "api.example.com", + * it should be configured as shown below. + * + * .. code-block:: yaml + * + * match_subject_alt_names: + * exact: "api.example.com" + * + * .. attention:: + * + * Subject Alternative Names are easily spoofable and verifying only them is insecure, + * therefore this option must be used together with :ref:`trusted_ca + * `. + */ + 'match_subject_alt_names': (_envoy_type_matcher_v3_StringMatcher__Output)[]; + /** + * Certificate trust chain verification mode. + */ + 'trust_chain_verification': (keyof typeof _envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_TrustChainVerification); + /** + * If specified, updates of a file-based *trusted_ca* source will be triggered + * by this watch. This allows explicit control over the path watched, by + * default the parent directory of the filesystem path in *trusted_ca* is + * watched if this field is not specified. This only applies when a + * *CertificateValidationContext* is delivered by SDS with references to + * filesystem paths. See the :ref:`SDS key rotation ` + * documentation for further details. + */ + 'watched_directory': (_envoy_config_core_v3_WatchedDirectory__Output | null); + /** + * The configuration of an extension specific certificate validator. + * If specified, all validation is done by the specified validator, + * and the behavior of all other validation settings is defined by the specified validator (and may be entirely ignored, unused, and unvalidated). + * Refer to the documentation for the specified validator. If you do not want a custom validation algorithm, do not set this field. + * [#extension-category: envoy.tls.cert_validator] + */ + 'custom_validator_config': (_envoy_config_core_v3_TypedExtensionConfig__Output | null); + /** + * Certificate provider instance for fetching TLS certificates. + * + * Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + * [#not-implemented-hide:] + */ + 'ca_certificate_provider_instance': (_envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/GenericSecret.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/GenericSecret.ts new file mode 100644 index 000000000..b206fb13a --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/GenericSecret.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/secret.proto + +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../../envoy/config/core/v3/DataSource'; + +export interface GenericSecret { + /** + * Secret of generic type and is available to filters. + */ + 'secret'?: (_envoy_config_core_v3_DataSource | null); +} + +export interface GenericSecret__Output { + /** + * Secret of generic type and is available to filters. + */ + 'secret': (_envoy_config_core_v3_DataSource__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/PrivateKeyProvider.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/PrivateKeyProvider.ts similarity index 67% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/auth/PrivateKeyProvider.ts rename to packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/PrivateKeyProvider.ts index 415448053..b4a2ad933 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/PrivateKeyProvider.ts +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/PrivateKeyProvider.ts @@ -1,7 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/common.proto +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto -import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../../google/protobuf/Struct'; -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../../google/protobuf/Any'; /** * BoringSSL private key method configuration. The private key methods are used for external @@ -14,12 +13,11 @@ export interface PrivateKeyProvider { * supported private key method provider type. */ 'provider_name'?: (string); - 'config'?: (_google_protobuf_Struct); - 'typed_config'?: (_google_protobuf_Any); + 'typed_config'?: (_google_protobuf_Any | null); /** * Private key method provider specific configuration. */ - 'config_type'?: "config"|"typed_config"; + 'config_type'?: "typed_config"; } /** @@ -33,10 +31,9 @@ export interface PrivateKeyProvider__Output { * supported private key method provider type. */ 'provider_name': (string); - 'config'?: (_google_protobuf_Struct__Output); - 'typed_config'?: (_google_protobuf_Any__Output); + 'typed_config'?: (_google_protobuf_Any__Output | null); /** * Private key method provider specific configuration. */ - 'config_type': "config"|"typed_config"; + 'config_type': "typed_config"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/SdsSecretConfig.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/SdsSecretConfig.ts new file mode 100644 index 000000000..38b850c50 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/SdsSecretConfig.ts @@ -0,0 +1,23 @@ +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/secret.proto + +import type { ConfigSource as _envoy_config_core_v3_ConfigSource, ConfigSource__Output as _envoy_config_core_v3_ConfigSource__Output } from '../../../../../envoy/config/core/v3/ConfigSource'; + +export interface SdsSecretConfig { + /** + * Name by which the secret can be uniquely referred to. When both name and config are specified, + * then secret can be fetched and/or reloaded via SDS. When only name is specified, then secret + * will be loaded from static resources. + */ + 'name'?: (string); + 'sds_config'?: (_envoy_config_core_v3_ConfigSource | null); +} + +export interface SdsSecretConfig__Output { + /** + * Name by which the secret can be uniquely referred to. When both name and config are specified, + * then secret can be fetched and/or reloaded via SDS. When only name is specified, then secret + * will be loaded from static resources. + */ + 'name': (string); + 'sds_config': (_envoy_config_core_v3_ConfigSource__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/Secret.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/Secret.ts new file mode 100644 index 000000000..c86957da5 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/Secret.ts @@ -0,0 +1,36 @@ +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/secret.proto + +import type { TlsCertificate as _envoy_extensions_transport_sockets_tls_v3_TlsCertificate, TlsCertificate__Output as _envoy_extensions_transport_sockets_tls_v3_TlsCertificate__Output } from '../../../../../envoy/extensions/transport_sockets/tls/v3/TlsCertificate'; +import type { TlsSessionTicketKeys as _envoy_extensions_transport_sockets_tls_v3_TlsSessionTicketKeys, TlsSessionTicketKeys__Output as _envoy_extensions_transport_sockets_tls_v3_TlsSessionTicketKeys__Output } from '../../../../../envoy/extensions/transport_sockets/tls/v3/TlsSessionTicketKeys'; +import type { CertificateValidationContext as _envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext, CertificateValidationContext__Output as _envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext__Output } from '../../../../../envoy/extensions/transport_sockets/tls/v3/CertificateValidationContext'; +import type { GenericSecret as _envoy_extensions_transport_sockets_tls_v3_GenericSecret, GenericSecret__Output as _envoy_extensions_transport_sockets_tls_v3_GenericSecret__Output } from '../../../../../envoy/extensions/transport_sockets/tls/v3/GenericSecret'; + +/** + * [#next-free-field: 6] + */ +export interface Secret { + /** + * Name (FQDN, UUID, SPKI, SHA256, etc.) by which the secret can be uniquely referred to. + */ + 'name'?: (string); + 'tls_certificate'?: (_envoy_extensions_transport_sockets_tls_v3_TlsCertificate | null); + 'session_ticket_keys'?: (_envoy_extensions_transport_sockets_tls_v3_TlsSessionTicketKeys | null); + 'validation_context'?: (_envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext | null); + 'generic_secret'?: (_envoy_extensions_transport_sockets_tls_v3_GenericSecret | null); + 'type'?: "tls_certificate"|"session_ticket_keys"|"validation_context"|"generic_secret"; +} + +/** + * [#next-free-field: 6] + */ +export interface Secret__Output { + /** + * Name (FQDN, UUID, SPKI, SHA256, etc.) by which the secret can be uniquely referred to. + */ + 'name': (string); + 'tls_certificate'?: (_envoy_extensions_transport_sockets_tls_v3_TlsCertificate__Output | null); + 'session_ticket_keys'?: (_envoy_extensions_transport_sockets_tls_v3_TlsSessionTicketKeys__Output | null); + 'validation_context'?: (_envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext__Output | null); + 'generic_secret'?: (_envoy_extensions_transport_sockets_tls_v3_GenericSecret__Output | null); + 'type': "tls_certificate"|"session_ticket_keys"|"validation_context"|"generic_secret"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsCertificate.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsCertificate.ts new file mode 100644 index 000000000..ce8046e95 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsCertificate.ts @@ -0,0 +1,127 @@ +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto + +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../../envoy/config/core/v3/DataSource'; +import type { PrivateKeyProvider as _envoy_extensions_transport_sockets_tls_v3_PrivateKeyProvider, PrivateKeyProvider__Output as _envoy_extensions_transport_sockets_tls_v3_PrivateKeyProvider__Output } from '../../../../../envoy/extensions/transport_sockets/tls/v3/PrivateKeyProvider'; +import type { WatchedDirectory as _envoy_config_core_v3_WatchedDirectory, WatchedDirectory__Output as _envoy_config_core_v3_WatchedDirectory__Output } from '../../../../../envoy/config/core/v3/WatchedDirectory'; + +/** + * [#next-free-field: 8] + */ +export interface TlsCertificate { + /** + * The TLS certificate chain. + * + * If *certificate_chain* is a filesystem path, a watch will be added to the + * parent directory for any file moves to support rotation. This currently + * only applies to dynamic secrets, when the *TlsCertificate* is delivered via + * SDS. + */ + 'certificate_chain'?: (_envoy_config_core_v3_DataSource | null); + /** + * The TLS private key. + * + * If *private_key* is a filesystem path, a watch will be added to the parent + * directory for any file moves to support rotation. This currently only + * applies to dynamic secrets, when the *TlsCertificate* is delivered via SDS. + */ + 'private_key'?: (_envoy_config_core_v3_DataSource | null); + /** + * The password to decrypt the TLS private key. If this field is not set, it is assumed that the + * TLS private key is not password encrypted. + */ + 'password'?: (_envoy_config_core_v3_DataSource | null); + /** + * The OCSP response to be stapled with this certificate during the handshake. + * The response must be DER-encoded and may only be provided via ``filename`` or + * ``inline_bytes``. The response may pertain to only one certificate. + */ + 'ocsp_staple'?: (_envoy_config_core_v3_DataSource | null); + /** + * [#not-implemented-hide:] + */ + 'signed_certificate_timestamp'?: (_envoy_config_core_v3_DataSource)[]; + /** + * BoringSSL private key method provider. This is an alternative to :ref:`private_key + * ` field. This can't be + * marked as ``oneof`` due to API compatibility reasons. Setting both :ref:`private_key + * ` and + * :ref:`private_key_provider + * ` fields will result in an + * error. + */ + 'private_key_provider'?: (_envoy_extensions_transport_sockets_tls_v3_PrivateKeyProvider | null); + /** + * If specified, updates of file-based *certificate_chain* and *private_key* + * sources will be triggered by this watch. The certificate/key pair will be + * read together and validated for atomic read consistency (i.e. no + * intervening modification occurred between cert/key read, verified by file + * hash comparisons). This allows explicit control over the path watched, by + * default the parent directories of the filesystem paths in + * *certificate_chain* and *private_key* are watched if this field is not + * specified. This only applies when a *TlsCertificate* is delivered by SDS + * with references to filesystem paths. See the :ref:`SDS key rotation + * ` documentation for further details. + */ + 'watched_directory'?: (_envoy_config_core_v3_WatchedDirectory | null); +} + +/** + * [#next-free-field: 8] + */ +export interface TlsCertificate__Output { + /** + * The TLS certificate chain. + * + * If *certificate_chain* is a filesystem path, a watch will be added to the + * parent directory for any file moves to support rotation. This currently + * only applies to dynamic secrets, when the *TlsCertificate* is delivered via + * SDS. + */ + 'certificate_chain': (_envoy_config_core_v3_DataSource__Output | null); + /** + * The TLS private key. + * + * If *private_key* is a filesystem path, a watch will be added to the parent + * directory for any file moves to support rotation. This currently only + * applies to dynamic secrets, when the *TlsCertificate* is delivered via SDS. + */ + 'private_key': (_envoy_config_core_v3_DataSource__Output | null); + /** + * The password to decrypt the TLS private key. If this field is not set, it is assumed that the + * TLS private key is not password encrypted. + */ + 'password': (_envoy_config_core_v3_DataSource__Output | null); + /** + * The OCSP response to be stapled with this certificate during the handshake. + * The response must be DER-encoded and may only be provided via ``filename`` or + * ``inline_bytes``. The response may pertain to only one certificate. + */ + 'ocsp_staple': (_envoy_config_core_v3_DataSource__Output | null); + /** + * [#not-implemented-hide:] + */ + 'signed_certificate_timestamp': (_envoy_config_core_v3_DataSource__Output)[]; + /** + * BoringSSL private key method provider. This is an alternative to :ref:`private_key + * ` field. This can't be + * marked as ``oneof`` due to API compatibility reasons. Setting both :ref:`private_key + * ` and + * :ref:`private_key_provider + * ` fields will result in an + * error. + */ + 'private_key_provider': (_envoy_extensions_transport_sockets_tls_v3_PrivateKeyProvider__Output | null); + /** + * If specified, updates of file-based *certificate_chain* and *private_key* + * sources will be triggered by this watch. The certificate/key pair will be + * read together and validated for atomic read consistency (i.e. no + * intervening modification occurred between cert/key read, verified by file + * hash comparisons). This allows explicit control over the path watched, by + * default the parent directories of the filesystem paths in + * *certificate_chain* and *private_key* are watched if this field is not + * specified. This only applies when a *TlsCertificate* is delivered by SDS + * with references to filesystem paths. See the :ref:`SDS key rotation + * ` documentation for further details. + */ + 'watched_directory': (_envoy_config_core_v3_WatchedDirectory__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsParameters.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsParameters.ts similarity index 57% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsParameters.ts rename to packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsParameters.ts index 29fe8f4c8..e68464c8b 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsParameters.ts +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsParameters.ts @@ -1,9 +1,9 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/common.proto +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto -// Original file: deps/envoy-api/envoy/api/v2/auth/common.proto +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto -export enum _envoy_api_v2_auth_TlsParameters_TlsProtocol { +export enum _envoy_extensions_transport_sockets_tls_v3_TlsParameters_TlsProtocol { /** * Envoy will choose the optimal TLS version. */ @@ -31,19 +31,21 @@ export interface TlsParameters { * Minimum TLS protocol version. By default, it's ``TLSv1_2`` for clients and ``TLSv1_0`` for * servers. */ - 'tls_minimum_protocol_version'?: (_envoy_api_v2_auth_TlsParameters_TlsProtocol | keyof typeof _envoy_api_v2_auth_TlsParameters_TlsProtocol); + 'tls_minimum_protocol_version'?: (_envoy_extensions_transport_sockets_tls_v3_TlsParameters_TlsProtocol | keyof typeof _envoy_extensions_transport_sockets_tls_v3_TlsParameters_TlsProtocol); /** - * Maximum TLS protocol version. By default, it's ``TLSv1_3`` for servers in non-FIPS builds, and - * ``TLSv1_2`` for clients and for servers using :ref:`BoringSSL FIPS `. + * Maximum TLS protocol version. By default, it's ``TLSv1_2`` for clients and ``TLSv1_3`` for + * servers. */ - 'tls_maximum_protocol_version'?: (_envoy_api_v2_auth_TlsParameters_TlsProtocol | keyof typeof _envoy_api_v2_auth_TlsParameters_TlsProtocol); + 'tls_maximum_protocol_version'?: (_envoy_extensions_transport_sockets_tls_v3_TlsParameters_TlsProtocol | keyof typeof _envoy_extensions_transport_sockets_tls_v3_TlsParameters_TlsProtocol); /** * If specified, the TLS listener will only support the specified `cipher list * `_ - * when negotiating TLS 1.0-1.2 (this setting has no effect when negotiating TLS 1.3). If not - * specified, the default list will be used. + * when negotiating TLS 1.0-1.2 (this setting has no effect when negotiating TLS 1.3). + * + * If not specified, a default list will be used. Defaults are different for server (downstream) and + * client (upstream) TLS configurations. * - * In non-FIPS builds, the default cipher list is: + * In non-FIPS builds, the default server cipher list is: * * .. code-block:: none * @@ -60,7 +62,7 @@ export interface TlsParameters { * AES256-GCM-SHA384 * AES256-SHA * - * In builds using :ref:`BoringSSL FIPS `, the default cipher list is: + * In builds using :ref:`BoringSSL FIPS `, the default server cipher list is: * * .. code-block:: none * @@ -76,6 +78,24 @@ export interface TlsParameters { * ECDHE-RSA-AES256-SHA * AES256-GCM-SHA384 * AES256-SHA + * + * In non-FIPS builds, the default client cipher list is: + * + * .. code-block:: none + * + * [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305] + * [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] + * ECDHE-ECDSA-AES256-GCM-SHA384 + * ECDHE-RSA-AES256-GCM-SHA384 + * + * In builds using :ref:`BoringSSL FIPS `, the default client cipher list is: + * + * .. code-block:: none + * + * ECDHE-ECDSA-AES128-GCM-SHA256 + * ECDHE-RSA-AES128-GCM-SHA256 + * ECDHE-ECDSA-AES256-GCM-SHA384 + * ECDHE-RSA-AES256-GCM-SHA384 */ 'cipher_suites'?: (string)[]; /** @@ -103,19 +123,21 @@ export interface TlsParameters__Output { * Minimum TLS protocol version. By default, it's ``TLSv1_2`` for clients and ``TLSv1_0`` for * servers. */ - 'tls_minimum_protocol_version': (keyof typeof _envoy_api_v2_auth_TlsParameters_TlsProtocol); + 'tls_minimum_protocol_version': (keyof typeof _envoy_extensions_transport_sockets_tls_v3_TlsParameters_TlsProtocol); /** - * Maximum TLS protocol version. By default, it's ``TLSv1_3`` for servers in non-FIPS builds, and - * ``TLSv1_2`` for clients and for servers using :ref:`BoringSSL FIPS `. + * Maximum TLS protocol version. By default, it's ``TLSv1_2`` for clients and ``TLSv1_3`` for + * servers. */ - 'tls_maximum_protocol_version': (keyof typeof _envoy_api_v2_auth_TlsParameters_TlsProtocol); + 'tls_maximum_protocol_version': (keyof typeof _envoy_extensions_transport_sockets_tls_v3_TlsParameters_TlsProtocol); /** * If specified, the TLS listener will only support the specified `cipher list * `_ - * when negotiating TLS 1.0-1.2 (this setting has no effect when negotiating TLS 1.3). If not - * specified, the default list will be used. + * when negotiating TLS 1.0-1.2 (this setting has no effect when negotiating TLS 1.3). + * + * If not specified, a default list will be used. Defaults are different for server (downstream) and + * client (upstream) TLS configurations. * - * In non-FIPS builds, the default cipher list is: + * In non-FIPS builds, the default server cipher list is: * * .. code-block:: none * @@ -132,7 +154,7 @@ export interface TlsParameters__Output { * AES256-GCM-SHA384 * AES256-SHA * - * In builds using :ref:`BoringSSL FIPS `, the default cipher list is: + * In builds using :ref:`BoringSSL FIPS `, the default server cipher list is: * * .. code-block:: none * @@ -148,6 +170,24 @@ export interface TlsParameters__Output { * ECDHE-RSA-AES256-SHA * AES256-GCM-SHA384 * AES256-SHA + * + * In non-FIPS builds, the default client cipher list is: + * + * .. code-block:: none + * + * [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305] + * [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] + * ECDHE-ECDSA-AES256-GCM-SHA384 + * ECDHE-RSA-AES256-GCM-SHA384 + * + * In builds using :ref:`BoringSSL FIPS `, the default client cipher list is: + * + * .. code-block:: none + * + * ECDHE-ECDSA-AES128-GCM-SHA256 + * ECDHE-RSA-AES128-GCM-SHA256 + * ECDHE-ECDSA-AES256-GCM-SHA384 + * ECDHE-RSA-AES256-GCM-SHA384 */ 'cipher_suites': (string)[]; /** diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsSessionTicketKeys.ts b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsSessionTicketKeys.ts similarity index 81% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsSessionTicketKeys.ts rename to packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsSessionTicketKeys.ts index d4bedd682..152bccac7 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/auth/TlsSessionTicketKeys.ts +++ b/packages/grpc-js-xds/src/generated/envoy/extensions/transport_sockets/tls/v3/TlsSessionTicketKeys.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/api/v2/auth/common.proto +// Original file: deps/envoy-api/envoy/extensions/transport_sockets/tls/v3/common.proto -import type { DataSource as _envoy_api_v2_core_DataSource, DataSource__Output as _envoy_api_v2_core_DataSource__Output } from '../../../../envoy/api/v2/core/DataSource'; +import type { DataSource as _envoy_config_core_v3_DataSource, DataSource__Output as _envoy_config_core_v3_DataSource__Output } from '../../../../../envoy/config/core/v3/DataSource'; export interface TlsSessionTicketKeys { /** @@ -9,7 +9,7 @@ export interface TlsSessionTicketKeys { * All keys are candidates for decrypting received tickets. This allows for easy rotation of keys * by, for example, putting the new key first, and the previous key second. * - * If :ref:`session_ticket_keys ` + * If :ref:`session_ticket_keys ` * is not specified, the TLS library will still support resuming sessions via tickets, but it will * use an internally-generated and managed key, so sessions cannot be resumed across hot restarts * or on different hosts. @@ -28,7 +28,7 @@ export interface TlsSessionTicketKeys { * * Rotate session ticket keys at least daily, and preferably hourly * * Always generate keys using a cryptographically-secure random data source */ - 'keys'?: (_envoy_api_v2_core_DataSource)[]; + 'keys'?: (_envoy_config_core_v3_DataSource)[]; } export interface TlsSessionTicketKeys__Output { @@ -38,7 +38,7 @@ export interface TlsSessionTicketKeys__Output { * All keys are candidates for decrypting received tickets. This allows for easy rotation of keys * by, for example, putting the new key first, and the previous key second. * - * If :ref:`session_ticket_keys ` + * If :ref:`session_ticket_keys ` * is not specified, the TLS library will still support resuming sessions via tickets, but it will * use an internally-generated and managed key, so sessions cannot be resumed across hot restarts * or on different hosts. @@ -57,5 +57,5 @@ export interface TlsSessionTicketKeys__Output { * * Rotate session ticket keys at least daily, and preferably hourly * * Always generate keys using a cryptographically-secure random data source */ - 'keys': (_envoy_api_v2_core_DataSource__Output)[]; + 'keys': (_envoy_config_core_v3_DataSource__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/service/discovery/v2/AggregatedDiscoveryService.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v2/AggregatedDiscoveryService.ts deleted file mode 100644 index ec7641dca..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/service/discovery/v2/AggregatedDiscoveryService.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Original file: deps/envoy-api/envoy/service/discovery/v2/ads.proto - -import type * as grpc from '@grpc/grpc-js' -import type { DeltaDiscoveryRequest as _envoy_api_v2_DeltaDiscoveryRequest, DeltaDiscoveryRequest__Output as _envoy_api_v2_DeltaDiscoveryRequest__Output } from '../../../../envoy/api/v2/DeltaDiscoveryRequest'; -import type { DeltaDiscoveryResponse as _envoy_api_v2_DeltaDiscoveryResponse, DeltaDiscoveryResponse__Output as _envoy_api_v2_DeltaDiscoveryResponse__Output } from '../../../../envoy/api/v2/DeltaDiscoveryResponse'; -import type { DiscoveryRequest as _envoy_api_v2_DiscoveryRequest, DiscoveryRequest__Output as _envoy_api_v2_DiscoveryRequest__Output } from '../../../../envoy/api/v2/DiscoveryRequest'; -import type { DiscoveryResponse as _envoy_api_v2_DiscoveryResponse, DiscoveryResponse__Output as _envoy_api_v2_DiscoveryResponse__Output } from '../../../../envoy/api/v2/DiscoveryResponse'; - -/** - * See https://github.com/lyft/envoy-api#apis for a description of the role of - * ADS and how it is intended to be used by a management server. ADS requests - * have the same structure as their singleton xDS counterparts, but can - * multiplex many resource types on a single stream. The type_url in the - * DiscoveryRequest/DiscoveryResponse provides sufficient information to recover - * the multiplexed singleton APIs at the Envoy instance and management server. - */ -export interface AggregatedDiscoveryServiceClient extends grpc.Client { - DeltaAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DeltaDiscoveryRequest, _envoy_api_v2_DeltaDiscoveryResponse__Output>; - DeltaAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DeltaDiscoveryRequest, _envoy_api_v2_DeltaDiscoveryResponse__Output>; - deltaAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DeltaDiscoveryRequest, _envoy_api_v2_DeltaDiscoveryResponse__Output>; - deltaAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DeltaDiscoveryRequest, _envoy_api_v2_DeltaDiscoveryResponse__Output>; - - /** - * This is a gRPC-only API. - */ - StreamAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DiscoveryRequest, _envoy_api_v2_DiscoveryResponse__Output>; - StreamAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DiscoveryRequest, _envoy_api_v2_DiscoveryResponse__Output>; - /** - * This is a gRPC-only API. - */ - streamAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DiscoveryRequest, _envoy_api_v2_DiscoveryResponse__Output>; - streamAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_api_v2_DiscoveryRequest, _envoy_api_v2_DiscoveryResponse__Output>; - -} - -/** - * See https://github.com/lyft/envoy-api#apis for a description of the role of - * ADS and how it is intended to be used by a management server. ADS requests - * have the same structure as their singleton xDS counterparts, but can - * multiplex many resource types on a single stream. The type_url in the - * DiscoveryRequest/DiscoveryResponse provides sufficient information to recover - * the multiplexed singleton APIs at the Envoy instance and management server. - */ -export interface AggregatedDiscoveryServiceHandlers extends grpc.UntypedServiceImplementation { - DeltaAggregatedResources: grpc.handleBidiStreamingCall<_envoy_api_v2_DeltaDiscoveryRequest__Output, _envoy_api_v2_DeltaDiscoveryResponse>; - - /** - * This is a gRPC-only API. - */ - StreamAggregatedResources: grpc.handleBidiStreamingCall<_envoy_api_v2_DiscoveryRequest__Output, _envoy_api_v2_DiscoveryResponse>; - -} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/discovery/v2/AdsDummy.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/AdsDummy.ts similarity index 86% rename from packages/grpc-js-xds/src/generated/envoy/service/discovery/v2/AdsDummy.ts rename to packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/AdsDummy.ts index eeb6aa6af..c15510877 100644 --- a/packages/grpc-js-xds/src/generated/envoy/service/discovery/v2/AdsDummy.ts +++ b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/AdsDummy.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/service/discovery/v2/ads.proto +// Original file: deps/envoy-api/envoy/service/discovery/v3/ads.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/AggregatedDiscoveryService.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/AggregatedDiscoveryService.ts new file mode 100644 index 000000000..e6498177b --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/AggregatedDiscoveryService.ts @@ -0,0 +1,58 @@ +// Original file: deps/envoy-api/envoy/service/discovery/v3/ads.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { DeltaDiscoveryRequest as _envoy_service_discovery_v3_DeltaDiscoveryRequest, DeltaDiscoveryRequest__Output as _envoy_service_discovery_v3_DeltaDiscoveryRequest__Output } from '../../../../envoy/service/discovery/v3/DeltaDiscoveryRequest'; +import type { DeltaDiscoveryResponse as _envoy_service_discovery_v3_DeltaDiscoveryResponse, DeltaDiscoveryResponse__Output as _envoy_service_discovery_v3_DeltaDiscoveryResponse__Output } from '../../../../envoy/service/discovery/v3/DeltaDiscoveryResponse'; +import type { DiscoveryRequest as _envoy_service_discovery_v3_DiscoveryRequest, DiscoveryRequest__Output as _envoy_service_discovery_v3_DiscoveryRequest__Output } from '../../../../envoy/service/discovery/v3/DiscoveryRequest'; +import type { DiscoveryResponse as _envoy_service_discovery_v3_DiscoveryResponse, DiscoveryResponse__Output as _envoy_service_discovery_v3_DiscoveryResponse__Output } from '../../../../envoy/service/discovery/v3/DiscoveryResponse'; + +/** + * See https://github.com/lyft/envoy-api#apis for a description of the role of + * ADS and how it is intended to be used by a management server. ADS requests + * have the same structure as their singleton xDS counterparts, but can + * multiplex many resource types on a single stream. The type_url in the + * DiscoveryRequest/DiscoveryResponse provides sufficient information to recover + * the multiplexed singleton APIs at the Envoy instance and management server. + */ +export interface AggregatedDiscoveryServiceClient extends grpc.Client { + DeltaAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DeltaDiscoveryRequest, _envoy_service_discovery_v3_DeltaDiscoveryResponse__Output>; + DeltaAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DeltaDiscoveryRequest, _envoy_service_discovery_v3_DeltaDiscoveryResponse__Output>; + deltaAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DeltaDiscoveryRequest, _envoy_service_discovery_v3_DeltaDiscoveryResponse__Output>; + deltaAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DeltaDiscoveryRequest, _envoy_service_discovery_v3_DeltaDiscoveryResponse__Output>; + + /** + * This is a gRPC-only API. + */ + StreamAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DiscoveryRequest, _envoy_service_discovery_v3_DiscoveryResponse__Output>; + StreamAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DiscoveryRequest, _envoy_service_discovery_v3_DiscoveryResponse__Output>; + /** + * This is a gRPC-only API. + */ + streamAggregatedResources(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DiscoveryRequest, _envoy_service_discovery_v3_DiscoveryResponse__Output>; + streamAggregatedResources(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_discovery_v3_DiscoveryRequest, _envoy_service_discovery_v3_DiscoveryResponse__Output>; + +} + +/** + * See https://github.com/lyft/envoy-api#apis for a description of the role of + * ADS and how it is intended to be used by a management server. ADS requests + * have the same structure as their singleton xDS counterparts, but can + * multiplex many resource types on a single stream. The type_url in the + * DiscoveryRequest/DiscoveryResponse provides sufficient information to recover + * the multiplexed singleton APIs at the Envoy instance and management server. + */ +export interface AggregatedDiscoveryServiceHandlers extends grpc.UntypedServiceImplementation { + DeltaAggregatedResources: grpc.handleBidiStreamingCall<_envoy_service_discovery_v3_DeltaDiscoveryRequest__Output, _envoy_service_discovery_v3_DeltaDiscoveryResponse>; + + /** + * This is a gRPC-only API. + */ + StreamAggregatedResources: grpc.handleBidiStreamingCall<_envoy_service_discovery_v3_DiscoveryRequest__Output, _envoy_service_discovery_v3_DiscoveryResponse>; + +} + +export interface AggregatedDiscoveryServiceDefinition extends grpc.ServiceDefinition { + DeltaAggregatedResources: MethodDefinition<_envoy_service_discovery_v3_DeltaDiscoveryRequest, _envoy_service_discovery_v3_DeltaDiscoveryResponse, _envoy_service_discovery_v3_DeltaDiscoveryRequest__Output, _envoy_service_discovery_v3_DeltaDiscoveryResponse__Output> + StreamAggregatedResources: MethodDefinition<_envoy_service_discovery_v3_DiscoveryRequest, _envoy_service_discovery_v3_DiscoveryResponse, _envoy_service_discovery_v3_DiscoveryRequest__Output, _envoy_service_discovery_v3_DiscoveryResponse__Output> +} diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/DeltaDiscoveryRequest.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DeltaDiscoveryRequest.ts similarity index 90% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/DeltaDiscoveryRequest.ts rename to packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DeltaDiscoveryRequest.ts index 11cbe8c2c..6e900970a 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/DeltaDiscoveryRequest.ts +++ b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DeltaDiscoveryRequest.ts @@ -1,7 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/discovery.proto +// Original file: deps/envoy-api/envoy/service/discovery/v3/discovery.proto -import type { Node as _envoy_api_v2_core_Node, Node__Output as _envoy_api_v2_core_Node__Output } from '../../../envoy/api/v2/core/Node'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; +import type { Node as _envoy_config_core_v3_Node, Node__Output as _envoy_config_core_v3_Node__Output } from '../../../../envoy/config/core/v3/Node'; +import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../../google/rpc/Status'; /** * DeltaDiscoveryRequest and DeltaDiscoveryResponse are used in a new gRPC @@ -42,10 +42,12 @@ export interface DeltaDiscoveryRequest { /** * The node making the request. */ - 'node'?: (_envoy_api_v2_core_Node); + 'node'?: (_envoy_config_core_v3_Node | null); /** * Type of the resource that is being requested, e.g. - * "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment". + * "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment". This does not need to be set if + * resources are only referenced via *xds_resource_subscribe* and + * *xds_resources_unsubscribe*. */ 'type_url'?: (string); /** @@ -95,11 +97,11 @@ export interface DeltaDiscoveryRequest { */ 'response_nonce'?: (string); /** - * This is populated when the previous :ref:`DiscoveryResponse ` + * This is populated when the previous :ref:`DiscoveryResponse ` * failed to update configuration. The *message* field in *error_details* * provides the Envoy internal exception related to the failure. */ - 'error_detail'?: (_google_rpc_Status); + 'error_detail'?: (_google_rpc_Status | null); } /** @@ -141,10 +143,12 @@ export interface DeltaDiscoveryRequest__Output { /** * The node making the request. */ - 'node'?: (_envoy_api_v2_core_Node__Output); + 'node': (_envoy_config_core_v3_Node__Output | null); /** * Type of the resource that is being requested, e.g. - * "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment". + * "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment". This does not need to be set if + * resources are only referenced via *xds_resource_subscribe* and + * *xds_resources_unsubscribe*. */ 'type_url': (string); /** @@ -194,9 +198,9 @@ export interface DeltaDiscoveryRequest__Output { */ 'response_nonce': (string); /** - * This is populated when the previous :ref:`DiscoveryResponse ` + * This is populated when the previous :ref:`DiscoveryResponse ` * failed to update configuration. The *message* field in *error_details* * provides the Envoy internal exception related to the failure. */ - 'error_detail'?: (_google_rpc_Status__Output); + 'error_detail': (_google_rpc_Status__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/DeltaDiscoveryResponse.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DeltaDiscoveryResponse.ts similarity index 64% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/DeltaDiscoveryResponse.ts rename to packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DeltaDiscoveryResponse.ts index 1a2584b95..efbbed85c 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/DeltaDiscoveryResponse.ts +++ b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DeltaDiscoveryResponse.ts @@ -1,9 +1,10 @@ -// Original file: deps/envoy-api/envoy/api/v2/discovery.proto +// Original file: deps/envoy-api/envoy/service/discovery/v3/discovery.proto -import type { Resource as _envoy_api_v2_Resource, Resource__Output as _envoy_api_v2_Resource__Output } from '../../../envoy/api/v2/Resource'; +import type { Resource as _envoy_service_discovery_v3_Resource, Resource__Output as _envoy_service_discovery_v3_Resource__Output } from '../../../../envoy/service/discovery/v3/Resource'; +import type { ControlPlane as _envoy_config_core_v3_ControlPlane, ControlPlane__Output as _envoy_config_core_v3_ControlPlane__Output } from '../../../../envoy/config/core/v3/ControlPlane'; /** - * [#next-free-field: 7] + * [#next-free-field: 8] */ export interface DeltaDiscoveryResponse { /** @@ -14,7 +15,7 @@ export interface DeltaDiscoveryResponse { * The response resources. These are typed resources, whose types must match * the type_url field. */ - 'resources'?: (_envoy_api_v2_Resource)[]; + 'resources'?: (_envoy_service_discovery_v3_Resource)[]; /** * Type URL for resources. Identifies the xDS API when muxing over ADS. * Must be consistent with the type_url in the Any within 'resources' if 'resources' is non-empty. @@ -30,10 +31,15 @@ export interface DeltaDiscoveryResponse { * Removed resources for missing resources can be ignored. */ 'removed_resources'?: (string)[]; + /** + * [#not-implemented-hide:] + * The control plane instance that sent the response. + */ + 'control_plane'?: (_envoy_config_core_v3_ControlPlane | null); } /** - * [#next-free-field: 7] + * [#next-free-field: 8] */ export interface DeltaDiscoveryResponse__Output { /** @@ -44,7 +50,7 @@ export interface DeltaDiscoveryResponse__Output { * The response resources. These are typed resources, whose types must match * the type_url field. */ - 'resources': (_envoy_api_v2_Resource__Output)[]; + 'resources': (_envoy_service_discovery_v3_Resource__Output)[]; /** * Type URL for resources. Identifies the xDS API when muxing over ADS. * Must be consistent with the type_url in the Any within 'resources' if 'resources' is non-empty. @@ -60,4 +66,9 @@ export interface DeltaDiscoveryResponse__Output { * Removed resources for missing resources can be ignored. */ 'removed_resources': (string)[]; + /** + * [#not-implemented-hide:] + * The control plane instance that sent the response. + */ + 'control_plane': (_envoy_config_core_v3_ControlPlane__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/DiscoveryRequest.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DiscoveryRequest.ts similarity index 88% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/DiscoveryRequest.ts rename to packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DiscoveryRequest.ts index 2150c41bc..f392ab8ae 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/DiscoveryRequest.ts +++ b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DiscoveryRequest.ts @@ -1,7 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/discovery.proto +// Original file: deps/envoy-api/envoy/service/discovery/v3/discovery.proto -import type { Node as _envoy_api_v2_core_Node, Node__Output as _envoy_api_v2_core_Node__Output } from '../../../envoy/api/v2/core/Node'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; +import type { Node as _envoy_config_core_v3_Node, Node__Output as _envoy_config_core_v3_Node__Output } from '../../../../envoy/config/core/v3/Node'; +import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../../google/rpc/Status'; /** * A DiscoveryRequest requests a set of versioned resources of the same type for @@ -22,7 +22,7 @@ export interface DiscoveryRequest { /** * The node making the request. */ - 'node'?: (_envoy_api_v2_core_Node); + 'node'?: (_envoy_config_core_v3_Node | null); /** * List of resources to subscribe to, e.g. list of cluster names or a route * configuration name. If this is empty, all resources for the API are @@ -48,12 +48,12 @@ export interface DiscoveryRequest { */ 'response_nonce'?: (string); /** - * This is populated when the previous :ref:`DiscoveryResponse ` + * This is populated when the previous :ref:`DiscoveryResponse ` * failed to update configuration. The *message* field in *error_details* provides the Envoy * internal exception related to the failure. It is only intended for consumption during manual * debugging, the string provided is not guaranteed to be stable across Envoy versions. */ - 'error_detail'?: (_google_rpc_Status); + 'error_detail'?: (_google_rpc_Status | null); } /** @@ -75,7 +75,7 @@ export interface DiscoveryRequest__Output { /** * The node making the request. */ - 'node'?: (_envoy_api_v2_core_Node__Output); + 'node': (_envoy_config_core_v3_Node__Output | null); /** * List of resources to subscribe to, e.g. list of cluster names or a route * configuration name. If this is empty, all resources for the API are @@ -101,10 +101,10 @@ export interface DiscoveryRequest__Output { */ 'response_nonce': (string); /** - * This is populated when the previous :ref:`DiscoveryResponse ` + * This is populated when the previous :ref:`DiscoveryResponse ` * failed to update configuration. The *message* field in *error_details* provides the Envoy * internal exception related to the failure. It is only intended for consumption during manual * debugging, the string provided is not guaranteed to be stable across Envoy versions. */ - 'error_detail'?: (_google_rpc_Status__Output); + 'error_detail': (_google_rpc_Status__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/api/v2/DiscoveryResponse.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DiscoveryResponse.ts similarity index 89% rename from packages/grpc-js-xds/src/generated/envoy/api/v2/DiscoveryResponse.ts rename to packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DiscoveryResponse.ts index dd7e70d4d..874168317 100644 --- a/packages/grpc-js-xds/src/generated/envoy/api/v2/DiscoveryResponse.ts +++ b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/DiscoveryResponse.ts @@ -1,7 +1,7 @@ -// Original file: deps/envoy-api/envoy/api/v2/discovery.proto +// Original file: deps/envoy-api/envoy/service/discovery/v3/discovery.proto -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; -import type { ControlPlane as _envoy_api_v2_core_ControlPlane, ControlPlane__Output as _envoy_api_v2_core_ControlPlane__Output } from '../../../envoy/api/v2/core/ControlPlane'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { ControlPlane as _envoy_config_core_v3_ControlPlane, ControlPlane__Output as _envoy_config_core_v3_ControlPlane__Output } from '../../../../envoy/config/core/v3/ControlPlane'; /** * [#next-free-field: 7] @@ -49,10 +49,9 @@ export interface DiscoveryResponse { */ 'nonce'?: (string); /** - * [#not-implemented-hide:] * The control plane instance that sent the response. */ - 'control_plane'?: (_envoy_api_v2_core_ControlPlane); + 'control_plane'?: (_envoy_config_core_v3_ControlPlane | null); } /** @@ -101,8 +100,7 @@ export interface DiscoveryResponse__Output { */ 'nonce': (string); /** - * [#not-implemented-hide:] * The control plane instance that sent the response. */ - 'control_plane'?: (_envoy_api_v2_core_ControlPlane__Output); + 'control_plane': (_envoy_config_core_v3_ControlPlane__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/Resource.ts b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/Resource.ts new file mode 100644 index 000000000..0e5897ab4 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/discovery/v3/Resource.ts @@ -0,0 +1,118 @@ +// Original file: deps/envoy-api/envoy/service/discovery/v3/discovery.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; + +/** + * Cache control properties for the resource. + * [#not-implemented-hide:] + */ +export interface _envoy_service_discovery_v3_Resource_CacheControl { + /** + * If true, xDS proxies may not cache this resource. + * Note that this does not apply to clients other than xDS proxies, which must cache resources + * for their own use, regardless of the value of this field. + */ + 'do_not_cache'?: (boolean); +} + +/** + * Cache control properties for the resource. + * [#not-implemented-hide:] + */ +export interface _envoy_service_discovery_v3_Resource_CacheControl__Output { + /** + * If true, xDS proxies may not cache this resource. + * Note that this does not apply to clients other than xDS proxies, which must cache resources + * for their own use, regardless of the value of this field. + */ + 'do_not_cache': (boolean); +} + +/** + * [#next-free-field: 8] + */ +export interface Resource { + /** + * The resource level version. It allows xDS to track the state of individual + * resources. + */ + 'version'?: (string); + /** + * The resource being tracked. + */ + 'resource'?: (_google_protobuf_Any | null); + /** + * The resource's name, to distinguish it from others of the same type of resource. + */ + 'name'?: (string); + /** + * The aliases are a list of other names that this resource can go by. + */ + 'aliases'?: (string)[]; + /** + * Time-to-live value for the resource. For each resource, a timer is started. The timer is + * reset each time the resource is received with a new TTL. If the resource is received with + * no TTL set, the timer is removed for the resource. Upon expiration of the timer, the + * configuration for the resource will be removed. + * + * The TTL can be refreshed or changed by sending a response that doesn't change the resource + * version. In this case the resource field does not need to be populated, which allows for + * light-weight "heartbeat" updates to keep a resource with a TTL alive. + * + * The TTL feature is meant to support configurations that should be removed in the event of + * a management server failure. For example, the feature may be used for fault injection + * testing where the fault injection should be terminated in the event that Envoy loses contact + * with the management server. + */ + 'ttl'?: (_google_protobuf_Duration | null); + /** + * Cache control properties for the resource. + * [#not-implemented-hide:] + */ + 'cache_control'?: (_envoy_service_discovery_v3_Resource_CacheControl | null); +} + +/** + * [#next-free-field: 8] + */ +export interface Resource__Output { + /** + * The resource level version. It allows xDS to track the state of individual + * resources. + */ + 'version': (string); + /** + * The resource being tracked. + */ + 'resource': (_google_protobuf_Any__Output | null); + /** + * The resource's name, to distinguish it from others of the same type of resource. + */ + 'name': (string); + /** + * The aliases are a list of other names that this resource can go by. + */ + 'aliases': (string)[]; + /** + * Time-to-live value for the resource. For each resource, a timer is started. The timer is + * reset each time the resource is received with a new TTL. If the resource is received with + * no TTL set, the timer is removed for the resource. Upon expiration of the timer, the + * configuration for the resource will be removed. + * + * The TTL can be refreshed or changed by sending a response that doesn't change the resource + * version. In this case the resource field does not need to be populated, which allows for + * light-weight "heartbeat" updates to keep a resource with a TTL alive. + * + * The TTL feature is meant to support configurations that should be removed in the event of + * a management server failure. For example, the feature may be used for fault injection + * testing where the fault injection should be terminated in the event that Envoy loses contact + * with the management server. + */ + 'ttl': (_google_protobuf_Duration__Output | null); + /** + * Cache control properties for the resource. + * [#not-implemented-hide:] + */ + 'cache_control': (_envoy_service_discovery_v3_Resource_CacheControl__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadStatsRequest.ts b/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadStatsRequest.ts deleted file mode 100644 index a7ac6b8e1..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadStatsRequest.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Original file: deps/envoy-api/envoy/service/load_stats/v2/lrs.proto - -import type { Node as _envoy_api_v2_core_Node, Node__Output as _envoy_api_v2_core_Node__Output } from '../../../../envoy/api/v2/core/Node'; -import type { ClusterStats as _envoy_api_v2_endpoint_ClusterStats, ClusterStats__Output as _envoy_api_v2_endpoint_ClusterStats__Output } from '../../../../envoy/api/v2/endpoint/ClusterStats'; - -/** - * A load report Envoy sends to the management server. - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. - */ -export interface LoadStatsRequest { - /** - * Node identifier for Envoy instance. - */ - 'node'?: (_envoy_api_v2_core_Node); - /** - * A list of load stats to report. - */ - 'cluster_stats'?: (_envoy_api_v2_endpoint_ClusterStats)[]; -} - -/** - * A load report Envoy sends to the management server. - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. - */ -export interface LoadStatsRequest__Output { - /** - * Node identifier for Envoy instance. - */ - 'node'?: (_envoy_api_v2_core_Node__Output); - /** - * A list of load stats to report. - */ - 'cluster_stats': (_envoy_api_v2_endpoint_ClusterStats__Output)[]; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadReportingService.ts b/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadReportingService.ts similarity index 81% rename from packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadReportingService.ts rename to packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadReportingService.ts index 41e73f0e9..32aa4f96e 100644 --- a/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadReportingService.ts +++ b/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadReportingService.ts @@ -1,8 +1,9 @@ -// Original file: deps/envoy-api/envoy/service/load_stats/v2/lrs.proto +// Original file: deps/envoy-api/envoy/service/load_stats/v3/lrs.proto import type * as grpc from '@grpc/grpc-js' -import type { LoadStatsRequest as _envoy_service_load_stats_v2_LoadStatsRequest, LoadStatsRequest__Output as _envoy_service_load_stats_v2_LoadStatsRequest__Output } from '../../../../envoy/service/load_stats/v2/LoadStatsRequest'; -import type { LoadStatsResponse as _envoy_service_load_stats_v2_LoadStatsResponse, LoadStatsResponse__Output as _envoy_service_load_stats_v2_LoadStatsResponse__Output } from '../../../../envoy/service/load_stats/v2/LoadStatsResponse'; +import type { MethodDefinition } from '@grpc/proto-loader' +import type { LoadStatsRequest as _envoy_service_load_stats_v3_LoadStatsRequest, LoadStatsRequest__Output as _envoy_service_load_stats_v3_LoadStatsRequest__Output } from '../../../../envoy/service/load_stats/v3/LoadStatsRequest'; +import type { LoadStatsResponse as _envoy_service_load_stats_v3_LoadStatsResponse, LoadStatsResponse__Output as _envoy_service_load_stats_v3_LoadStatsResponse__Output } from '../../../../envoy/service/load_stats/v3/LoadStatsResponse'; export interface LoadReportingServiceClient extends grpc.Client { /** @@ -35,8 +36,8 @@ export interface LoadReportingServiceClient extends grpc.Client { * from around the world, computes global assignment and prepares traffic * assignment destined for each zone Envoys are located in. Goto 2. */ - StreamLoadStats(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v2_LoadStatsRequest, _envoy_service_load_stats_v2_LoadStatsResponse__Output>; - StreamLoadStats(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v2_LoadStatsRequest, _envoy_service_load_stats_v2_LoadStatsResponse__Output>; + StreamLoadStats(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v3_LoadStatsRequest, _envoy_service_load_stats_v3_LoadStatsResponse__Output>; + StreamLoadStats(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v3_LoadStatsRequest, _envoy_service_load_stats_v3_LoadStatsResponse__Output>; /** * Advanced API to allow for multi-dimensional load balancing by remote * server. For receiving LB assignments, the steps are: @@ -67,8 +68,8 @@ export interface LoadReportingServiceClient extends grpc.Client { * from around the world, computes global assignment and prepares traffic * assignment destined for each zone Envoys are located in. Goto 2. */ - streamLoadStats(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v2_LoadStatsRequest, _envoy_service_load_stats_v2_LoadStatsResponse__Output>; - streamLoadStats(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v2_LoadStatsRequest, _envoy_service_load_stats_v2_LoadStatsResponse__Output>; + streamLoadStats(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v3_LoadStatsRequest, _envoy_service_load_stats_v3_LoadStatsResponse__Output>; + streamLoadStats(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_load_stats_v3_LoadStatsRequest, _envoy_service_load_stats_v3_LoadStatsResponse__Output>; } @@ -103,6 +104,10 @@ export interface LoadReportingServiceHandlers extends grpc.UntypedServiceImpleme * from around the world, computes global assignment and prepares traffic * assignment destined for each zone Envoys are located in. Goto 2. */ - StreamLoadStats: grpc.handleBidiStreamingCall<_envoy_service_load_stats_v2_LoadStatsRequest__Output, _envoy_service_load_stats_v2_LoadStatsResponse>; + StreamLoadStats: grpc.handleBidiStreamingCall<_envoy_service_load_stats_v3_LoadStatsRequest__Output, _envoy_service_load_stats_v3_LoadStatsResponse>; } + +export interface LoadReportingServiceDefinition extends grpc.ServiceDefinition { + StreamLoadStats: MethodDefinition<_envoy_service_load_stats_v3_LoadStatsRequest, _envoy_service_load_stats_v3_LoadStatsResponse, _envoy_service_load_stats_v3_LoadStatsRequest__Output, _envoy_service_load_stats_v3_LoadStatsResponse__Output> +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadStatsRequest.ts b/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadStatsRequest.ts new file mode 100644 index 000000000..e430eb270 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadStatsRequest.ts @@ -0,0 +1,32 @@ +// Original file: deps/envoy-api/envoy/service/load_stats/v3/lrs.proto + +import type { Node as _envoy_config_core_v3_Node, Node__Output as _envoy_config_core_v3_Node__Output } from '../../../../envoy/config/core/v3/Node'; +import type { ClusterStats as _envoy_config_endpoint_v3_ClusterStats, ClusterStats__Output as _envoy_config_endpoint_v3_ClusterStats__Output } from '../../../../envoy/config/endpoint/v3/ClusterStats'; + +/** + * A load report Envoy sends to the management server. + */ +export interface LoadStatsRequest { + /** + * Node identifier for Envoy instance. + */ + 'node'?: (_envoy_config_core_v3_Node | null); + /** + * A list of load stats to report. + */ + 'cluster_stats'?: (_envoy_config_endpoint_v3_ClusterStats)[]; +} + +/** + * A load report Envoy sends to the management server. + */ +export interface LoadStatsRequest__Output { + /** + * Node identifier for Envoy instance. + */ + 'node': (_envoy_config_core_v3_Node__Output | null); + /** + * A list of load stats to report. + */ + 'cluster_stats': (_envoy_config_endpoint_v3_ClusterStats__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadStatsResponse.ts b/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadStatsResponse.ts similarity index 83% rename from packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadStatsResponse.ts rename to packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadStatsResponse.ts index afec8f180..40f561870 100644 --- a/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v2/LoadStatsResponse.ts +++ b/packages/grpc-js-xds/src/generated/envoy/service/load_stats/v3/LoadStatsResponse.ts @@ -1,11 +1,10 @@ -// Original file: deps/envoy-api/envoy/service/load_stats/v2/lrs.proto +// Original file: deps/envoy-api/envoy/service/load_stats/v3/lrs.proto import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../../google/protobuf/Duration'; /** * The management server sends envoy a LoadStatsResponse with all clusters it * is interested in learning load stats about. - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. */ export interface LoadStatsResponse { /** @@ -15,6 +14,7 @@ export interface LoadStatsResponse { 'clusters'?: (string)[]; /** * The minimum interval of time to collect stats over. This is only a minimum for two reasons: + * * 1. There may be some delay from when the timer fires until stats sampling occurs. * 2. For clusters that were already feature in the previous *LoadStatsResponse*, any traffic * that is observed in between the corresponding previous *LoadStatsRequest* and this @@ -22,7 +22,7 @@ export interface LoadStatsResponse { * of inobservability that might otherwise exists between the messages. New clusters are not * subject to this consideration. */ - 'load_reporting_interval'?: (_google_protobuf_Duration); + 'load_reporting_interval'?: (_google_protobuf_Duration | null); /** * Set to *true* if the management server supports endpoint granularity * report. @@ -31,7 +31,7 @@ export interface LoadStatsResponse { /** * If true, the client should send all clusters it knows about. * Only clients that advertise the "envoy.lrs.supports_send_all_clusters" capability in their - * :ref:`client_features` field will honor this field. + * :ref:`client_features` field will honor this field. */ 'send_all_clusters'?: (boolean); } @@ -39,7 +39,6 @@ export interface LoadStatsResponse { /** * The management server sends envoy a LoadStatsResponse with all clusters it * is interested in learning load stats about. - * [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs. */ export interface LoadStatsResponse__Output { /** @@ -49,6 +48,7 @@ export interface LoadStatsResponse__Output { 'clusters': (string)[]; /** * The minimum interval of time to collect stats over. This is only a minimum for two reasons: + * * 1. There may be some delay from when the timer fires until stats sampling occurs. * 2. For clusters that were already feature in the previous *LoadStatsResponse*, any traffic * that is observed in between the corresponding previous *LoadStatsRequest* and this @@ -56,7 +56,7 @@ export interface LoadStatsResponse__Output { * of inobservability that might otherwise exists between the messages. New clusters are not * subject to this consideration. */ - 'load_reporting_interval'?: (_google_protobuf_Duration__Output); + 'load_reporting_interval': (_google_protobuf_Duration__Output | null); /** * Set to *true* if the management server supports endpoint granularity * report. @@ -65,7 +65,7 @@ export interface LoadStatsResponse__Output { /** * If true, the client should send all clusters it knows about. * Only clients that advertise the "envoy.lrs.supports_send_all_clusters" capability in their - * :ref:`client_features` field will honor this field. + * :ref:`client_features` field will honor this field. */ 'send_all_clusters': (boolean); } diff --git a/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientConfig.ts b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientConfig.ts new file mode 100644 index 000000000..ba6b25b4c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientConfig.ts @@ -0,0 +1,159 @@ +// Original file: deps/envoy-api/envoy/service/status/v3/csds.proto + +import type { Node as _envoy_config_core_v3_Node, Node__Output as _envoy_config_core_v3_Node__Output } from '../../../../envoy/config/core/v3/Node'; +import type { PerXdsConfig as _envoy_service_status_v3_PerXdsConfig, PerXdsConfig__Output as _envoy_service_status_v3_PerXdsConfig__Output } from '../../../../envoy/service/status/v3/PerXdsConfig'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../../google/protobuf/Any'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../../google/protobuf/Timestamp'; +import type { ConfigStatus as _envoy_service_status_v3_ConfigStatus } from '../../../../envoy/service/status/v3/ConfigStatus'; +import type { ClientResourceStatus as _envoy_admin_v3_ClientResourceStatus } from '../../../../envoy/admin/v3/ClientResourceStatus'; +import type { UpdateFailureState as _envoy_admin_v3_UpdateFailureState, UpdateFailureState__Output as _envoy_admin_v3_UpdateFailureState__Output } from '../../../../envoy/admin/v3/UpdateFailureState'; + +/** + * GenericXdsConfig is used to specify the config status and the dump + * of any xDS resource identified by their type URL. It is the generalized + * version of the now deprecated ListenersConfigDump, ClustersConfigDump etc + * [#next-free-field: 10] + */ +export interface _envoy_service_status_v3_ClientConfig_GenericXdsConfig { + /** + * Type_url represents the fully qualified name of xDS resource type + * like envoy.v3.Cluster, envoy.v3.ClusterLoadAssignment etc. + */ + 'type_url'?: (string); + /** + * Name of the xDS resource + */ + 'name'?: (string); + /** + * This is the :ref:`version_info ` + * in the last processed xDS discovery response. If there are only + * static bootstrap listeners, this field will be "" + */ + 'version_info'?: (string); + /** + * The xDS resource config. Actual content depends on the type + */ + 'xds_config'?: (_google_protobuf_Any | null); + /** + * Timestamp when the xDS resource was last updated + */ + 'last_updated'?: (_google_protobuf_Timestamp | null); + /** + * Per xDS resource config status. It is generated by management servers. + * It will not be present if the CSDS server is an xDS client. + */ + 'config_status'?: (_envoy_service_status_v3_ConfigStatus | keyof typeof _envoy_service_status_v3_ConfigStatus); + /** + * Per xDS resource status from the view of a xDS client + */ + 'client_status'?: (_envoy_admin_v3_ClientResourceStatus | keyof typeof _envoy_admin_v3_ClientResourceStatus); + /** + * Set if the last update failed, cleared after the next successful + * update. The *error_state* field contains the rejected version of + * this particular resource along with the reason and timestamp. For + * successfully updated or acknowledged resource, this field should + * be empty. + * [#not-implemented-hide:] + */ + 'error_state'?: (_envoy_admin_v3_UpdateFailureState | null); + /** + * Is static resource is true if it is specified in the config supplied + * through the file at the startup. + */ + 'is_static_resource'?: (boolean); +} + +/** + * GenericXdsConfig is used to specify the config status and the dump + * of any xDS resource identified by their type URL. It is the generalized + * version of the now deprecated ListenersConfigDump, ClustersConfigDump etc + * [#next-free-field: 10] + */ +export interface _envoy_service_status_v3_ClientConfig_GenericXdsConfig__Output { + /** + * Type_url represents the fully qualified name of xDS resource type + * like envoy.v3.Cluster, envoy.v3.ClusterLoadAssignment etc. + */ + 'type_url': (string); + /** + * Name of the xDS resource + */ + 'name': (string); + /** + * This is the :ref:`version_info ` + * in the last processed xDS discovery response. If there are only + * static bootstrap listeners, this field will be "" + */ + 'version_info': (string); + /** + * The xDS resource config. Actual content depends on the type + */ + 'xds_config': (_google_protobuf_Any__Output | null); + /** + * Timestamp when the xDS resource was last updated + */ + 'last_updated': (_google_protobuf_Timestamp__Output | null); + /** + * Per xDS resource config status. It is generated by management servers. + * It will not be present if the CSDS server is an xDS client. + */ + 'config_status': (keyof typeof _envoy_service_status_v3_ConfigStatus); + /** + * Per xDS resource status from the view of a xDS client + */ + 'client_status': (keyof typeof _envoy_admin_v3_ClientResourceStatus); + /** + * Set if the last update failed, cleared after the next successful + * update. The *error_state* field contains the rejected version of + * this particular resource along with the reason and timestamp. For + * successfully updated or acknowledged resource, this field should + * be empty. + * [#not-implemented-hide:] + */ + 'error_state': (_envoy_admin_v3_UpdateFailureState__Output | null); + /** + * Is static resource is true if it is specified in the config supplied + * through the file at the startup. + */ + 'is_static_resource': (boolean); +} + +/** + * All xds configs for a particular client. + */ +export interface ClientConfig { + /** + * Node for a particular client. + */ + 'node'?: (_envoy_config_core_v3_Node | null); + /** + * This field is deprecated in favor of generic_xds_configs which is + * much simpler and uniform in structure. + */ + 'xds_config'?: (_envoy_service_status_v3_PerXdsConfig)[]; + /** + * Represents generic xDS config and the exact config structure depends on + * the type URL (like Cluster if it is CDS) + */ + 'generic_xds_configs'?: (_envoy_service_status_v3_ClientConfig_GenericXdsConfig)[]; +} + +/** + * All xds configs for a particular client. + */ +export interface ClientConfig__Output { + /** + * Node for a particular client. + */ + 'node': (_envoy_config_core_v3_Node__Output | null); + /** + * This field is deprecated in favor of generic_xds_configs which is + * much simpler and uniform in structure. + */ + 'xds_config': (_envoy_service_status_v3_PerXdsConfig__Output)[]; + /** + * Represents generic xDS config and the exact config structure depends on + * the type URL (like Cluster if it is CDS) + */ + 'generic_xds_configs': (_envoy_service_status_v3_ClientConfig_GenericXdsConfig__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientConfigStatus.ts b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientConfigStatus.ts new file mode 100644 index 000000000..104445a3f --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientConfigStatus.ts @@ -0,0 +1,26 @@ +// Original file: deps/envoy-api/envoy/service/status/v3/csds.proto + +/** + * Config status from a client-side view. + */ +export enum ClientConfigStatus { + /** + * Config status is not available/unknown. + */ + CLIENT_UNKNOWN = 0, + /** + * Client requested the config but hasn't received any config from management + * server yet. + */ + CLIENT_REQUESTED = 1, + /** + * Client received the config and replied with ACK. + */ + CLIENT_ACKED = 2, + /** + * Client received the config and replied with NACK. Notably, the attached + * config dump is not the NACKed version, but the most recent accepted one. If + * no config is accepted yet, the attached config dump will be empty. + */ + CLIENT_NACKED = 3, +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusDiscoveryService.ts b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusDiscoveryService.ts new file mode 100644 index 000000000..7402fb69b --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusDiscoveryService.ts @@ -0,0 +1,45 @@ +// Original file: deps/envoy-api/envoy/service/status/v3/csds.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { ClientStatusRequest as _envoy_service_status_v3_ClientStatusRequest, ClientStatusRequest__Output as _envoy_service_status_v3_ClientStatusRequest__Output } from '../../../../envoy/service/status/v3/ClientStatusRequest'; +import type { ClientStatusResponse as _envoy_service_status_v3_ClientStatusResponse, ClientStatusResponse__Output as _envoy_service_status_v3_ClientStatusResponse__Output } from '../../../../envoy/service/status/v3/ClientStatusResponse'; + +/** + * CSDS is Client Status Discovery Service. It can be used to get the status of + * an xDS-compliant client from the management server's point of view. It can + * also be used to get the current xDS states directly from the client. + */ +export interface ClientStatusDiscoveryServiceClient extends grpc.Client { + FetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + FetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + FetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + FetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + fetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + fetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + fetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + fetchClientStatus(argument: _envoy_service_status_v3_ClientStatusRequest, callback: grpc.requestCallback<_envoy_service_status_v3_ClientStatusResponse__Output>): grpc.ClientUnaryCall; + + StreamClientStatus(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_status_v3_ClientStatusRequest, _envoy_service_status_v3_ClientStatusResponse__Output>; + StreamClientStatus(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_status_v3_ClientStatusRequest, _envoy_service_status_v3_ClientStatusResponse__Output>; + streamClientStatus(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_status_v3_ClientStatusRequest, _envoy_service_status_v3_ClientStatusResponse__Output>; + streamClientStatus(options?: grpc.CallOptions): grpc.ClientDuplexStream<_envoy_service_status_v3_ClientStatusRequest, _envoy_service_status_v3_ClientStatusResponse__Output>; + +} + +/** + * CSDS is Client Status Discovery Service. It can be used to get the status of + * an xDS-compliant client from the management server's point of view. It can + * also be used to get the current xDS states directly from the client. + */ +export interface ClientStatusDiscoveryServiceHandlers extends grpc.UntypedServiceImplementation { + FetchClientStatus: grpc.handleUnaryCall<_envoy_service_status_v3_ClientStatusRequest__Output, _envoy_service_status_v3_ClientStatusResponse>; + + StreamClientStatus: grpc.handleBidiStreamingCall<_envoy_service_status_v3_ClientStatusRequest__Output, _envoy_service_status_v3_ClientStatusResponse>; + +} + +export interface ClientStatusDiscoveryServiceDefinition extends grpc.ServiceDefinition { + FetchClientStatus: MethodDefinition<_envoy_service_status_v3_ClientStatusRequest, _envoy_service_status_v3_ClientStatusResponse, _envoy_service_status_v3_ClientStatusRequest__Output, _envoy_service_status_v3_ClientStatusResponse__Output> + StreamClientStatus: MethodDefinition<_envoy_service_status_v3_ClientStatusRequest, _envoy_service_status_v3_ClientStatusResponse, _envoy_service_status_v3_ClientStatusRequest__Output, _envoy_service_status_v3_ClientStatusResponse__Output> +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusRequest.ts b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusRequest.ts new file mode 100644 index 000000000..91adddacc --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusRequest.ts @@ -0,0 +1,34 @@ +// Original file: deps/envoy-api/envoy/service/status/v3/csds.proto + +import type { NodeMatcher as _envoy_type_matcher_v3_NodeMatcher, NodeMatcher__Output as _envoy_type_matcher_v3_NodeMatcher__Output } from '../../../../envoy/type/matcher/v3/NodeMatcher'; +import type { Node as _envoy_config_core_v3_Node, Node__Output as _envoy_config_core_v3_Node__Output } from '../../../../envoy/config/core/v3/Node'; + +/** + * Request for client status of clients identified by a list of NodeMatchers. + */ +export interface ClientStatusRequest { + /** + * Management server can use these match criteria to identify clients. + * The match follows OR semantics. + */ + 'node_matchers'?: (_envoy_type_matcher_v3_NodeMatcher)[]; + /** + * The node making the csds request. + */ + 'node'?: (_envoy_config_core_v3_Node | null); +} + +/** + * Request for client status of clients identified by a list of NodeMatchers. + */ +export interface ClientStatusRequest__Output { + /** + * Management server can use these match criteria to identify clients. + * The match follows OR semantics. + */ + 'node_matchers': (_envoy_type_matcher_v3_NodeMatcher__Output)[]; + /** + * The node making the csds request. + */ + 'node': (_envoy_config_core_v3_Node__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusResponse.ts b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusResponse.ts new file mode 100644 index 000000000..3611016ec --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ClientStatusResponse.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/service/status/v3/csds.proto + +import type { ClientConfig as _envoy_service_status_v3_ClientConfig, ClientConfig__Output as _envoy_service_status_v3_ClientConfig__Output } from '../../../../envoy/service/status/v3/ClientConfig'; + +export interface ClientStatusResponse { + /** + * Client configs for the clients specified in the ClientStatusRequest. + */ + 'config'?: (_envoy_service_status_v3_ClientConfig)[]; +} + +export interface ClientStatusResponse__Output { + /** + * Client configs for the clients specified in the ClientStatusRequest. + */ + 'config': (_envoy_service_status_v3_ClientConfig__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ConfigStatus.ts b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ConfigStatus.ts new file mode 100644 index 000000000..71db302c3 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/ConfigStatus.ts @@ -0,0 +1,30 @@ +// Original file: deps/envoy-api/envoy/service/status/v3/csds.proto + +/** + * Status of a config from a management server view. + */ +export enum ConfigStatus { + /** + * Status info is not available/unknown. + */ + UNKNOWN = 0, + /** + * Management server has sent the config to client and received ACK. + */ + SYNCED = 1, + /** + * Config is not sent. + */ + NOT_SENT = 2, + /** + * Management server has sent the config to client but hasn’t received + * ACK/NACK. + */ + STALE = 3, + /** + * Management server has sent the config to client but received NACK. The + * attached config dump will be the latest config (the rejected one), since + * it is the persisted version in the management server. + */ + ERROR = 4, +} diff --git a/packages/grpc-js-xds/src/generated/envoy/service/status/v3/PerXdsConfig.ts b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/PerXdsConfig.ts new file mode 100644 index 000000000..947f1c81a --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/service/status/v3/PerXdsConfig.ts @@ -0,0 +1,67 @@ +// Original file: deps/envoy-api/envoy/service/status/v3/csds.proto + +import type { ConfigStatus as _envoy_service_status_v3_ConfigStatus } from '../../../../envoy/service/status/v3/ConfigStatus'; +import type { ListenersConfigDump as _envoy_admin_v3_ListenersConfigDump, ListenersConfigDump__Output as _envoy_admin_v3_ListenersConfigDump__Output } from '../../../../envoy/admin/v3/ListenersConfigDump'; +import type { ClustersConfigDump as _envoy_admin_v3_ClustersConfigDump, ClustersConfigDump__Output as _envoy_admin_v3_ClustersConfigDump__Output } from '../../../../envoy/admin/v3/ClustersConfigDump'; +import type { RoutesConfigDump as _envoy_admin_v3_RoutesConfigDump, RoutesConfigDump__Output as _envoy_admin_v3_RoutesConfigDump__Output } from '../../../../envoy/admin/v3/RoutesConfigDump'; +import type { ScopedRoutesConfigDump as _envoy_admin_v3_ScopedRoutesConfigDump, ScopedRoutesConfigDump__Output as _envoy_admin_v3_ScopedRoutesConfigDump__Output } from '../../../../envoy/admin/v3/ScopedRoutesConfigDump'; +import type { EndpointsConfigDump as _envoy_admin_v3_EndpointsConfigDump, EndpointsConfigDump__Output as _envoy_admin_v3_EndpointsConfigDump__Output } from '../../../../envoy/admin/v3/EndpointsConfigDump'; +import type { ClientConfigStatus as _envoy_service_status_v3_ClientConfigStatus } from '../../../../envoy/service/status/v3/ClientConfigStatus'; + +/** + * Detailed config (per xDS) with status. + * [#next-free-field: 8] + */ +export interface PerXdsConfig { + /** + * Config status generated by management servers. Will not be present if the + * CSDS server is an xDS client. + */ + 'status'?: (_envoy_service_status_v3_ConfigStatus | keyof typeof _envoy_service_status_v3_ConfigStatus); + 'listener_config'?: (_envoy_admin_v3_ListenersConfigDump | null); + 'cluster_config'?: (_envoy_admin_v3_ClustersConfigDump | null); + 'route_config'?: (_envoy_admin_v3_RoutesConfigDump | null); + 'scoped_route_config'?: (_envoy_admin_v3_ScopedRoutesConfigDump | null); + 'endpoint_config'?: (_envoy_admin_v3_EndpointsConfigDump | null); + /** + * Client config status is populated by xDS clients. Will not be present if + * the CSDS server is an xDS server. No matter what the client config status + * is, xDS clients should always dump the most recent accepted xDS config. + * + * .. attention:: + * This field is deprecated. Use :ref:`ClientResourceStatus + * ` for per-resource + * config status instead. + */ + 'client_status'?: (_envoy_service_status_v3_ClientConfigStatus | keyof typeof _envoy_service_status_v3_ClientConfigStatus); + 'per_xds_config'?: "listener_config"|"cluster_config"|"route_config"|"scoped_route_config"|"endpoint_config"; +} + +/** + * Detailed config (per xDS) with status. + * [#next-free-field: 8] + */ +export interface PerXdsConfig__Output { + /** + * Config status generated by management servers. Will not be present if the + * CSDS server is an xDS client. + */ + 'status': (keyof typeof _envoy_service_status_v3_ConfigStatus); + 'listener_config'?: (_envoy_admin_v3_ListenersConfigDump__Output | null); + 'cluster_config'?: (_envoy_admin_v3_ClustersConfigDump__Output | null); + 'route_config'?: (_envoy_admin_v3_RoutesConfigDump__Output | null); + 'scoped_route_config'?: (_envoy_admin_v3_ScopedRoutesConfigDump__Output | null); + 'endpoint_config'?: (_envoy_admin_v3_EndpointsConfigDump__Output | null); + /** + * Client config status is populated by xDS clients. Will not be present if + * the CSDS server is an xDS server. No matter what the client config status + * is, xDS clients should always dump the most recent accepted xDS config. + * + * .. attention:: + * This field is deprecated. Use :ref:`ClientResourceStatus + * ` for per-resource + * config status instead. + */ + 'client_status': (keyof typeof _envoy_service_status_v3_ClientConfigStatus); + 'per_xds_config': "listener_config"|"cluster_config"|"route_config"|"scoped_route_config"|"endpoint_config"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/http/v3/PathTransformation.ts b/packages/grpc-js-xds/src/generated/envoy/type/http/v3/PathTransformation.ts new file mode 100644 index 000000000..4dc10efcb --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/http/v3/PathTransformation.ts @@ -0,0 +1,92 @@ +// Original file: deps/envoy-api/envoy/type/http/v3/path_transformation.proto + + +/** + * Determines if adjacent slashes are merged into one. A common use case is for a request path + * header. Using this option in `:ref: PathNormalizationOptions + * ` + * will allow incoming requests with path `//dir///file` to match against route with `prefix` + * match set to `/dir`. When using for header transformations, note that slash merging is not + * part of `HTTP spec `_ and is provided for convenience. + */ +export interface _envoy_type_http_v3_PathTransformation_Operation_MergeSlashes { +} + +/** + * Determines if adjacent slashes are merged into one. A common use case is for a request path + * header. Using this option in `:ref: PathNormalizationOptions + * ` + * will allow incoming requests with path `//dir///file` to match against route with `prefix` + * match set to `/dir`. When using for header transformations, note that slash merging is not + * part of `HTTP spec `_ and is provided for convenience. + */ +export interface _envoy_type_http_v3_PathTransformation_Operation_MergeSlashes__Output { +} + +/** + * Should text be normalized according to RFC 3986? This typically is used for path headers + * before any processing of requests by HTTP filters or routing. This applies percent-encoded + * normalization and path segment normalization. Fails on characters disallowed in URLs + * (e.g. NULLs). See `Normalization and Comparison + * `_ for details of normalization. Note that + * this options does not perform `case normalization + * `_ + */ +export interface _envoy_type_http_v3_PathTransformation_Operation_NormalizePathRFC3986 { +} + +/** + * Should text be normalized according to RFC 3986? This typically is used for path headers + * before any processing of requests by HTTP filters or routing. This applies percent-encoded + * normalization and path segment normalization. Fails on characters disallowed in URLs + * (e.g. NULLs). See `Normalization and Comparison + * `_ for details of normalization. Note that + * this options does not perform `case normalization + * `_ + */ +export interface _envoy_type_http_v3_PathTransformation_Operation_NormalizePathRFC3986__Output { +} + +/** + * A type of operation to alter text. + */ +export interface _envoy_type_http_v3_PathTransformation_Operation { + /** + * Enable path normalization per RFC 3986. + */ + 'normalize_path_rfc_3986'?: (_envoy_type_http_v3_PathTransformation_Operation_NormalizePathRFC3986 | null); + /** + * Enable merging adjacent slashes. + */ + 'merge_slashes'?: (_envoy_type_http_v3_PathTransformation_Operation_MergeSlashes | null); + 'operation_specifier'?: "normalize_path_rfc_3986"|"merge_slashes"; +} + +/** + * A type of operation to alter text. + */ +export interface _envoy_type_http_v3_PathTransformation_Operation__Output { + /** + * Enable path normalization per RFC 3986. + */ + 'normalize_path_rfc_3986'?: (_envoy_type_http_v3_PathTransformation_Operation_NormalizePathRFC3986__Output | null); + /** + * Enable merging adjacent slashes. + */ + 'merge_slashes'?: (_envoy_type_http_v3_PathTransformation_Operation_MergeSlashes__Output | null); + 'operation_specifier': "normalize_path_rfc_3986"|"merge_slashes"; +} + +export interface PathTransformation { + /** + * A list of operations to apply. Transformations will be performed in the order that they appear. + */ + 'operations'?: (_envoy_type_http_v3_PathTransformation_Operation)[]; +} + +export interface PathTransformation__Output { + /** + * A list of operations to apply. Transformations will be performed in the order that they appear. + */ + 'operations': (_envoy_type_http_v3_PathTransformation_Operation__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/ListStringMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/ListStringMatcher.ts deleted file mode 100644 index 42bde031b..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/type/matcher/ListStringMatcher.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Original file: deps/envoy-api/envoy/type/matcher/string.proto - -import type { StringMatcher as _envoy_type_matcher_StringMatcher, StringMatcher__Output as _envoy_type_matcher_StringMatcher__Output } from '../../../envoy/type/matcher/StringMatcher'; - -/** - * Specifies a list of ways to match a string. - */ -export interface ListStringMatcher { - 'patterns'?: (_envoy_type_matcher_StringMatcher)[]; -} - -/** - * Specifies a list of ways to match a string. - */ -export interface ListStringMatcher__Output { - 'patterns': (_envoy_type_matcher_StringMatcher__Output)[]; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/DoubleMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/DoubleMatcher.ts new file mode 100644 index 000000000..0bf3bca79 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/DoubleMatcher.ts @@ -0,0 +1,35 @@ +// Original file: deps/envoy-api/envoy/type/matcher/v3/number.proto + +import type { DoubleRange as _envoy_type_v3_DoubleRange, DoubleRange__Output as _envoy_type_v3_DoubleRange__Output } from '../../../../envoy/type/v3/DoubleRange'; + +/** + * Specifies the way to match a double value. + */ +export interface DoubleMatcher { + /** + * If specified, the input double value must be in the range specified here. + * Note: The range is using half-open interval semantics [start, end). + */ + 'range'?: (_envoy_type_v3_DoubleRange | null); + /** + * If specified, the input double value must be equal to the value specified here. + */ + 'exact'?: (number | string); + 'match_pattern'?: "range"|"exact"; +} + +/** + * Specifies the way to match a double value. + */ +export interface DoubleMatcher__Output { + /** + * If specified, the input double value must be in the range specified here. + * Note: The range is using half-open interval semantics [start, end). + */ + 'range'?: (_envoy_type_v3_DoubleRange__Output | null); + /** + * If specified, the input double value must be equal to the value specified here. + */ + 'exact'?: (number); + 'match_pattern': "range"|"exact"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ListMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ListMatcher.ts new file mode 100644 index 000000000..10bf5567c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ListMatcher.ts @@ -0,0 +1,25 @@ +// Original file: deps/envoy-api/envoy/type/matcher/v3/value.proto + +import type { ValueMatcher as _envoy_type_matcher_v3_ValueMatcher, ValueMatcher__Output as _envoy_type_matcher_v3_ValueMatcher__Output } from '../../../../envoy/type/matcher/v3/ValueMatcher'; + +/** + * Specifies the way to match a list value. + */ +export interface ListMatcher { + /** + * If specified, at least one of the values in the list must match the value specified. + */ + 'one_of'?: (_envoy_type_matcher_v3_ValueMatcher | null); + 'match_pattern'?: "one_of"; +} + +/** + * Specifies the way to match a list value. + */ +export interface ListMatcher__Output { + /** + * If specified, at least one of the values in the list must match the value specified. + */ + 'one_of'?: (_envoy_type_matcher_v3_ValueMatcher__Output | null); + 'match_pattern': "one_of"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ListStringMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ListStringMatcher.ts new file mode 100644 index 000000000..4d5062382 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ListStringMatcher.ts @@ -0,0 +1,17 @@ +// Original file: deps/envoy-api/envoy/type/matcher/v3/string.proto + +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; + +/** + * Specifies a list of ways to match a string. + */ +export interface ListStringMatcher { + 'patterns'?: (_envoy_type_matcher_v3_StringMatcher)[]; +} + +/** + * Specifies a list of ways to match a string. + */ +export interface ListStringMatcher__Output { + 'patterns': (_envoy_type_matcher_v3_StringMatcher__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/MetadataMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/MetadataMatcher.ts new file mode 100644 index 000000000..78d4f03da --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/MetadataMatcher.ts @@ -0,0 +1,73 @@ +// Original file: deps/envoy-api/envoy/type/matcher/v3/metadata.proto + +import type { ValueMatcher as _envoy_type_matcher_v3_ValueMatcher, ValueMatcher__Output as _envoy_type_matcher_v3_ValueMatcher__Output } from '../../../../envoy/type/matcher/v3/ValueMatcher'; + +/** + * Specifies the segment in a path to retrieve value from Metadata. + * Note: Currently it's not supported to retrieve a value from a list in Metadata. This means that + * if the segment key refers to a list, it has to be the last segment in a path. + */ +export interface _envoy_type_matcher_v3_MetadataMatcher_PathSegment { + /** + * If specified, use the key to retrieve the value in a Struct. + */ + 'key'?: (string); + 'segment'?: "key"; +} + +/** + * Specifies the segment in a path to retrieve value from Metadata. + * Note: Currently it's not supported to retrieve a value from a list in Metadata. This means that + * if the segment key refers to a list, it has to be the last segment in a path. + */ +export interface _envoy_type_matcher_v3_MetadataMatcher_PathSegment__Output { + /** + * If specified, use the key to retrieve the value in a Struct. + */ + 'key'?: (string); + 'segment': "key"; +} + +/** + * [#next-major-version: MetadataMatcher should use StructMatcher] + */ +export interface MetadataMatcher { + /** + * The filter name to retrieve the Struct from the Metadata. + */ + 'filter'?: (string); + /** + * The path to retrieve the Value from the Struct. + */ + 'path'?: (_envoy_type_matcher_v3_MetadataMatcher_PathSegment)[]; + /** + * The MetadataMatcher is matched if the value retrieved by path is matched to this value. + */ + 'value'?: (_envoy_type_matcher_v3_ValueMatcher | null); + /** + * If true, the match result will be inverted. + */ + 'invert'?: (boolean); +} + +/** + * [#next-major-version: MetadataMatcher should use StructMatcher] + */ +export interface MetadataMatcher__Output { + /** + * The filter name to retrieve the Struct from the Metadata. + */ + 'filter': (string); + /** + * The path to retrieve the Value from the Struct. + */ + 'path': (_envoy_type_matcher_v3_MetadataMatcher_PathSegment__Output)[]; + /** + * The MetadataMatcher is matched if the value retrieved by path is matched to this value. + */ + 'value': (_envoy_type_matcher_v3_ValueMatcher__Output | null); + /** + * If true, the match result will be inverted. + */ + 'invert': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/NodeMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/NodeMatcher.ts new file mode 100644 index 000000000..7e31b9753 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/NodeMatcher.ts @@ -0,0 +1,34 @@ +// Original file: deps/envoy-api/envoy/type/matcher/v3/node.proto + +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; +import type { StructMatcher as _envoy_type_matcher_v3_StructMatcher, StructMatcher__Output as _envoy_type_matcher_v3_StructMatcher__Output } from '../../../../envoy/type/matcher/v3/StructMatcher'; + +/** + * Specifies the way to match a Node. + * The match follows AND semantics. + */ +export interface NodeMatcher { + /** + * Specifies match criteria on the node id. + */ + 'node_id'?: (_envoy_type_matcher_v3_StringMatcher | null); + /** + * Specifies match criteria on the node metadata. + */ + 'node_metadatas'?: (_envoy_type_matcher_v3_StructMatcher)[]; +} + +/** + * Specifies the way to match a Node. + * The match follows AND semantics. + */ +export interface NodeMatcher__Output { + /** + * Specifies match criteria on the node id. + */ + 'node_id': (_envoy_type_matcher_v3_StringMatcher__Output | null); + /** + * Specifies match criteria on the node metadata. + */ + 'node_metadatas': (_envoy_type_matcher_v3_StructMatcher__Output)[]; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/RegexMatchAndSubstitute.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/RegexMatchAndSubstitute.ts similarity index 88% rename from packages/grpc-js-xds/src/generated/envoy/type/matcher/RegexMatchAndSubstitute.ts rename to packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/RegexMatchAndSubstitute.ts index 17c38c7c0..3796765a7 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/matcher/RegexMatchAndSubstitute.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/RegexMatchAndSubstitute.ts @@ -1,6 +1,6 @@ -// Original file: deps/envoy-api/envoy/type/matcher/regex.proto +// Original file: deps/envoy-api/envoy/type/matcher/v3/regex.proto -import type { RegexMatcher as _envoy_type_matcher_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_RegexMatcher__Output } from '../../../envoy/type/matcher/RegexMatcher'; +import type { RegexMatcher as _envoy_type_matcher_v3_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_v3_RegexMatcher__Output } from '../../../../envoy/type/matcher/v3/RegexMatcher'; /** * Describes how to match a string and then produce a new string using a regular @@ -18,7 +18,7 @@ export interface RegexMatchAndSubstitute { * used in the pattern to extract portions of the subject string, and then * referenced in the substitution string. */ - 'pattern'?: (_envoy_type_matcher_RegexMatcher); + 'pattern'?: (_envoy_type_matcher_v3_RegexMatcher | null); /** * The string that should be substituted into matching portions of the * subject string during a substitution operation to produce a new string. @@ -49,7 +49,7 @@ export interface RegexMatchAndSubstitute__Output { * used in the pattern to extract portions of the subject string, and then * referenced in the substitution string. */ - 'pattern'?: (_envoy_type_matcher_RegexMatcher__Output); + 'pattern': (_envoy_type_matcher_v3_RegexMatcher__Output | null); /** * The string that should be substituted into matching portions of the * subject string during a substitution operation to produce a new string. diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/RegexMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/RegexMatcher.ts similarity index 54% rename from packages/grpc-js-xds/src/generated/envoy/type/matcher/RegexMatcher.ts rename to packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/RegexMatcher.ts index 8a18816b0..1addb1730 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/matcher/RegexMatcher.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/RegexMatcher.ts @@ -1,13 +1,23 @@ -// Original file: deps/envoy-api/envoy/type/matcher/regex.proto +// Original file: deps/envoy-api/envoy/type/matcher/v3/regex.proto -import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../google/protobuf/UInt32Value'; +import type { UInt32Value as _google_protobuf_UInt32Value, UInt32Value__Output as _google_protobuf_UInt32Value__Output } from '../../../../google/protobuf/UInt32Value'; /** * Google's `RE2 `_ regex engine. The regex string must adhere to * the documented `syntax `_. The engine is designed * to complete execution in linear time as well as limit the amount of memory used. + * + * Envoy supports program size checking via runtime. The runtime keys `re2.max_program_size.error_level` + * and `re2.max_program_size.warn_level` can be set to integers as the maximum program size or + * complexity that a compiled regex can have before an exception is thrown or a warning is + * logged, respectively. `re2.max_program_size.error_level` defaults to 100, and + * `re2.max_program_size.warn_level` has no default if unset (will not check/log a warning). + * + * Envoy emits two stats for tracking the program size of regexes: the histogram `re2.program_size`, + * which records the program size, and the counter `re2.exceeded_warn_level`, which is incremented + * each time the program size exceeds the warn level threshold. */ -export interface _envoy_type_matcher_RegexMatcher_GoogleRE2 { +export interface _envoy_type_matcher_v3_RegexMatcher_GoogleRE2 { /** * This field controls the RE2 "program size" which is a rough estimate of how complex a * compiled regex is to evaluate. A regex that has a program size greater than the configured @@ -17,15 +27,25 @@ export interface _envoy_type_matcher_RegexMatcher_GoogleRE2 { * This field is deprecated; regexp validation should be performed on the management server * instead of being done by each individual client. */ - 'max_program_size'?: (_google_protobuf_UInt32Value); + 'max_program_size'?: (_google_protobuf_UInt32Value | null); } /** * Google's `RE2 `_ regex engine. The regex string must adhere to * the documented `syntax `_. The engine is designed * to complete execution in linear time as well as limit the amount of memory used. + * + * Envoy supports program size checking via runtime. The runtime keys `re2.max_program_size.error_level` + * and `re2.max_program_size.warn_level` can be set to integers as the maximum program size or + * complexity that a compiled regex can have before an exception is thrown or a warning is + * logged, respectively. `re2.max_program_size.error_level` defaults to 100, and + * `re2.max_program_size.warn_level` has no default if unset (will not check/log a warning). + * + * Envoy emits two stats for tracking the program size of regexes: the histogram `re2.program_size`, + * which records the program size, and the counter `re2.exceeded_warn_level`, which is incremented + * each time the program size exceeds the warn level threshold. */ -export interface _envoy_type_matcher_RegexMatcher_GoogleRE2__Output { +export interface _envoy_type_matcher_v3_RegexMatcher_GoogleRE2__Output { /** * This field controls the RE2 "program size" which is a rough estimate of how complex a * compiled regex is to evaluate. A regex that has a program size greater than the configured @@ -35,7 +55,7 @@ export interface _envoy_type_matcher_RegexMatcher_GoogleRE2__Output { * This field is deprecated; regexp validation should be performed on the management server * instead of being done by each individual client. */ - 'max_program_size'?: (_google_protobuf_UInt32Value__Output); + 'max_program_size': (_google_protobuf_UInt32Value__Output | null); } /** @@ -45,7 +65,7 @@ export interface RegexMatcher { /** * Google's RE2 regex engine. */ - 'google_re2'?: (_envoy_type_matcher_RegexMatcher_GoogleRE2); + 'google_re2'?: (_envoy_type_matcher_v3_RegexMatcher_GoogleRE2 | null); /** * The regex match string. The string must be supported by the configured engine. */ @@ -60,7 +80,7 @@ export interface RegexMatcher__Output { /** * Google's RE2 regex engine. */ - 'google_re2'?: (_envoy_type_matcher_RegexMatcher_GoogleRE2__Output); + 'google_re2'?: (_envoy_type_matcher_v3_RegexMatcher_GoogleRE2__Output | null); /** * The regex match string. The string must be supported by the configured engine. */ diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/StringMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/StringMatcher.ts similarity index 51% rename from packages/grpc-js-xds/src/generated/envoy/type/matcher/StringMatcher.ts rename to packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/StringMatcher.ts index e434b1e1b..7440746f1 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/matcher/StringMatcher.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/StringMatcher.ts @@ -1,10 +1,10 @@ -// Original file: deps/envoy-api/envoy/type/matcher/string.proto +// Original file: deps/envoy-api/envoy/type/matcher/v3/string.proto -import type { RegexMatcher as _envoy_type_matcher_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_RegexMatcher__Output } from '../../../envoy/type/matcher/RegexMatcher'; +import type { RegexMatcher as _envoy_type_matcher_v3_RegexMatcher, RegexMatcher__Output as _envoy_type_matcher_v3_RegexMatcher__Output } from '../../../../envoy/type/matcher/v3/RegexMatcher'; /** * Specifies the way to match a string. - * [#next-free-field: 7] + * [#next-free-field: 8] */ export interface StringMatcher { /** @@ -33,38 +33,31 @@ export interface StringMatcher { * * *abc* matches the value *xyz.abc* */ 'suffix'?: (string); - /** - * The input string must match the regular expression specified here. - * The regex grammar is defined `here - * `_. - * - * Examples: - * - * * The regex ``\d{3}`` matches the value *123* - * * The regex ``\d{3}`` does not match the value *1234* - * * The regex ``\d{3}`` does not match the value *123.456* - * - * .. attention:: - * This field has been deprecated in favor of `safe_regex` as it is not safe for use with - * untrusted input in all cases. - */ - 'regex'?: (string); /** * The input string must match the regular expression specified here. */ - 'safe_regex'?: (_envoy_type_matcher_RegexMatcher); + 'safe_regex'?: (_envoy_type_matcher_v3_RegexMatcher | null); /** - * If true, indicates the exact/prefix/suffix matching should be case insensitive. This has no - * effect for the safe_regex match. + * If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. This + * has no effect for the safe_regex match. * For example, the matcher *data* will match both input string *Data* and *data* if set to true. */ 'ignore_case'?: (boolean); - 'match_pattern'?: "exact"|"prefix"|"suffix"|"regex"|"safe_regex"; + /** + * The input string must have the substring specified here. + * Note: empty contains match is not allowed, please use regex instead. + * + * Examples: + * + * * *abc* matches the value *xyz.abc.def* + */ + 'contains'?: (string); + 'match_pattern'?: "exact"|"prefix"|"suffix"|"safe_regex"|"contains"; } /** * Specifies the way to match a string. - * [#next-free-field: 7] + * [#next-free-field: 8] */ export interface StringMatcher__Output { /** @@ -93,31 +86,24 @@ export interface StringMatcher__Output { * * *abc* matches the value *xyz.abc* */ 'suffix'?: (string); - /** - * The input string must match the regular expression specified here. - * The regex grammar is defined `here - * `_. - * - * Examples: - * - * * The regex ``\d{3}`` matches the value *123* - * * The regex ``\d{3}`` does not match the value *1234* - * * The regex ``\d{3}`` does not match the value *123.456* - * - * .. attention:: - * This field has been deprecated in favor of `safe_regex` as it is not safe for use with - * untrusted input in all cases. - */ - 'regex'?: (string); /** * The input string must match the regular expression specified here. */ - 'safe_regex'?: (_envoy_type_matcher_RegexMatcher__Output); + 'safe_regex'?: (_envoy_type_matcher_v3_RegexMatcher__Output | null); /** - * If true, indicates the exact/prefix/suffix matching should be case insensitive. This has no - * effect for the safe_regex match. + * If true, indicates the exact/prefix/suffix/contains matching should be case insensitive. This + * has no effect for the safe_regex match. * For example, the matcher *data* will match both input string *Data* and *data* if set to true. */ 'ignore_case': (boolean); - 'match_pattern': "exact"|"prefix"|"suffix"|"regex"|"safe_regex"; + /** + * The input string must have the substring specified here. + * Note: empty contains match is not allowed, please use regex instead. + * + * Examples: + * + * * *abc* matches the value *xyz.abc.def* + */ + 'contains'?: (string); + 'match_pattern': "exact"|"prefix"|"suffix"|"safe_regex"|"contains"; } diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/StructMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/StructMatcher.ts new file mode 100644 index 000000000..141806489 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/StructMatcher.ts @@ -0,0 +1,153 @@ +// Original file: deps/envoy-api/envoy/type/matcher/v3/struct.proto + +import type { ValueMatcher as _envoy_type_matcher_v3_ValueMatcher, ValueMatcher__Output as _envoy_type_matcher_v3_ValueMatcher__Output } from '../../../../envoy/type/matcher/v3/ValueMatcher'; + +/** + * Specifies the segment in a path to retrieve value from Struct. + */ +export interface _envoy_type_matcher_v3_StructMatcher_PathSegment { + /** + * If specified, use the key to retrieve the value in a Struct. + */ + 'key'?: (string); + 'segment'?: "key"; +} + +/** + * Specifies the segment in a path to retrieve value from Struct. + */ +export interface _envoy_type_matcher_v3_StructMatcher_PathSegment__Output { + /** + * If specified, use the key to retrieve the value in a Struct. + */ + 'key'?: (string); + 'segment': "key"; +} + +/** + * StructMatcher provides a general interface to check if a given value is matched in + * google.protobuf.Struct. It uses `path` to retrieve the value + * from the struct and then check if it's matched to the specified value. + * + * For example, for the following Struct: + * + * .. code-block:: yaml + * + * fields: + * a: + * struct_value: + * fields: + * b: + * struct_value: + * fields: + * c: + * string_value: pro + * t: + * list_value: + * values: + * - string_value: m + * - string_value: n + * + * The following MetadataMatcher is matched as the path [a, b, c] will retrieve a string value "pro" + * from the Metadata which is matched to the specified prefix match. + * + * .. code-block:: yaml + * + * path: + * - key: a + * - key: b + * - key: c + * value: + * string_match: + * prefix: pr + * + * The following StructMatcher is matched as the code will match one of the string values in the + * list at the path [a, t]. + * + * .. code-block:: yaml + * + * path: + * - key: a + * - key: t + * value: + * list_match: + * one_of: + * string_match: + * exact: m + * + * An example use of StructMatcher is to match metadata in envoy.v*.core.Node. + */ +export interface StructMatcher { + /** + * The path to retrieve the Value from the Struct. + */ + 'path'?: (_envoy_type_matcher_v3_StructMatcher_PathSegment)[]; + /** + * The StructMatcher is matched if the value retrieved by path is matched to this value. + */ + 'value'?: (_envoy_type_matcher_v3_ValueMatcher | null); +} + +/** + * StructMatcher provides a general interface to check if a given value is matched in + * google.protobuf.Struct. It uses `path` to retrieve the value + * from the struct and then check if it's matched to the specified value. + * + * For example, for the following Struct: + * + * .. code-block:: yaml + * + * fields: + * a: + * struct_value: + * fields: + * b: + * struct_value: + * fields: + * c: + * string_value: pro + * t: + * list_value: + * values: + * - string_value: m + * - string_value: n + * + * The following MetadataMatcher is matched as the path [a, b, c] will retrieve a string value "pro" + * from the Metadata which is matched to the specified prefix match. + * + * .. code-block:: yaml + * + * path: + * - key: a + * - key: b + * - key: c + * value: + * string_match: + * prefix: pr + * + * The following StructMatcher is matched as the code will match one of the string values in the + * list at the path [a, t]. + * + * .. code-block:: yaml + * + * path: + * - key: a + * - key: t + * value: + * list_match: + * one_of: + * string_match: + * exact: m + * + * An example use of StructMatcher is to match metadata in envoy.v*.core.Node. + */ +export interface StructMatcher__Output { + /** + * The path to retrieve the Value from the Struct. + */ + 'path': (_envoy_type_matcher_v3_StructMatcher_PathSegment__Output)[]; + /** + * The StructMatcher is matched if the value retrieved by path is matched to this value. + */ + 'value': (_envoy_type_matcher_v3_ValueMatcher__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ValueMatcher.ts b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ValueMatcher.ts new file mode 100644 index 000000000..d01060446 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/matcher/v3/ValueMatcher.ts @@ -0,0 +1,101 @@ +// Original file: deps/envoy-api/envoy/type/matcher/v3/value.proto + +import type { DoubleMatcher as _envoy_type_matcher_v3_DoubleMatcher, DoubleMatcher__Output as _envoy_type_matcher_v3_DoubleMatcher__Output } from '../../../../envoy/type/matcher/v3/DoubleMatcher'; +import type { StringMatcher as _envoy_type_matcher_v3_StringMatcher, StringMatcher__Output as _envoy_type_matcher_v3_StringMatcher__Output } from '../../../../envoy/type/matcher/v3/StringMatcher'; +import type { ListMatcher as _envoy_type_matcher_v3_ListMatcher, ListMatcher__Output as _envoy_type_matcher_v3_ListMatcher__Output } from '../../../../envoy/type/matcher/v3/ListMatcher'; + +/** + * NullMatch is an empty message to specify a null value. + */ +export interface _envoy_type_matcher_v3_ValueMatcher_NullMatch { +} + +/** + * NullMatch is an empty message to specify a null value. + */ +export interface _envoy_type_matcher_v3_ValueMatcher_NullMatch__Output { +} + +/** + * Specifies the way to match a ProtobufWkt::Value. Primitive values and ListValue are supported. + * StructValue is not supported and is always not matched. + * [#next-free-field: 7] + */ +export interface ValueMatcher { + /** + * If specified, a match occurs if and only if the target value is a NullValue. + */ + 'null_match'?: (_envoy_type_matcher_v3_ValueMatcher_NullMatch | null); + /** + * If specified, a match occurs if and only if the target value is a double value and is + * matched to this field. + */ + 'double_match'?: (_envoy_type_matcher_v3_DoubleMatcher | null); + /** + * If specified, a match occurs if and only if the target value is a string value and is + * matched to this field. + */ + 'string_match'?: (_envoy_type_matcher_v3_StringMatcher | null); + /** + * If specified, a match occurs if and only if the target value is a bool value and is equal + * to this field. + */ + 'bool_match'?: (boolean); + /** + * If specified, value match will be performed based on whether the path is referring to a + * valid primitive value in the metadata. If the path is referring to a non-primitive value, + * the result is always not matched. + */ + 'present_match'?: (boolean); + /** + * If specified, a match occurs if and only if the target value is a list value and + * is matched to this field. + */ + 'list_match'?: (_envoy_type_matcher_v3_ListMatcher | null); + /** + * Specifies how to match a value. + */ + 'match_pattern'?: "null_match"|"double_match"|"string_match"|"bool_match"|"present_match"|"list_match"; +} + +/** + * Specifies the way to match a ProtobufWkt::Value. Primitive values and ListValue are supported. + * StructValue is not supported and is always not matched. + * [#next-free-field: 7] + */ +export interface ValueMatcher__Output { + /** + * If specified, a match occurs if and only if the target value is a NullValue. + */ + 'null_match'?: (_envoy_type_matcher_v3_ValueMatcher_NullMatch__Output | null); + /** + * If specified, a match occurs if and only if the target value is a double value and is + * matched to this field. + */ + 'double_match'?: (_envoy_type_matcher_v3_DoubleMatcher__Output | null); + /** + * If specified, a match occurs if and only if the target value is a string value and is + * matched to this field. + */ + 'string_match'?: (_envoy_type_matcher_v3_StringMatcher__Output | null); + /** + * If specified, a match occurs if and only if the target value is a bool value and is equal + * to this field. + */ + 'bool_match'?: (boolean); + /** + * If specified, value match will be performed based on whether the path is referring to a + * valid primitive value in the metadata. If the path is referring to a non-primitive value, + * the result is always not matched. + */ + 'present_match'?: (boolean); + /** + * If specified, a match occurs if and only if the target value is a list value and + * is matched to this field. + */ + 'list_match'?: (_envoy_type_matcher_v3_ListMatcher__Output | null); + /** + * Specifies how to match a value. + */ + 'match_pattern': "null_match"|"double_match"|"string_match"|"bool_match"|"present_match"|"list_match"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/metadata/v2/MetadataKind.ts b/packages/grpc-js-xds/src/generated/envoy/type/metadata/v2/MetadataKind.ts deleted file mode 100644 index 665b95f0d..000000000 --- a/packages/grpc-js-xds/src/generated/envoy/type/metadata/v2/MetadataKind.ts +++ /dev/null @@ -1,98 +0,0 @@ -// Original file: deps/envoy-api/envoy/type/metadata/v2/metadata.proto - - -/** - * Represents metadata from :ref:`the upstream cluster`. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Cluster { -} - -/** - * Represents metadata from :ref:`the upstream cluster`. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Cluster__Output { -} - -/** - * Represents metadata from :ref:`the upstream - * host`. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Host { -} - -/** - * Represents metadata from :ref:`the upstream - * host`. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Host__Output { -} - -/** - * Represents dynamic metadata associated with the request. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Request { -} - -/** - * Represents dynamic metadata associated with the request. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Request__Output { -} - -/** - * Represents metadata from :ref:`the route`. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Route { -} - -/** - * Represents metadata from :ref:`the route`. - */ -export interface _envoy_type_metadata_v2_MetadataKind_Route__Output { -} - -/** - * Describes what kind of metadata. - */ -export interface MetadataKind { - /** - * Request kind of metadata. - */ - 'request'?: (_envoy_type_metadata_v2_MetadataKind_Request); - /** - * Route kind of metadata. - */ - 'route'?: (_envoy_type_metadata_v2_MetadataKind_Route); - /** - * Cluster kind of metadata. - */ - 'cluster'?: (_envoy_type_metadata_v2_MetadataKind_Cluster); - /** - * Host kind of metadata. - */ - 'host'?: (_envoy_type_metadata_v2_MetadataKind_Host); - 'kind'?: "request"|"route"|"cluster"|"host"; -} - -/** - * Describes what kind of metadata. - */ -export interface MetadataKind__Output { - /** - * Request kind of metadata. - */ - 'request'?: (_envoy_type_metadata_v2_MetadataKind_Request__Output); - /** - * Route kind of metadata. - */ - 'route'?: (_envoy_type_metadata_v2_MetadataKind_Route__Output); - /** - * Cluster kind of metadata. - */ - 'cluster'?: (_envoy_type_metadata_v2_MetadataKind_Cluster__Output); - /** - * Host kind of metadata. - */ - 'host'?: (_envoy_type_metadata_v2_MetadataKind_Host__Output); - 'kind': "request"|"route"|"cluster"|"host"; -} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/metadata/v2/MetadataKey.ts b/packages/grpc-js-xds/src/generated/envoy/type/metadata/v3/MetadataKey.ts similarity index 85% rename from packages/grpc-js-xds/src/generated/envoy/type/metadata/v2/MetadataKey.ts rename to packages/grpc-js-xds/src/generated/envoy/type/metadata/v3/MetadataKey.ts index 94d661879..50b6690d3 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/metadata/v2/MetadataKey.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/metadata/v3/MetadataKey.ts @@ -1,11 +1,11 @@ -// Original file: deps/envoy-api/envoy/type/metadata/v2/metadata.proto +// Original file: deps/envoy-api/envoy/type/metadata/v3/metadata.proto /** * Specifies the segment in a path to retrieve value from Metadata. * Currently it is only supported to specify the key, i.e. field name, as one segment of a path. */ -export interface _envoy_type_metadata_v2_MetadataKey_PathSegment { +export interface _envoy_type_metadata_v3_MetadataKey_PathSegment { /** * If specified, use the key to retrieve the value in a Struct. */ @@ -17,7 +17,7 @@ export interface _envoy_type_metadata_v2_MetadataKey_PathSegment { * Specifies the segment in a path to retrieve value from Metadata. * Currently it is only supported to specify the key, i.e. field name, as one segment of a path. */ -export interface _envoy_type_metadata_v2_MetadataKey_PathSegment__Output { +export interface _envoy_type_metadata_v3_MetadataKey_PathSegment__Output { /** * If specified, use the key to retrieve the value in a Struct. */ @@ -27,7 +27,7 @@ export interface _envoy_type_metadata_v2_MetadataKey_PathSegment__Output { /** * MetadataKey provides a general interface using `key` and `path` to retrieve value from - * :ref:`Metadata `. + * :ref:`Metadata `. * * For example, for the following Metadata: * @@ -63,12 +63,12 @@ export interface MetadataKey { * Note: Due to that only the key type segment is supported, the path can not specify a list * unless the list is the last segment. */ - 'path'?: (_envoy_type_metadata_v2_MetadataKey_PathSegment)[]; + 'path'?: (_envoy_type_metadata_v3_MetadataKey_PathSegment)[]; } /** * MetadataKey provides a general interface using `key` and `path` to retrieve value from - * :ref:`Metadata `. + * :ref:`Metadata `. * * For example, for the following Metadata: * @@ -104,5 +104,5 @@ export interface MetadataKey__Output { * Note: Due to that only the key type segment is supported, the path can not specify a list * unless the list is the last segment. */ - 'path': (_envoy_type_metadata_v2_MetadataKey_PathSegment__Output)[]; + 'path': (_envoy_type_metadata_v3_MetadataKey_PathSegment__Output)[]; } diff --git a/packages/grpc-js-xds/src/generated/envoy/type/metadata/v3/MetadataKind.ts b/packages/grpc-js-xds/src/generated/envoy/type/metadata/v3/MetadataKind.ts new file mode 100644 index 000000000..3ca368ccb --- /dev/null +++ b/packages/grpc-js-xds/src/generated/envoy/type/metadata/v3/MetadataKind.ts @@ -0,0 +1,98 @@ +// Original file: deps/envoy-api/envoy/type/metadata/v3/metadata.proto + + +/** + * Represents metadata from :ref:`the upstream cluster`. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Cluster { +} + +/** + * Represents metadata from :ref:`the upstream cluster`. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Cluster__Output { +} + +/** + * Represents metadata from :ref:`the upstream + * host`. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Host { +} + +/** + * Represents metadata from :ref:`the upstream + * host`. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Host__Output { +} + +/** + * Represents dynamic metadata associated with the request. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Request { +} + +/** + * Represents dynamic metadata associated with the request. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Request__Output { +} + +/** + * Represents metadata from :ref:`the route`. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Route { +} + +/** + * Represents metadata from :ref:`the route`. + */ +export interface _envoy_type_metadata_v3_MetadataKind_Route__Output { +} + +/** + * Describes what kind of metadata. + */ +export interface MetadataKind { + /** + * Request kind of metadata. + */ + 'request'?: (_envoy_type_metadata_v3_MetadataKind_Request | null); + /** + * Route kind of metadata. + */ + 'route'?: (_envoy_type_metadata_v3_MetadataKind_Route | null); + /** + * Cluster kind of metadata. + */ + 'cluster'?: (_envoy_type_metadata_v3_MetadataKind_Cluster | null); + /** + * Host kind of metadata. + */ + 'host'?: (_envoy_type_metadata_v3_MetadataKind_Host | null); + 'kind'?: "request"|"route"|"cluster"|"host"; +} + +/** + * Describes what kind of metadata. + */ +export interface MetadataKind__Output { + /** + * Request kind of metadata. + */ + 'request'?: (_envoy_type_metadata_v3_MetadataKind_Request__Output | null); + /** + * Route kind of metadata. + */ + 'route'?: (_envoy_type_metadata_v3_MetadataKind_Route__Output | null); + /** + * Cluster kind of metadata. + */ + 'cluster'?: (_envoy_type_metadata_v3_MetadataKind_Cluster__Output | null); + /** + * Host kind of metadata. + */ + 'host'?: (_envoy_type_metadata_v3_MetadataKind_Host__Output | null); + 'kind': "request"|"route"|"cluster"|"host"; +} diff --git a/packages/grpc-js-xds/src/generated/envoy/type/tracing/v2/CustomTag.ts b/packages/grpc-js-xds/src/generated/envoy/type/tracing/v3/CustomTag.ts similarity index 64% rename from packages/grpc-js-xds/src/generated/envoy/type/tracing/v2/CustomTag.ts rename to packages/grpc-js-xds/src/generated/envoy/type/tracing/v3/CustomTag.ts index 3eed4cf44..34ac26f8c 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/tracing/v2/CustomTag.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/tracing/v3/CustomTag.ts @@ -1,12 +1,12 @@ -// Original file: deps/envoy-api/envoy/type/tracing/v2/custom_tag.proto +// Original file: deps/envoy-api/envoy/type/tracing/v3/custom_tag.proto -import type { MetadataKind as _envoy_type_metadata_v2_MetadataKind, MetadataKind__Output as _envoy_type_metadata_v2_MetadataKind__Output } from '../../../../envoy/type/metadata/v2/MetadataKind'; -import type { MetadataKey as _envoy_type_metadata_v2_MetadataKey, MetadataKey__Output as _envoy_type_metadata_v2_MetadataKey__Output } from '../../../../envoy/type/metadata/v2/MetadataKey'; +import type { MetadataKind as _envoy_type_metadata_v3_MetadataKind, MetadataKind__Output as _envoy_type_metadata_v3_MetadataKind__Output } from '../../../../envoy/type/metadata/v3/MetadataKind'; +import type { MetadataKey as _envoy_type_metadata_v3_MetadataKey, MetadataKey__Output as _envoy_type_metadata_v3_MetadataKey__Output } from '../../../../envoy/type/metadata/v3/MetadataKey'; /** * Environment type custom tag with environment name and default value. */ -export interface _envoy_type_tracing_v2_CustomTag_Environment { +export interface _envoy_type_tracing_v3_CustomTag_Environment { /** * Environment variable name to obtain the value to populate the tag value. */ @@ -22,7 +22,7 @@ export interface _envoy_type_tracing_v2_CustomTag_Environment { /** * Environment type custom tag with environment name and default value. */ -export interface _envoy_type_tracing_v2_CustomTag_Environment__Output { +export interface _envoy_type_tracing_v3_CustomTag_Environment__Output { /** * Environment variable name to obtain the value to populate the tag value. */ @@ -38,7 +38,7 @@ export interface _envoy_type_tracing_v2_CustomTag_Environment__Output { /** * Header type custom tag with header name and default value. */ -export interface _envoy_type_tracing_v2_CustomTag_Header { +export interface _envoy_type_tracing_v3_CustomTag_Header { /** * Header name to obtain the value to populate the tag value. */ @@ -54,7 +54,7 @@ export interface _envoy_type_tracing_v2_CustomTag_Header { /** * Header type custom tag with header name and default value. */ -export interface _envoy_type_tracing_v2_CustomTag_Header__Output { +export interface _envoy_type_tracing_v3_CustomTag_Header__Output { /** * Header name to obtain the value to populate the tag value. */ @@ -70,7 +70,7 @@ export interface _envoy_type_tracing_v2_CustomTag_Header__Output { /** * Literal type custom tag with static value for the tag value. */ -export interface _envoy_type_tracing_v2_CustomTag_Literal { +export interface _envoy_type_tracing_v3_CustomTag_Literal { /** * Static literal value to populate the tag value. */ @@ -80,7 +80,7 @@ export interface _envoy_type_tracing_v2_CustomTag_Literal { /** * Literal type custom tag with static value for the tag value. */ -export interface _envoy_type_tracing_v2_CustomTag_Literal__Output { +export interface _envoy_type_tracing_v3_CustomTag_Literal__Output { /** * Static literal value to populate the tag value. */ @@ -89,20 +89,20 @@ export interface _envoy_type_tracing_v2_CustomTag_Literal__Output { /** * Metadata type custom tag using - * :ref:`MetadataKey ` to retrieve the protobuf value - * from :ref:`Metadata `, and populate the tag value with + * :ref:`MetadataKey ` to retrieve the protobuf value + * from :ref:`Metadata `, and populate the tag value with * `the canonical JSON `_ * representation of it. */ -export interface _envoy_type_tracing_v2_CustomTag_Metadata { +export interface _envoy_type_tracing_v3_CustomTag_Metadata { /** * Specify what kind of metadata to obtain tag value from. */ - 'kind'?: (_envoy_type_metadata_v2_MetadataKind); + 'kind'?: (_envoy_type_metadata_v3_MetadataKind | null); /** * Metadata key to define the path to retrieve the tag value. */ - 'metadata_key'?: (_envoy_type_metadata_v2_MetadataKey); + 'metadata_key'?: (_envoy_type_metadata_v3_MetadataKey | null); /** * When no valid metadata is found, * the tag value would be populated with this default value if specified, @@ -113,20 +113,20 @@ export interface _envoy_type_tracing_v2_CustomTag_Metadata { /** * Metadata type custom tag using - * :ref:`MetadataKey ` to retrieve the protobuf value - * from :ref:`Metadata `, and populate the tag value with + * :ref:`MetadataKey ` to retrieve the protobuf value + * from :ref:`Metadata `, and populate the tag value with * `the canonical JSON `_ * representation of it. */ -export interface _envoy_type_tracing_v2_CustomTag_Metadata__Output { +export interface _envoy_type_tracing_v3_CustomTag_Metadata__Output { /** * Specify what kind of metadata to obtain tag value from. */ - 'kind'?: (_envoy_type_metadata_v2_MetadataKind__Output); + 'kind': (_envoy_type_metadata_v3_MetadataKind__Output | null); /** * Metadata key to define the path to retrieve the tag value. */ - 'metadata_key'?: (_envoy_type_metadata_v2_MetadataKey__Output); + 'metadata_key': (_envoy_type_metadata_v3_MetadataKey__Output | null); /** * When no valid metadata is found, * the tag value would be populated with this default value if specified, @@ -147,19 +147,19 @@ export interface CustomTag { /** * A literal custom tag. */ - 'literal'?: (_envoy_type_tracing_v2_CustomTag_Literal); + 'literal'?: (_envoy_type_tracing_v3_CustomTag_Literal | null); /** * An environment custom tag. */ - 'environment'?: (_envoy_type_tracing_v2_CustomTag_Environment); + 'environment'?: (_envoy_type_tracing_v3_CustomTag_Environment | null); /** * A request header custom tag. */ - 'request_header'?: (_envoy_type_tracing_v2_CustomTag_Header); + 'request_header'?: (_envoy_type_tracing_v3_CustomTag_Header | null); /** * A custom tag to obtain tag value from the metadata. */ - 'metadata'?: (_envoy_type_tracing_v2_CustomTag_Metadata); + 'metadata'?: (_envoy_type_tracing_v3_CustomTag_Metadata | null); /** * Used to specify what kind of custom tag. */ @@ -178,19 +178,19 @@ export interface CustomTag__Output { /** * A literal custom tag. */ - 'literal'?: (_envoy_type_tracing_v2_CustomTag_Literal__Output); + 'literal'?: (_envoy_type_tracing_v3_CustomTag_Literal__Output | null); /** * An environment custom tag. */ - 'environment'?: (_envoy_type_tracing_v2_CustomTag_Environment__Output); + 'environment'?: (_envoy_type_tracing_v3_CustomTag_Environment__Output | null); /** * A request header custom tag. */ - 'request_header'?: (_envoy_type_tracing_v2_CustomTag_Header__Output); + 'request_header'?: (_envoy_type_tracing_v3_CustomTag_Header__Output | null); /** * A custom tag to obtain tag value from the metadata. */ - 'metadata'?: (_envoy_type_tracing_v2_CustomTag_Metadata__Output); + 'metadata'?: (_envoy_type_tracing_v3_CustomTag_Metadata__Output | null); /** * Used to specify what kind of custom tag. */ diff --git a/packages/grpc-js-xds/src/generated/envoy/type/CodecClientType.ts b/packages/grpc-js-xds/src/generated/envoy/type/v3/CodecClientType.ts similarity index 84% rename from packages/grpc-js-xds/src/generated/envoy/type/CodecClientType.ts rename to packages/grpc-js-xds/src/generated/envoy/type/v3/CodecClientType.ts index a0bf07351..308f14446 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/CodecClientType.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/v3/CodecClientType.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/type/http.proto +// Original file: deps/envoy-api/envoy/type/v3/http.proto export enum CodecClientType { HTTP1 = 0, diff --git a/packages/grpc-js-xds/src/generated/envoy/type/DoubleRange.ts b/packages/grpc-js-xds/src/generated/envoy/type/v3/DoubleRange.ts similarity index 82% rename from packages/grpc-js-xds/src/generated/envoy/type/DoubleRange.ts rename to packages/grpc-js-xds/src/generated/envoy/type/v3/DoubleRange.ts index 5ebc3a579..5d13bebdb 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/DoubleRange.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/v3/DoubleRange.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/type/range.proto +// Original file: deps/envoy-api/envoy/type/v3/range.proto /** @@ -24,9 +24,9 @@ export interface DoubleRange__Output { /** * start of the range (inclusive) */ - 'start': (number | string); + 'start': (number); /** * end of the range (exclusive) */ - 'end': (number | string); + 'end': (number); } diff --git a/packages/grpc-js-xds/src/generated/envoy/type/FractionalPercent.ts b/packages/grpc-js-xds/src/generated/envoy/type/v3/FractionalPercent.ts similarity index 80% rename from packages/grpc-js-xds/src/generated/envoy/type/FractionalPercent.ts rename to packages/grpc-js-xds/src/generated/envoy/type/v3/FractionalPercent.ts index e450f0bfa..564af9a0f 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/FractionalPercent.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/v3/FractionalPercent.ts @@ -1,12 +1,12 @@ -// Original file: deps/envoy-api/envoy/type/percent.proto +// Original file: deps/envoy-api/envoy/type/v3/percent.proto -// Original file: deps/envoy-api/envoy/type/percent.proto +// Original file: deps/envoy-api/envoy/type/v3/percent.proto /** * Fraction percentages support several fixed denominator values. */ -export enum _envoy_type_FractionalPercent_DenominatorType { +export enum _envoy_type_v3_FractionalPercent_DenominatorType { /** * 100. * @@ -44,7 +44,7 @@ export interface FractionalPercent { * Specifies the denominator. If the denominator specified is less than the numerator, the final * fractional percentage is capped at 1 (100%). */ - 'denominator'?: (_envoy_type_FractionalPercent_DenominatorType | keyof typeof _envoy_type_FractionalPercent_DenominatorType); + 'denominator'?: (_envoy_type_v3_FractionalPercent_DenominatorType | keyof typeof _envoy_type_v3_FractionalPercent_DenominatorType); } /** @@ -64,5 +64,5 @@ export interface FractionalPercent__Output { * Specifies the denominator. If the denominator specified is less than the numerator, the final * fractional percentage is capped at 1 (100%). */ - 'denominator': (keyof typeof _envoy_type_FractionalPercent_DenominatorType); + 'denominator': (keyof typeof _envoy_type_v3_FractionalPercent_DenominatorType); } diff --git a/packages/grpc-js-xds/src/generated/envoy/type/Int32Range.ts b/packages/grpc-js-xds/src/generated/envoy/type/v3/Int32Range.ts similarity index 90% rename from packages/grpc-js-xds/src/generated/envoy/type/Int32Range.ts rename to packages/grpc-js-xds/src/generated/envoy/type/v3/Int32Range.ts index f5475c2db..826af6c38 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/Int32Range.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/v3/Int32Range.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/type/range.proto +// Original file: deps/envoy-api/envoy/type/v3/range.proto /** diff --git a/packages/grpc-js-xds/src/generated/envoy/type/Int64Range.ts b/packages/grpc-js-xds/src/generated/envoy/type/v3/Int64Range.ts similarity index 91% rename from packages/grpc-js-xds/src/generated/envoy/type/Int64Range.ts rename to packages/grpc-js-xds/src/generated/envoy/type/v3/Int64Range.ts index f9664cba4..89ce7fb8d 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/Int64Range.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/v3/Int64Range.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/type/range.proto +// Original file: deps/envoy-api/envoy/type/v3/range.proto import type { Long } from '@grpc/proto-loader'; diff --git a/packages/grpc-js-xds/src/generated/envoy/type/Percent.ts b/packages/grpc-js-xds/src/generated/envoy/type/v3/Percent.ts similarity index 71% rename from packages/grpc-js-xds/src/generated/envoy/type/Percent.ts rename to packages/grpc-js-xds/src/generated/envoy/type/v3/Percent.ts index f63553acd..01d236c4e 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/Percent.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/v3/Percent.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/type/percent.proto +// Original file: deps/envoy-api/envoy/type/v3/percent.proto /** @@ -12,5 +12,5 @@ export interface Percent { * Identifies a percentage, in the range [0.0, 100.0]. */ export interface Percent__Output { - 'value': (number | string); + 'value': (number); } diff --git a/packages/grpc-js-xds/src/generated/envoy/type/SemanticVersion.ts b/packages/grpc-js-xds/src/generated/envoy/type/v3/SemanticVersion.ts similarity index 90% rename from packages/grpc-js-xds/src/generated/envoy/type/SemanticVersion.ts rename to packages/grpc-js-xds/src/generated/envoy/type/v3/SemanticVersion.ts index f99431703..3f714a766 100644 --- a/packages/grpc-js-xds/src/generated/envoy/type/SemanticVersion.ts +++ b/packages/grpc-js-xds/src/generated/envoy/type/v3/SemanticVersion.ts @@ -1,4 +1,4 @@ -// Original file: deps/envoy-api/envoy/type/semantic_version.proto +// Original file: deps/envoy-api/envoy/type/v3/semantic_version.proto /** diff --git a/packages/grpc-js-xds/src/generated/fault.ts b/packages/grpc-js-xds/src/generated/fault.ts new file mode 100644 index 000000000..896382e50 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/fault.ts @@ -0,0 +1,236 @@ +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + envoy: { + annotations: { + } + config: { + core: { + v3: { + Address: MessageTypeDefinition + AggregatedConfigSource: MessageTypeDefinition + ApiConfigSource: MessageTypeDefinition + ApiVersion: EnumTypeDefinition + AsyncDataSource: MessageTypeDefinition + BackoffStrategy: MessageTypeDefinition + BindConfig: MessageTypeDefinition + BuildVersion: MessageTypeDefinition + CidrRange: MessageTypeDefinition + ConfigSource: MessageTypeDefinition + ControlPlane: MessageTypeDefinition + DataSource: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition + Extension: MessageTypeDefinition + ExtensionConfigSource: MessageTypeDefinition + GrpcService: MessageTypeDefinition + HeaderMap: MessageTypeDefinition + HeaderValue: MessageTypeDefinition + HeaderValueOption: MessageTypeDefinition + HttpUri: MessageTypeDefinition + Locality: MessageTypeDefinition + Metadata: MessageTypeDefinition + Node: MessageTypeDefinition + Pipe: MessageTypeDefinition + ProxyProtocolConfig: MessageTypeDefinition + QueryParameter: MessageTypeDefinition + RateLimitSettings: MessageTypeDefinition + RemoteDataSource: MessageTypeDefinition + RequestMethod: EnumTypeDefinition + RetryPolicy: MessageTypeDefinition + RoutingPriority: EnumTypeDefinition + RuntimeDouble: MessageTypeDefinition + RuntimeFeatureFlag: MessageTypeDefinition + RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition + RuntimeUInt32: MessageTypeDefinition + SelfConfigSource: MessageTypeDefinition + SocketAddress: MessageTypeDefinition + SocketOption: MessageTypeDefinition + TcpKeepalive: MessageTypeDefinition + TrafficDirection: EnumTypeDefinition + TransportSocket: MessageTypeDefinition + TypedExtensionConfig: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition + } + } + route: { + v3: { + CorsPolicy: MessageTypeDefinition + Decorator: MessageTypeDefinition + DirectResponseAction: MessageTypeDefinition + FilterAction: MessageTypeDefinition + FilterConfig: MessageTypeDefinition + HeaderMatcher: MessageTypeDefinition + HedgePolicy: MessageTypeDefinition + InternalRedirectPolicy: MessageTypeDefinition + NonForwardingAction: MessageTypeDefinition + QueryParameterMatcher: MessageTypeDefinition + RateLimit: MessageTypeDefinition + RedirectAction: MessageTypeDefinition + RetryPolicy: MessageTypeDefinition + Route: MessageTypeDefinition + RouteAction: MessageTypeDefinition + RouteMatch: MessageTypeDefinition + Tracing: MessageTypeDefinition + VirtualCluster: MessageTypeDefinition + VirtualHost: MessageTypeDefinition + WeightedCluster: MessageTypeDefinition + } + } + } + extensions: { + filters: { + common: { + fault: { + v3: { + FaultDelay: MessageTypeDefinition + FaultRateLimit: MessageTypeDefinition + } + } + } + http: { + fault: { + v3: { + FaultAbort: MessageTypeDefinition + HTTPFault: MessageTypeDefinition + } + } + } + } + } + type: { + matcher: { + v3: { + DoubleMatcher: MessageTypeDefinition + ListMatcher: MessageTypeDefinition + ListStringMatcher: MessageTypeDefinition + MetadataMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + ValueMatcher: MessageTypeDefinition + } + } + metadata: { + v3: { + MetadataKey: MessageTypeDefinition + MetadataKind: MessageTypeDefinition + } + } + tracing: { + v3: { + CustomTag: MessageTypeDefinition + } + } + v3: { + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + } + } + } + google: { + protobuf: { + Any: MessageTypeDefinition + BoolValue: MessageTypeDefinition + BytesValue: MessageTypeDefinition + DescriptorProto: MessageTypeDefinition + DoubleValue: MessageTypeDefinition + Duration: MessageTypeDefinition + Empty: MessageTypeDefinition + EnumDescriptorProto: MessageTypeDefinition + EnumOptions: MessageTypeDefinition + EnumValueDescriptorProto: MessageTypeDefinition + EnumValueOptions: MessageTypeDefinition + FieldDescriptorProto: MessageTypeDefinition + FieldOptions: MessageTypeDefinition + FileDescriptorProto: MessageTypeDefinition + FileDescriptorSet: MessageTypeDefinition + FileOptions: MessageTypeDefinition + FloatValue: MessageTypeDefinition + GeneratedCodeInfo: MessageTypeDefinition + Int32Value: MessageTypeDefinition + Int64Value: MessageTypeDefinition + ListValue: MessageTypeDefinition + MessageOptions: MessageTypeDefinition + MethodDescriptorProto: MessageTypeDefinition + MethodOptions: MessageTypeDefinition + NullValue: EnumTypeDefinition + OneofDescriptorProto: MessageTypeDefinition + OneofOptions: MessageTypeDefinition + ServiceDescriptorProto: MessageTypeDefinition + ServiceOptions: MessageTypeDefinition + SourceCodeInfo: MessageTypeDefinition + StringValue: MessageTypeDefinition + Struct: MessageTypeDefinition + Timestamp: MessageTypeDefinition + UInt32Value: MessageTypeDefinition + UInt64Value: MessageTypeDefinition + UninterpretedOption: MessageTypeDefinition + Value: MessageTypeDefinition + } + } + udpa: { + annotations: { + FieldMigrateAnnotation: MessageTypeDefinition + FileMigrateAnnotation: MessageTypeDefinition + MigrateAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition + } + } + validate: { + AnyRules: MessageTypeDefinition + BoolRules: MessageTypeDefinition + BytesRules: MessageTypeDefinition + DoubleRules: MessageTypeDefinition + DurationRules: MessageTypeDefinition + EnumRules: MessageTypeDefinition + FieldRules: MessageTypeDefinition + Fixed32Rules: MessageTypeDefinition + Fixed64Rules: MessageTypeDefinition + FloatRules: MessageTypeDefinition + Int32Rules: MessageTypeDefinition + Int64Rules: MessageTypeDefinition + KnownRegex: EnumTypeDefinition + MapRules: MessageTypeDefinition + MessageRules: MessageTypeDefinition + RepeatedRules: MessageTypeDefinition + SFixed32Rules: MessageTypeDefinition + SFixed64Rules: MessageTypeDefinition + SInt32Rules: MessageTypeDefinition + SInt64Rules: MessageTypeDefinition + StringRules: MessageTypeDefinition + TimestampRules: MessageTypeDefinition + UInt32Rules: MessageTypeDefinition + UInt64Rules: MessageTypeDefinition + } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + Authority: MessageTypeDefinition + ContextParams: MessageTypeDefinition + } + } + } +} + diff --git a/packages/grpc-js-xds/src/generated/google/api/HttpRule.ts b/packages/grpc-js-xds/src/generated/google/api/HttpRule.ts index 21ad897ee..243a99f80 100644 --- a/packages/grpc-js-xds/src/generated/google/api/HttpRule.ts +++ b/packages/grpc-js-xds/src/generated/google/api/HttpRule.ts @@ -317,7 +317,7 @@ export interface HttpRule { * HTTP method unspecified for this rule. The wild-card rule is useful * for services that provide content to Web (HTML) clients. */ - 'custom'?: (_google_api_CustomHttpPattern); + 'custom'?: (_google_api_CustomHttpPattern | null); /** * Additional HTTP bindings for the selector. Nested bindings must * not contain an `additional_bindings` field themselves (that is, @@ -655,7 +655,7 @@ export interface HttpRule__Output { * HTTP method unspecified for this rule. The wild-card rule is useful * for services that provide content to Web (HTML) clients. */ - 'custom'?: (_google_api_CustomHttpPattern__Output); + 'custom'?: (_google_api_CustomHttpPattern__Output | null); /** * Additional HTTP bindings for the selector. Nested bindings must * not contain an `additional_bindings` field themselves (that is, diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/Any.ts b/packages/grpc-js-xds/src/generated/google/protobuf/Any.ts index fe0d05f12..fcaa6724e 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/Any.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/Any.ts @@ -7,7 +7,7 @@ export type Any = AnyExtension | { value: Buffer | Uint8Array | string; } -export type Any__Output = AnyExtension | { - type_url: string; - value: Buffer; +export interface Any__Output { + 'type_url': (string); + 'value': (Buffer); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/DescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/DescriptorProto.ts index 2f6f9f0cc..f729437f4 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/DescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/DescriptorProto.ts @@ -33,7 +33,7 @@ export interface DescriptorProto { 'enumType'?: (_google_protobuf_EnumDescriptorProto)[]; 'extensionRange'?: (_google_protobuf_DescriptorProto_ExtensionRange)[]; 'extension'?: (_google_protobuf_FieldDescriptorProto)[]; - 'options'?: (_google_protobuf_MessageOptions); + 'options'?: (_google_protobuf_MessageOptions | null); 'oneofDecl'?: (_google_protobuf_OneofDescriptorProto)[]; 'reservedRange'?: (_google_protobuf_DescriptorProto_ReservedRange)[]; 'reservedName'?: (string)[]; @@ -46,7 +46,7 @@ export interface DescriptorProto__Output { 'enumType': (_google_protobuf_EnumDescriptorProto__Output)[]; 'extensionRange': (_google_protobuf_DescriptorProto_ExtensionRange__Output)[]; 'extension': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'options'?: (_google_protobuf_MessageOptions__Output); + 'options': (_google_protobuf_MessageOptions__Output | null); 'oneofDecl': (_google_protobuf_OneofDescriptorProto__Output)[]; 'reservedRange': (_google_protobuf_DescriptorProto_ReservedRange__Output)[]; 'reservedName': (string)[]; diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/DoubleValue.ts b/packages/grpc-js-xds/src/generated/google/protobuf/DoubleValue.ts index e4f2eb4b8..d70b303c2 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/DoubleValue.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/DoubleValue.ts @@ -6,5 +6,5 @@ export interface DoubleValue { } export interface DoubleValue__Output { - 'value': (number | string); + 'value': (number); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/EnumDescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/EnumDescriptorProto.ts index 7aa40ce4d..dc4c9673e 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/EnumDescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/EnumDescriptorProto.ts @@ -6,11 +6,11 @@ import type { EnumOptions as _google_protobuf_EnumOptions, EnumOptions__Output a export interface EnumDescriptorProto { 'name'?: (string); 'value'?: (_google_protobuf_EnumValueDescriptorProto)[]; - 'options'?: (_google_protobuf_EnumOptions); + 'options'?: (_google_protobuf_EnumOptions | null); } export interface EnumDescriptorProto__Output { 'name': (string); 'value': (_google_protobuf_EnumValueDescriptorProto__Output)[]; - 'options'?: (_google_protobuf_EnumOptions__Output); + 'options': (_google_protobuf_EnumOptions__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/EnumOptions.ts b/packages/grpc-js-xds/src/generated/google/protobuf/EnumOptions.ts index b92f699a0..777901a54 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/EnumOptions.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/EnumOptions.ts @@ -7,12 +7,12 @@ export interface EnumOptions { 'allowAlias'?: (boolean); 'deprecated'?: (boolean); 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; - '.udpa.annotations.enum_migrate'?: (_udpa_annotations_MigrateAnnotation); + '.udpa.annotations.enum_migrate'?: (_udpa_annotations_MigrateAnnotation | null); } export interface EnumOptions__Output { 'allowAlias': (boolean); 'deprecated': (boolean); 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; - '.udpa.annotations.enum_migrate'?: (_udpa_annotations_MigrateAnnotation__Output); + '.udpa.annotations.enum_migrate': (_udpa_annotations_MigrateAnnotation__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueDescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueDescriptorProto.ts index 238e7fd01..7f8e57ea5 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueDescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueDescriptorProto.ts @@ -5,11 +5,11 @@ import type { EnumValueOptions as _google_protobuf_EnumValueOptions, EnumValueOp export interface EnumValueDescriptorProto { 'name'?: (string); 'number'?: (number); - 'options'?: (_google_protobuf_EnumValueOptions); + 'options'?: (_google_protobuf_EnumValueOptions | null); } export interface EnumValueDescriptorProto__Output { 'name': (string); 'number': (number); - 'options'?: (_google_protobuf_EnumValueOptions__Output); + 'options': (_google_protobuf_EnumValueOptions__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueOptions.ts b/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueOptions.ts index db2770534..9ba51ed60 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueOptions.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/EnumValueOptions.ts @@ -7,12 +7,14 @@ export interface EnumValueOptions { 'deprecated'?: (boolean); 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; '.envoy.annotations.disallowed_by_default_enum'?: (boolean); - '.udpa.annotations.enum_value_migrate'?: (_udpa_annotations_MigrateAnnotation); + '.udpa.annotations.enum_value_migrate'?: (_udpa_annotations_MigrateAnnotation | null); + '.envoy.annotations.deprecated_at_minor_version_enum'?: (string); } export interface EnumValueOptions__Output { 'deprecated': (boolean); 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; '.envoy.annotations.disallowed_by_default_enum': (boolean); - '.udpa.annotations.enum_value_migrate'?: (_udpa_annotations_MigrateAnnotation__Output); + '.udpa.annotations.enum_value_migrate': (_udpa_annotations_MigrateAnnotation__Output | null); + '.envoy.annotations.deprecated_at_minor_version_enum': (string); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/FieldDescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/FieldDescriptorProto.ts index b59518c4b..c511e2eff 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/FieldDescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/FieldDescriptorProto.ts @@ -41,7 +41,7 @@ export interface FieldDescriptorProto { 'type'?: (_google_protobuf_FieldDescriptorProto_Type | keyof typeof _google_protobuf_FieldDescriptorProto_Type); 'typeName'?: (string); 'defaultValue'?: (string); - 'options'?: (_google_protobuf_FieldOptions); + 'options'?: (_google_protobuf_FieldOptions | null); 'oneofIndex'?: (number); 'jsonName'?: (string); } @@ -54,7 +54,7 @@ export interface FieldDescriptorProto__Output { 'type': (keyof typeof _google_protobuf_FieldDescriptorProto_Type); 'typeName': (string); 'defaultValue': (string); - 'options'?: (_google_protobuf_FieldOptions__Output); + 'options': (_google_protobuf_FieldOptions__Output | null); 'oneofIndex': (number); 'jsonName': (string); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/FieldOptions.ts b/packages/grpc-js-xds/src/generated/google/protobuf/FieldOptions.ts index b76a60815..d62db88d0 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/FieldOptions.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/FieldOptions.ts @@ -2,7 +2,9 @@ import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; import type { FieldRules as _validate_FieldRules, FieldRules__Output as _validate_FieldRules__Output } from '../../validate/FieldRules'; +import type { FieldSecurityAnnotation as _udpa_annotations_FieldSecurityAnnotation, FieldSecurityAnnotation__Output as _udpa_annotations_FieldSecurityAnnotation__Output } from '../../udpa/annotations/FieldSecurityAnnotation'; import type { FieldMigrateAnnotation as _udpa_annotations_FieldMigrateAnnotation, FieldMigrateAnnotation__Output as _udpa_annotations_FieldMigrateAnnotation__Output } from '../../udpa/annotations/FieldMigrateAnnotation'; +import type { FieldStatusAnnotation as _xds_annotations_v3_FieldStatusAnnotation, FieldStatusAnnotation__Output as _xds_annotations_v3_FieldStatusAnnotation__Output } from '../../xds/annotations/v3/FieldStatusAnnotation'; // Original file: null @@ -28,10 +30,13 @@ export interface FieldOptions { 'jstype'?: (_google_protobuf_FieldOptions_JSType | keyof typeof _google_protobuf_FieldOptions_JSType); 'weak'?: (boolean); 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; - '.validate.rules'?: (_validate_FieldRules); + '.validate.rules'?: (_validate_FieldRules | null); + '.udpa.annotations.security'?: (_udpa_annotations_FieldSecurityAnnotation | null); '.udpa.annotations.sensitive'?: (boolean); - '.udpa.annotations.field_migrate'?: (_udpa_annotations_FieldMigrateAnnotation); + '.envoy.annotations.deprecated_at_minor_version'?: (string); + '.udpa.annotations.field_migrate'?: (_udpa_annotations_FieldMigrateAnnotation | null); '.envoy.annotations.disallowed_by_default'?: (boolean); + '.xds.annotations.v3.field_status'?: (_xds_annotations_v3_FieldStatusAnnotation | null); } export interface FieldOptions__Output { @@ -42,8 +47,11 @@ export interface FieldOptions__Output { 'jstype': (keyof typeof _google_protobuf_FieldOptions_JSType); 'weak': (boolean); 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; - '.validate.rules'?: (_validate_FieldRules__Output); + '.validate.rules': (_validate_FieldRules__Output | null); + '.udpa.annotations.security': (_udpa_annotations_FieldSecurityAnnotation__Output | null); '.udpa.annotations.sensitive': (boolean); - '.udpa.annotations.field_migrate'?: (_udpa_annotations_FieldMigrateAnnotation__Output); + '.envoy.annotations.deprecated_at_minor_version': (string); + '.udpa.annotations.field_migrate': (_udpa_annotations_FieldMigrateAnnotation__Output | null); '.envoy.annotations.disallowed_by_default': (boolean); + '.xds.annotations.v3.field_status': (_xds_annotations_v3_FieldStatusAnnotation__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/FileDescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/FileDescriptorProto.ts index 2954e4208..b723da7c0 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/FileDescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/FileDescriptorProto.ts @@ -15,8 +15,8 @@ export interface FileDescriptorProto { 'enumType'?: (_google_protobuf_EnumDescriptorProto)[]; 'service'?: (_google_protobuf_ServiceDescriptorProto)[]; 'extension'?: (_google_protobuf_FieldDescriptorProto)[]; - 'options'?: (_google_protobuf_FileOptions); - 'sourceCodeInfo'?: (_google_protobuf_SourceCodeInfo); + 'options'?: (_google_protobuf_FileOptions | null); + 'sourceCodeInfo'?: (_google_protobuf_SourceCodeInfo | null); 'publicDependency'?: (number)[]; 'weakDependency'?: (number)[]; 'syntax'?: (string); @@ -30,8 +30,8 @@ export interface FileDescriptorProto__Output { 'enumType': (_google_protobuf_EnumDescriptorProto__Output)[]; 'service': (_google_protobuf_ServiceDescriptorProto__Output)[]; 'extension': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'options'?: (_google_protobuf_FileOptions__Output); - 'sourceCodeInfo'?: (_google_protobuf_SourceCodeInfo__Output); + 'options': (_google_protobuf_FileOptions__Output | null); + 'sourceCodeInfo': (_google_protobuf_SourceCodeInfo__Output | null); 'publicDependency': (number)[]; 'weakDependency': (number)[]; 'syntax': (string); diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/FileOptions.ts b/packages/grpc-js-xds/src/generated/google/protobuf/FileOptions.ts index b2ddbb374..48a376cd0 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/FileOptions.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/FileOptions.ts @@ -3,6 +3,7 @@ import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; import type { FileMigrateAnnotation as _udpa_annotations_FileMigrateAnnotation, FileMigrateAnnotation__Output as _udpa_annotations_FileMigrateAnnotation__Output } from '../../udpa/annotations/FileMigrateAnnotation'; import type { StatusAnnotation as _udpa_annotations_StatusAnnotation, StatusAnnotation__Output as _udpa_annotations_StatusAnnotation__Output } from '../../udpa/annotations/StatusAnnotation'; +import type { FileStatusAnnotation as _xds_annotations_v3_FileStatusAnnotation, FileStatusAnnotation__Output as _xds_annotations_v3_FileStatusAnnotation__Output } from '../../xds/annotations/v3/FileStatusAnnotation'; // Original file: null @@ -28,8 +29,9 @@ export interface FileOptions { 'objcClassPrefix'?: (string); 'csharpNamespace'?: (string); 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; - '.udpa.annotations.file_migrate'?: (_udpa_annotations_FileMigrateAnnotation); - '.udpa.annotations.file_status'?: (_udpa_annotations_StatusAnnotation); + '.udpa.annotations.file_migrate'?: (_udpa_annotations_FileMigrateAnnotation | null); + '.udpa.annotations.file_status'?: (_udpa_annotations_StatusAnnotation | null); + '.xds.annotations.v3.file_status'?: (_xds_annotations_v3_FileStatusAnnotation | null); } export interface FileOptions__Output { @@ -48,6 +50,7 @@ export interface FileOptions__Output { 'objcClassPrefix': (string); 'csharpNamespace': (string); 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; - '.udpa.annotations.file_migrate'?: (_udpa_annotations_FileMigrateAnnotation__Output); - '.udpa.annotations.file_status'?: (_udpa_annotations_StatusAnnotation__Output); + '.udpa.annotations.file_migrate': (_udpa_annotations_FileMigrateAnnotation__Output | null); + '.udpa.annotations.file_status': (_udpa_annotations_StatusAnnotation__Output | null); + '.xds.annotations.v3.file_status': (_xds_annotations_v3_FileStatusAnnotation__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/FloatValue.ts b/packages/grpc-js-xds/src/generated/google/protobuf/FloatValue.ts index 144a9a585..54a655fbb 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/FloatValue.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/FloatValue.ts @@ -6,5 +6,5 @@ export interface FloatValue { } export interface FloatValue__Output { - 'value': (number | string); + 'value': (number); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/MessageOptions.ts b/packages/grpc-js-xds/src/generated/google/protobuf/MessageOptions.ts index 7560daa28..71d8c855b 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/MessageOptions.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/MessageOptions.ts @@ -1,7 +1,9 @@ // Original file: null import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { VersioningAnnotation as _udpa_annotations_VersioningAnnotation, VersioningAnnotation__Output as _udpa_annotations_VersioningAnnotation__Output } from '../../udpa/annotations/VersioningAnnotation'; import type { MigrateAnnotation as _udpa_annotations_MigrateAnnotation, MigrateAnnotation__Output as _udpa_annotations_MigrateAnnotation__Output } from '../../udpa/annotations/MigrateAnnotation'; +import type { MessageStatusAnnotation as _xds_annotations_v3_MessageStatusAnnotation, MessageStatusAnnotation__Output as _xds_annotations_v3_MessageStatusAnnotation__Output } from '../../xds/annotations/v3/MessageStatusAnnotation'; export interface MessageOptions { 'messageSetWireFormat'?: (boolean); @@ -10,7 +12,9 @@ export interface MessageOptions { 'mapEntry'?: (boolean); 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; '.validate.disabled'?: (boolean); - '.udpa.annotations.message_migrate'?: (_udpa_annotations_MigrateAnnotation); + '.udpa.annotations.versioning'?: (_udpa_annotations_VersioningAnnotation | null); + '.udpa.annotations.message_migrate'?: (_udpa_annotations_MigrateAnnotation | null); + '.xds.annotations.v3.message_status'?: (_xds_annotations_v3_MessageStatusAnnotation | null); } export interface MessageOptions__Output { @@ -20,5 +24,7 @@ export interface MessageOptions__Output { 'mapEntry': (boolean); 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; '.validate.disabled': (boolean); - '.udpa.annotations.message_migrate'?: (_udpa_annotations_MigrateAnnotation__Output); + '.udpa.annotations.versioning': (_udpa_annotations_VersioningAnnotation__Output | null); + '.udpa.annotations.message_migrate': (_udpa_annotations_MigrateAnnotation__Output | null); + '.xds.annotations.v3.message_status': (_xds_annotations_v3_MessageStatusAnnotation__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/MethodDescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/MethodDescriptorProto.ts index bc2f0afb5..c76c0ea23 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/MethodDescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/MethodDescriptorProto.ts @@ -6,7 +6,7 @@ export interface MethodDescriptorProto { 'name'?: (string); 'inputType'?: (string); 'outputType'?: (string); - 'options'?: (_google_protobuf_MethodOptions); + 'options'?: (_google_protobuf_MethodOptions | null); 'clientStreaming'?: (boolean); 'serverStreaming'?: (boolean); } @@ -15,7 +15,7 @@ export interface MethodDescriptorProto__Output { 'name': (string); 'inputType': (string); 'outputType': (string); - 'options'?: (_google_protobuf_MethodOptions__Output); + 'options': (_google_protobuf_MethodOptions__Output | null); 'clientStreaming': (boolean); 'serverStreaming': (boolean); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/MethodOptions.ts b/packages/grpc-js-xds/src/generated/google/protobuf/MethodOptions.ts index e47fd756c..5f81f0dd9 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/MethodOptions.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/MethodOptions.ts @@ -1,13 +1,16 @@ // Original file: null import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; export interface MethodOptions { 'deprecated'?: (boolean); 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + '.google.api.http'?: (_google_api_HttpRule | null); } export interface MethodOptions__Output { 'deprecated': (boolean); 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + '.google.api.http': (_google_api_HttpRule__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/OneofDescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/OneofDescriptorProto.ts index c10ccecd3..636f13ed4 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/OneofDescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/OneofDescriptorProto.ts @@ -4,10 +4,10 @@ import type { OneofOptions as _google_protobuf_OneofOptions, OneofOptions__Outpu export interface OneofDescriptorProto { 'name'?: (string); - 'options'?: (_google_protobuf_OneofOptions); + 'options'?: (_google_protobuf_OneofOptions | null); } export interface OneofDescriptorProto__Output { 'name': (string); - 'options'?: (_google_protobuf_OneofOptions__Output); + 'options': (_google_protobuf_OneofOptions__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/ServiceDescriptorProto.ts b/packages/grpc-js-xds/src/generated/google/protobuf/ServiceDescriptorProto.ts index 695a8775c..40c9263ea 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/ServiceDescriptorProto.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/ServiceDescriptorProto.ts @@ -6,11 +6,11 @@ import type { ServiceOptions as _google_protobuf_ServiceOptions, ServiceOptions_ export interface ServiceDescriptorProto { 'name'?: (string); 'method'?: (_google_protobuf_MethodDescriptorProto)[]; - 'options'?: (_google_protobuf_ServiceOptions); + 'options'?: (_google_protobuf_ServiceOptions | null); } export interface ServiceDescriptorProto__Output { 'name': (string); 'method': (_google_protobuf_MethodDescriptorProto__Output)[]; - 'options'?: (_google_protobuf_ServiceOptions__Output); + 'options': (_google_protobuf_ServiceOptions__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/Struct.ts b/packages/grpc-js-xds/src/generated/google/protobuf/Struct.ts index 9919350e4..41b79eab3 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/Struct.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/Struct.ts @@ -7,5 +7,5 @@ export interface Struct { } export interface Struct__Output { - 'fields'?: ({[key: string]: _google_protobuf_Value__Output}); + 'fields': ({[key: string]: _google_protobuf_Value__Output}); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/UninterpretedOption.ts b/packages/grpc-js-xds/src/generated/google/protobuf/UninterpretedOption.ts index 433820f55..6e9fc275b 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/UninterpretedOption.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/UninterpretedOption.ts @@ -27,7 +27,7 @@ export interface UninterpretedOption__Output { 'identifierValue': (string); 'positiveIntValue': (string); 'negativeIntValue': (string); - 'doubleValue': (number | string); + 'doubleValue': (number); 'stringValue': (Buffer); 'aggregateValue': (string); } diff --git a/packages/grpc-js-xds/src/generated/google/protobuf/Value.ts b/packages/grpc-js-xds/src/generated/google/protobuf/Value.ts index 68b665dcb..b1a942a56 100644 --- a/packages/grpc-js-xds/src/generated/google/protobuf/Value.ts +++ b/packages/grpc-js-xds/src/generated/google/protobuf/Value.ts @@ -9,17 +9,17 @@ export interface Value { 'numberValue'?: (number | string); 'stringValue'?: (string); 'boolValue'?: (boolean); - 'structValue'?: (_google_protobuf_Struct); - 'listValue'?: (_google_protobuf_ListValue); + 'structValue'?: (_google_protobuf_Struct | null); + 'listValue'?: (_google_protobuf_ListValue | null); 'kind'?: "nullValue"|"numberValue"|"stringValue"|"boolValue"|"structValue"|"listValue"; } export interface Value__Output { 'nullValue'?: (keyof typeof _google_protobuf_NullValue); - 'numberValue'?: (number | string); + 'numberValue'?: (number); 'stringValue'?: (string); 'boolValue'?: (boolean); - 'structValue'?: (_google_protobuf_Struct__Output); - 'listValue'?: (_google_protobuf_ListValue__Output); + 'structValue'?: (_google_protobuf_Struct__Output | null); + 'listValue'?: (_google_protobuf_ListValue__Output | null); 'kind': "nullValue"|"numberValue"|"stringValue"|"boolValue"|"structValue"|"listValue"; } diff --git a/packages/grpc-js-xds/src/generated/http_connection_manager.ts b/packages/grpc-js-xds/src/generated/http_connection_manager.ts index 7e822564d..137dcd45a 100644 --- a/packages/grpc-js-xds/src/generated/http_connection_manager.ts +++ b/packages/grpc-js-xds/src/generated/http_connection_manager.ts @@ -1,5 +1,5 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; type SubtypeConstructor any, Subtype> = { @@ -10,14 +10,31 @@ export interface ProtoGrpcType { envoy: { annotations: { } - api: { - v2: { - RouteConfiguration: MessageTypeDefinition - ScopedRouteConfiguration: MessageTypeDefinition - Vhds: MessageTypeDefinition - core: { + config: { + accesslog: { + v3: { + AccessLog: MessageTypeDefinition + AccessLogFilter: MessageTypeDefinition + AndFilter: MessageTypeDefinition + ComparisonFilter: MessageTypeDefinition + DurationFilter: MessageTypeDefinition + ExtensionFilter: MessageTypeDefinition + GrpcStatusFilter: MessageTypeDefinition + HeaderFilter: MessageTypeDefinition + MetadataFilter: MessageTypeDefinition + NotHealthCheckFilter: MessageTypeDefinition + OrFilter: MessageTypeDefinition + ResponseFlagFilter: MessageTypeDefinition + RuntimeFilter: MessageTypeDefinition + StatusCodeFilter: MessageTypeDefinition + TraceableFilter: MessageTypeDefinition + } + } + core: { + v3: { Address: MessageTypeDefinition AggregatedConfigSource: MessageTypeDefinition + AlternateProtocolsCacheOptions: MessageTypeDefinition ApiConfigSource: MessageTypeDefinition ApiVersion: EnumTypeDefinition AsyncDataSource: MessageTypeDefinition @@ -28,7 +45,9 @@ export interface ProtoGrpcType { ConfigSource: MessageTypeDefinition ControlPlane: MessageTypeDefinition DataSource: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition Extension: MessageTypeDefinition + ExtensionConfigSource: MessageTypeDefinition GrpcProtocolOptions: MessageTypeDefinition GrpcService: MessageTypeDefinition HeaderMap: MessageTypeDefinition @@ -36,12 +55,17 @@ export interface ProtoGrpcType { HeaderValueOption: MessageTypeDefinition Http1ProtocolOptions: MessageTypeDefinition Http2ProtocolOptions: MessageTypeDefinition + Http3ProtocolOptions: MessageTypeDefinition HttpProtocolOptions: MessageTypeDefinition HttpUri: MessageTypeDefinition + KeepaliveSettings: MessageTypeDefinition Locality: MessageTypeDefinition Metadata: MessageTypeDefinition Node: MessageTypeDefinition Pipe: MessageTypeDefinition + ProxyProtocolConfig: MessageTypeDefinition + QueryParameter: MessageTypeDefinition + QuicProtocolOptions: MessageTypeDefinition RateLimitSettings: MessageTypeDefinition RemoteDataSource: MessageTypeDefinition RequestMethod: EnumTypeDefinition @@ -50,64 +74,68 @@ export interface ProtoGrpcType { RuntimeDouble: MessageTypeDefinition RuntimeFeatureFlag: MessageTypeDefinition RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition RuntimeUInt32: MessageTypeDefinition + SchemeHeaderTransformation: MessageTypeDefinition SelfConfigSource: MessageTypeDefinition SocketAddress: MessageTypeDefinition SocketOption: MessageTypeDefinition + SubstitutionFormatString: MessageTypeDefinition TcpKeepalive: MessageTypeDefinition TcpProtocolOptions: MessageTypeDefinition TrafficDirection: EnumTypeDefinition TransportSocket: MessageTypeDefinition + TypedExtensionConfig: MessageTypeDefinition UpstreamHttpProtocolOptions: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition } - route: { + } + route: { + v3: { + ClusterSpecifierPlugin: MessageTypeDefinition CorsPolicy: MessageTypeDefinition Decorator: MessageTypeDefinition DirectResponseAction: MessageTypeDefinition FilterAction: MessageTypeDefinition + FilterConfig: MessageTypeDefinition HeaderMatcher: MessageTypeDefinition HedgePolicy: MessageTypeDefinition + InternalRedirectPolicy: MessageTypeDefinition + NonForwardingAction: MessageTypeDefinition QueryParameterMatcher: MessageTypeDefinition RateLimit: MessageTypeDefinition RedirectAction: MessageTypeDefinition RetryPolicy: MessageTypeDefinition Route: MessageTypeDefinition RouteAction: MessageTypeDefinition + RouteConfiguration: MessageTypeDefinition RouteMatch: MessageTypeDefinition + ScopedRouteConfiguration: MessageTypeDefinition Tracing: MessageTypeDefinition + Vhds: MessageTypeDefinition VirtualCluster: MessageTypeDefinition VirtualHost: MessageTypeDefinition WeightedCluster: MessageTypeDefinition } } - } - config: { - filter: { - accesslog: { - v2: { - AccessLog: MessageTypeDefinition - AccessLogFilter: MessageTypeDefinition - AndFilter: MessageTypeDefinition - ComparisonFilter: MessageTypeDefinition - DurationFilter: MessageTypeDefinition - ExtensionFilter: MessageTypeDefinition - GrpcStatusFilter: MessageTypeDefinition - HeaderFilter: MessageTypeDefinition - NotHealthCheckFilter: MessageTypeDefinition - OrFilter: MessageTypeDefinition - ResponseFlagFilter: MessageTypeDefinition - RuntimeFilter: MessageTypeDefinition - StatusCodeFilter: MessageTypeDefinition - TraceableFilter: MessageTypeDefinition - } + trace: { + v3: { + Tracing: MessageTypeDefinition } + } + } + extensions: { + filters: { network: { http_connection_manager: { - v2: { + v3: { + EnvoyMobileHttpConnectionManager: MessageTypeDefinition HttpConnectionManager: MessageTypeDefinition HttpFilter: MessageTypeDefinition + LocalReplyConfig: MessageTypeDefinition Rds: MessageTypeDefinition RequestIDExtension: MessageTypeDefinition + ResponseMapper: MessageTypeDefinition ScopedRds: MessageTypeDefinition ScopedRouteConfigurationsList: MessageTypeDefinition ScopedRoutes: MessageTypeDefinition @@ -115,36 +143,44 @@ export interface ProtoGrpcType { } } } - trace: { - v2: { - Tracing: MessageTypeDefinition - } - } } type: { - DoubleRange: MessageTypeDefinition - FractionalPercent: MessageTypeDefinition - Int32Range: MessageTypeDefinition - Int64Range: MessageTypeDefinition - Percent: MessageTypeDefinition - SemanticVersion: MessageTypeDefinition + http: { + v3: { + PathTransformation: MessageTypeDefinition + } + } matcher: { - ListStringMatcher: MessageTypeDefinition - RegexMatchAndSubstitute: MessageTypeDefinition - RegexMatcher: MessageTypeDefinition - StringMatcher: MessageTypeDefinition + v3: { + DoubleMatcher: MessageTypeDefinition + ListMatcher: MessageTypeDefinition + ListStringMatcher: MessageTypeDefinition + MetadataMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + ValueMatcher: MessageTypeDefinition + } } metadata: { - v2: { + v3: { MetadataKey: MessageTypeDefinition MetadataKind: MessageTypeDefinition } } tracing: { - v2: { + v3: { CustomTag: MessageTypeDefinition } } + v3: { + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + } } } google: { @@ -191,10 +227,12 @@ export interface ProtoGrpcType { udpa: { annotations: { FieldMigrateAnnotation: MessageTypeDefinition + FieldSecurityAnnotation: MessageTypeDefinition FileMigrateAnnotation: MessageTypeDefinition MigrateAnnotation: MessageTypeDefinition PackageVersionStatus: EnumTypeDefinition StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition } } validate: { @@ -223,5 +261,22 @@ export interface ProtoGrpcType { UInt32Rules: MessageTypeDefinition UInt64Rules: MessageTypeDefinition } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + Authority: MessageTypeDefinition + ContextParams: MessageTypeDefinition + } + } + } } diff --git a/packages/grpc-js-xds/src/generated/listener.ts b/packages/grpc-js-xds/src/generated/listener.ts index ab67cd096..b92353ab1 100644 --- a/packages/grpc-js-xds/src/generated/listener.ts +++ b/packages/grpc-js-xds/src/generated/listener.ts @@ -1,5 +1,5 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; type SubtypeConstructor any, Subtype> = { @@ -10,25 +10,31 @@ export interface ProtoGrpcType { envoy: { annotations: { } - api: { - v2: { - Listener: MessageTypeDefinition - auth: { - CertificateValidationContext: MessageTypeDefinition - CommonTlsContext: MessageTypeDefinition - DownstreamTlsContext: MessageTypeDefinition - GenericSecret: MessageTypeDefinition - PrivateKeyProvider: MessageTypeDefinition - SdsSecretConfig: MessageTypeDefinition - Secret: MessageTypeDefinition - TlsCertificate: MessageTypeDefinition - TlsParameters: MessageTypeDefinition - TlsSessionTicketKeys: MessageTypeDefinition - UpstreamTlsContext: MessageTypeDefinition + config: { + accesslog: { + v3: { + AccessLog: MessageTypeDefinition + AccessLogFilter: MessageTypeDefinition + AndFilter: MessageTypeDefinition + ComparisonFilter: MessageTypeDefinition + DurationFilter: MessageTypeDefinition + ExtensionFilter: MessageTypeDefinition + GrpcStatusFilter: MessageTypeDefinition + HeaderFilter: MessageTypeDefinition + MetadataFilter: MessageTypeDefinition + NotHealthCheckFilter: MessageTypeDefinition + OrFilter: MessageTypeDefinition + ResponseFlagFilter: MessageTypeDefinition + RuntimeFilter: MessageTypeDefinition + StatusCodeFilter: MessageTypeDefinition + TraceableFilter: MessageTypeDefinition } - core: { + } + core: { + v3: { Address: MessageTypeDefinition AggregatedConfigSource: MessageTypeDefinition + AlternateProtocolsCacheOptions: MessageTypeDefinition ApiConfigSource: MessageTypeDefinition ApiVersion: EnumTypeDefinition AsyncDataSource: MessageTypeDefinition @@ -39,16 +45,27 @@ export interface ProtoGrpcType { ConfigSource: MessageTypeDefinition ControlPlane: MessageTypeDefinition DataSource: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition Extension: MessageTypeDefinition + ExtensionConfigSource: MessageTypeDefinition + GrpcProtocolOptions: MessageTypeDefinition GrpcService: MessageTypeDefinition HeaderMap: MessageTypeDefinition HeaderValue: MessageTypeDefinition HeaderValueOption: MessageTypeDefinition + Http1ProtocolOptions: MessageTypeDefinition + Http2ProtocolOptions: MessageTypeDefinition + Http3ProtocolOptions: MessageTypeDefinition + HttpProtocolOptions: MessageTypeDefinition HttpUri: MessageTypeDefinition + KeepaliveSettings: MessageTypeDefinition Locality: MessageTypeDefinition Metadata: MessageTypeDefinition Node: MessageTypeDefinition Pipe: MessageTypeDefinition + ProxyProtocolConfig: MessageTypeDefinition + QueryParameter: MessageTypeDefinition + QuicProtocolOptions: MessageTypeDefinition RateLimitSettings: MessageTypeDefinition RemoteDataSource: MessageTypeDefinition RequestMethod: EnumTypeDefinition @@ -57,30 +74,48 @@ export interface ProtoGrpcType { RuntimeDouble: MessageTypeDefinition RuntimeFeatureFlag: MessageTypeDefinition RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition RuntimeUInt32: MessageTypeDefinition + SchemeHeaderTransformation: MessageTypeDefinition SelfConfigSource: MessageTypeDefinition SocketAddress: MessageTypeDefinition SocketOption: MessageTypeDefinition TcpKeepalive: MessageTypeDefinition + TcpProtocolOptions: MessageTypeDefinition TrafficDirection: EnumTypeDefinition TransportSocket: MessageTypeDefinition + TypedExtensionConfig: MessageTypeDefinition + UdpSocketConfig: MessageTypeDefinition + UpstreamHttpProtocolOptions: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition } - listener: { + } + listener: { + v3: { ActiveRawUdpListenerConfig: MessageTypeDefinition + ApiListener: MessageTypeDefinition Filter: MessageTypeDefinition FilterChain: MessageTypeDefinition FilterChainMatch: MessageTypeDefinition + Listener: MessageTypeDefinition + ListenerCollection: MessageTypeDefinition ListenerFilter: MessageTypeDefinition ListenerFilterChainMatchPredicate: MessageTypeDefinition + QuicProtocolOptions: MessageTypeDefinition UdpListenerConfig: MessageTypeDefinition } - route: { + } + route: { + v3: { CorsPolicy: MessageTypeDefinition Decorator: MessageTypeDefinition DirectResponseAction: MessageTypeDefinition FilterAction: MessageTypeDefinition + FilterConfig: MessageTypeDefinition HeaderMatcher: MessageTypeDefinition HedgePolicy: MessageTypeDefinition + InternalRedirectPolicy: MessageTypeDefinition + NonForwardingAction: MessageTypeDefinition QueryParameterMatcher: MessageTypeDefinition RateLimit: MessageTypeDefinition RedirectAction: MessageTypeDefinition @@ -95,65 +130,41 @@ export interface ProtoGrpcType { } } } - config: { - filter: { - accesslog: { - v2: { - AccessLog: MessageTypeDefinition - AccessLogFilter: MessageTypeDefinition - AndFilter: MessageTypeDefinition - ComparisonFilter: MessageTypeDefinition - DurationFilter: MessageTypeDefinition - ExtensionFilter: MessageTypeDefinition - GrpcStatusFilter: MessageTypeDefinition - HeaderFilter: MessageTypeDefinition - NotHealthCheckFilter: MessageTypeDefinition - OrFilter: MessageTypeDefinition - ResponseFlagFilter: MessageTypeDefinition - RuntimeFilter: MessageTypeDefinition - StatusCodeFilter: MessageTypeDefinition - TraceableFilter: MessageTypeDefinition - } - } - } - listener: { - v2: { - ApiListener: MessageTypeDefinition - } - } - } type: { - DoubleRange: MessageTypeDefinition - FractionalPercent: MessageTypeDefinition - Int32Range: MessageTypeDefinition - Int64Range: MessageTypeDefinition - Percent: MessageTypeDefinition - SemanticVersion: MessageTypeDefinition matcher: { - ListStringMatcher: MessageTypeDefinition - RegexMatchAndSubstitute: MessageTypeDefinition - RegexMatcher: MessageTypeDefinition - StringMatcher: MessageTypeDefinition + v3: { + DoubleMatcher: MessageTypeDefinition + ListMatcher: MessageTypeDefinition + ListStringMatcher: MessageTypeDefinition + MetadataMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + ValueMatcher: MessageTypeDefinition + } } metadata: { - v2: { + v3: { MetadataKey: MessageTypeDefinition MetadataKind: MessageTypeDefinition } } tracing: { - v2: { + v3: { CustomTag: MessageTypeDefinition } } + v3: { + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + } } } google: { - api: { - CustomHttpPattern: MessageTypeDefinition - Http: MessageTypeDefinition - HttpRule: MessageTypeDefinition - } protobuf: { Any: MessageTypeDefinition BoolValue: MessageTypeDefinition @@ -197,10 +208,12 @@ export interface ProtoGrpcType { udpa: { annotations: { FieldMigrateAnnotation: MessageTypeDefinition + FieldSecurityAnnotation: MessageTypeDefinition FileMigrateAnnotation: MessageTypeDefinition MigrateAnnotation: MessageTypeDefinition PackageVersionStatus: EnumTypeDefinition StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition } } validate: { @@ -229,5 +242,24 @@ export interface ProtoGrpcType { UInt32Rules: MessageTypeDefinition UInt64Rules: MessageTypeDefinition } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + Authority: MessageTypeDefinition + CollectionEntry: MessageTypeDefinition + ContextParams: MessageTypeDefinition + ResourceLocator: MessageTypeDefinition + } + } + } } diff --git a/packages/grpc-js-xds/src/generated/lrs.ts b/packages/grpc-js-xds/src/generated/lrs.ts index f3f180807..e57d6c249 100644 --- a/packages/grpc-js-xds/src/generated/lrs.ts +++ b/packages/grpc-js-xds/src/generated/lrs.ts @@ -1,7 +1,7 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; -import type { LoadReportingServiceClient as _envoy_service_load_stats_v2_LoadReportingServiceClient } from './envoy/service/load_stats/v2/LoadReportingService'; +import type { LoadReportingServiceClient as _envoy_service_load_stats_v3_LoadReportingServiceClient, LoadReportingServiceDefinition as _envoy_service_load_stats_v3_LoadReportingServiceDefinition } from './envoy/service/load_stats/v3/LoadReportingService'; type SubtypeConstructor any, Subtype> = { new(...args: ConstructorParameters): Subtype; @@ -9,9 +9,11 @@ type SubtypeConstructor any, Subtype> export interface ProtoGrpcType { envoy: { - api: { - v2: { - core: { + annotations: { + } + config: { + core: { + v3: { Address: MessageTypeDefinition AsyncDataSource: MessageTypeDefinition BackoffStrategy: MessageTypeDefinition @@ -20,6 +22,7 @@ export interface ProtoGrpcType { CidrRange: MessageTypeDefinition ControlPlane: MessageTypeDefinition DataSource: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition Extension: MessageTypeDefinition HeaderMap: MessageTypeDefinition HeaderValue: MessageTypeDefinition @@ -29,6 +32,7 @@ export interface ProtoGrpcType { Metadata: MessageTypeDefinition Node: MessageTypeDefinition Pipe: MessageTypeDefinition + QueryParameter: MessageTypeDefinition RemoteDataSource: MessageTypeDefinition RequestMethod: EnumTypeDefinition RetryPolicy: MessageTypeDefinition @@ -36,14 +40,18 @@ export interface ProtoGrpcType { RuntimeDouble: MessageTypeDefinition RuntimeFeatureFlag: MessageTypeDefinition RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition RuntimeUInt32: MessageTypeDefinition SocketAddress: MessageTypeDefinition SocketOption: MessageTypeDefinition TcpKeepalive: MessageTypeDefinition TrafficDirection: EnumTypeDefinition TransportSocket: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition } - endpoint: { + } + endpoint: { + v3: { ClusterStats: MessageTypeDefinition EndpointLoadMetricStats: MessageTypeDefinition UpstreamEndpointStats: MessageTypeDefinition @@ -53,17 +61,19 @@ export interface ProtoGrpcType { } service: { load_stats: { - v2: { - LoadReportingService: SubtypeConstructor & { service: ServiceDefinition } + v3: { + LoadReportingService: SubtypeConstructor & { service: _envoy_service_load_stats_v3_LoadReportingServiceDefinition } LoadStatsRequest: MessageTypeDefinition LoadStatsResponse: MessageTypeDefinition } } } type: { - FractionalPercent: MessageTypeDefinition - Percent: MessageTypeDefinition - SemanticVersion: MessageTypeDefinition + v3: { + FractionalPercent: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + } } } google: { @@ -113,6 +123,7 @@ export interface ProtoGrpcType { MigrateAnnotation: MessageTypeDefinition PackageVersionStatus: EnumTypeDefinition StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition } } validate: { @@ -141,5 +152,21 @@ export interface ProtoGrpcType { UInt32Rules: MessageTypeDefinition UInt64Rules: MessageTypeDefinition } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + ContextParams: MessageTypeDefinition + } + } + } } diff --git a/packages/grpc-js-xds/src/generated/route.ts b/packages/grpc-js-xds/src/generated/route.ts index 05332fe37..d6485bcd7 100644 --- a/packages/grpc-js-xds/src/generated/route.ts +++ b/packages/grpc-js-xds/src/generated/route.ts @@ -1,5 +1,5 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; type SubtypeConstructor any, Subtype> = { @@ -10,11 +10,9 @@ export interface ProtoGrpcType { envoy: { annotations: { } - api: { - v2: { - RouteConfiguration: MessageTypeDefinition - Vhds: MessageTypeDefinition - core: { + config: { + core: { + v3: { Address: MessageTypeDefinition AggregatedConfigSource: MessageTypeDefinition ApiConfigSource: MessageTypeDefinition @@ -27,7 +25,9 @@ export interface ProtoGrpcType { ConfigSource: MessageTypeDefinition ControlPlane: MessageTypeDefinition DataSource: MessageTypeDefinition + EnvoyInternalAddress: MessageTypeDefinition Extension: MessageTypeDefinition + ExtensionConfigSource: MessageTypeDefinition GrpcService: MessageTypeDefinition HeaderMap: MessageTypeDefinition HeaderValue: MessageTypeDefinition @@ -37,6 +37,8 @@ export interface ProtoGrpcType { Metadata: MessageTypeDefinition Node: MessageTypeDefinition Pipe: MessageTypeDefinition + ProxyProtocolConfig: MessageTypeDefinition + QueryParameter: MessageTypeDefinition RateLimitSettings: MessageTypeDefinition RemoteDataSource: MessageTypeDefinition RequestMethod: EnumTypeDefinition @@ -45,6 +47,7 @@ export interface ProtoGrpcType { RuntimeDouble: MessageTypeDefinition RuntimeFeatureFlag: MessageTypeDefinition RuntimeFractionalPercent: MessageTypeDefinition + RuntimePercent: MessageTypeDefinition RuntimeUInt32: MessageTypeDefinition SelfConfigSource: MessageTypeDefinition SocketAddress: MessageTypeDefinition @@ -52,22 +55,32 @@ export interface ProtoGrpcType { TcpKeepalive: MessageTypeDefinition TrafficDirection: EnumTypeDefinition TransportSocket: MessageTypeDefinition + TypedExtensionConfig: MessageTypeDefinition + WatchedDirectory: MessageTypeDefinition } - route: { + } + route: { + v3: { + ClusterSpecifierPlugin: MessageTypeDefinition CorsPolicy: MessageTypeDefinition Decorator: MessageTypeDefinition DirectResponseAction: MessageTypeDefinition FilterAction: MessageTypeDefinition + FilterConfig: MessageTypeDefinition HeaderMatcher: MessageTypeDefinition HedgePolicy: MessageTypeDefinition + InternalRedirectPolicy: MessageTypeDefinition + NonForwardingAction: MessageTypeDefinition QueryParameterMatcher: MessageTypeDefinition RateLimit: MessageTypeDefinition RedirectAction: MessageTypeDefinition RetryPolicy: MessageTypeDefinition Route: MessageTypeDefinition RouteAction: MessageTypeDefinition + RouteConfiguration: MessageTypeDefinition RouteMatch: MessageTypeDefinition Tracing: MessageTypeDefinition + Vhds: MessageTypeDefinition VirtualCluster: MessageTypeDefinition VirtualHost: MessageTypeDefinition WeightedCluster: MessageTypeDefinition @@ -75,29 +88,37 @@ export interface ProtoGrpcType { } } type: { - DoubleRange: MessageTypeDefinition - FractionalPercent: MessageTypeDefinition - Int32Range: MessageTypeDefinition - Int64Range: MessageTypeDefinition - Percent: MessageTypeDefinition - SemanticVersion: MessageTypeDefinition matcher: { - ListStringMatcher: MessageTypeDefinition - RegexMatchAndSubstitute: MessageTypeDefinition - RegexMatcher: MessageTypeDefinition - StringMatcher: MessageTypeDefinition + v3: { + DoubleMatcher: MessageTypeDefinition + ListMatcher: MessageTypeDefinition + ListStringMatcher: MessageTypeDefinition + MetadataMatcher: MessageTypeDefinition + RegexMatchAndSubstitute: MessageTypeDefinition + RegexMatcher: MessageTypeDefinition + StringMatcher: MessageTypeDefinition + ValueMatcher: MessageTypeDefinition + } } metadata: { - v2: { + v3: { MetadataKey: MessageTypeDefinition MetadataKind: MessageTypeDefinition } } tracing: { - v2: { + v3: { CustomTag: MessageTypeDefinition } } + v3: { + DoubleRange: MessageTypeDefinition + FractionalPercent: MessageTypeDefinition + Int32Range: MessageTypeDefinition + Int64Range: MessageTypeDefinition + Percent: MessageTypeDefinition + SemanticVersion: MessageTypeDefinition + } } } google: { @@ -148,6 +169,7 @@ export interface ProtoGrpcType { MigrateAnnotation: MessageTypeDefinition PackageVersionStatus: EnumTypeDefinition StatusAnnotation: MessageTypeDefinition + VersioningAnnotation: MessageTypeDefinition } } validate: { @@ -176,5 +198,22 @@ export interface ProtoGrpcType { UInt32Rules: MessageTypeDefinition UInt64Rules: MessageTypeDefinition } + xds: { + annotations: { + v3: { + FieldStatusAnnotation: MessageTypeDefinition + FileStatusAnnotation: MessageTypeDefinition + MessageStatusAnnotation: MessageTypeDefinition + PackageVersionStatus: EnumTypeDefinition + StatusAnnotation: MessageTypeDefinition + } + } + core: { + v3: { + Authority: MessageTypeDefinition + ContextParams: MessageTypeDefinition + } + } + } } diff --git a/packages/grpc-js-xds/src/generated/typed_struct.ts b/packages/grpc-js-xds/src/generated/typed_struct.ts new file mode 100644 index 000000000..e8dca13d5 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/typed_struct.ts @@ -0,0 +1,81 @@ +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + google: { + protobuf: { + DescriptorProto: MessageTypeDefinition + Duration: MessageTypeDefinition + EnumDescriptorProto: MessageTypeDefinition + EnumOptions: MessageTypeDefinition + EnumValueDescriptorProto: MessageTypeDefinition + EnumValueOptions: MessageTypeDefinition + FieldDescriptorProto: MessageTypeDefinition + FieldOptions: MessageTypeDefinition + FileDescriptorProto: MessageTypeDefinition + FileDescriptorSet: MessageTypeDefinition + FileOptions: MessageTypeDefinition + GeneratedCodeInfo: MessageTypeDefinition + ListValue: MessageTypeDefinition + MessageOptions: MessageTypeDefinition + MethodDescriptorProto: MessageTypeDefinition + MethodOptions: MessageTypeDefinition + NullValue: EnumTypeDefinition + OneofDescriptorProto: MessageTypeDefinition + OneofOptions: MessageTypeDefinition + ServiceDescriptorProto: MessageTypeDefinition + ServiceOptions: MessageTypeDefinition + SourceCodeInfo: MessageTypeDefinition + Struct: MessageTypeDefinition + Timestamp: MessageTypeDefinition + UninterpretedOption: MessageTypeDefinition + Value: MessageTypeDefinition + } + } + udpa: { + type: { + v1: { + TypedStruct: MessageTypeDefinition + } + } + } + validate: { + AnyRules: MessageTypeDefinition + BoolRules: MessageTypeDefinition + BytesRules: MessageTypeDefinition + DoubleRules: MessageTypeDefinition + DurationRules: MessageTypeDefinition + EnumRules: MessageTypeDefinition + FieldRules: MessageTypeDefinition + Fixed32Rules: MessageTypeDefinition + Fixed64Rules: MessageTypeDefinition + FloatRules: MessageTypeDefinition + Int32Rules: MessageTypeDefinition + Int64Rules: MessageTypeDefinition + KnownRegex: EnumTypeDefinition + MapRules: MessageTypeDefinition + MessageRules: MessageTypeDefinition + RepeatedRules: MessageTypeDefinition + SFixed32Rules: MessageTypeDefinition + SFixed64Rules: MessageTypeDefinition + SInt32Rules: MessageTypeDefinition + SInt64Rules: MessageTypeDefinition + StringRules: MessageTypeDefinition + TimestampRules: MessageTypeDefinition + UInt32Rules: MessageTypeDefinition + UInt64Rules: MessageTypeDefinition + } + xds: { + type: { + v3: { + TypedStruct: MessageTypeDefinition + } + } + } +} + diff --git a/packages/grpc-js-xds/src/generated/udpa/annotations/FieldMigrateAnnotation.ts b/packages/grpc-js-xds/src/generated/udpa/annotations/FieldMigrateAnnotation.ts index 1ad015b25..4cbe9fdcb 100644 --- a/packages/grpc-js-xds/src/generated/udpa/annotations/FieldMigrateAnnotation.ts +++ b/packages/grpc-js-xds/src/generated/udpa/annotations/FieldMigrateAnnotation.ts @@ -1,4 +1,4 @@ -// Original file: deps/udpa/udpa/annotations/migrate.proto +// Original file: deps/xds/udpa/annotations/migrate.proto export interface FieldMigrateAnnotation { diff --git a/packages/grpc-js-xds/src/generated/udpa/annotations/FieldSecurityAnnotation.ts b/packages/grpc-js-xds/src/generated/udpa/annotations/FieldSecurityAnnotation.ts new file mode 100644 index 000000000..9c25fb84e --- /dev/null +++ b/packages/grpc-js-xds/src/generated/udpa/annotations/FieldSecurityAnnotation.ts @@ -0,0 +1,32 @@ +// Original file: deps/xds/udpa/annotations/security.proto + + +/** + * These annotations indicate metadata for the purpose of understanding the + * security significance of fields. + */ +export interface FieldSecurityAnnotation { + /** + * Field should be set in the presence of untrusted downstreams. + */ + 'configure_for_untrusted_downstream'?: (boolean); + /** + * Field should be set in the presence of untrusted upstreams. + */ + 'configure_for_untrusted_upstream'?: (boolean); +} + +/** + * These annotations indicate metadata for the purpose of understanding the + * security significance of fields. + */ +export interface FieldSecurityAnnotation__Output { + /** + * Field should be set in the presence of untrusted downstreams. + */ + 'configure_for_untrusted_downstream': (boolean); + /** + * Field should be set in the presence of untrusted upstreams. + */ + 'configure_for_untrusted_upstream': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/udpa/annotations/FileMigrateAnnotation.ts b/packages/grpc-js-xds/src/generated/udpa/annotations/FileMigrateAnnotation.ts index b7ef7c21d..95d29245d 100644 --- a/packages/grpc-js-xds/src/generated/udpa/annotations/FileMigrateAnnotation.ts +++ b/packages/grpc-js-xds/src/generated/udpa/annotations/FileMigrateAnnotation.ts @@ -1,4 +1,4 @@ -// Original file: deps/udpa/udpa/annotations/migrate.proto +// Original file: deps/xds/udpa/annotations/migrate.proto export interface FileMigrateAnnotation { diff --git a/packages/grpc-js-xds/src/generated/udpa/annotations/MigrateAnnotation.ts b/packages/grpc-js-xds/src/generated/udpa/annotations/MigrateAnnotation.ts index e3fdcaa99..16def9f28 100644 --- a/packages/grpc-js-xds/src/generated/udpa/annotations/MigrateAnnotation.ts +++ b/packages/grpc-js-xds/src/generated/udpa/annotations/MigrateAnnotation.ts @@ -1,4 +1,4 @@ -// Original file: deps/udpa/udpa/annotations/migrate.proto +// Original file: deps/xds/udpa/annotations/migrate.proto export interface MigrateAnnotation { diff --git a/packages/grpc-js-xds/src/generated/udpa/annotations/PackageVersionStatus.ts b/packages/grpc-js-xds/src/generated/udpa/annotations/PackageVersionStatus.ts index c60c3f984..d0e181aa5 100644 --- a/packages/grpc-js-xds/src/generated/udpa/annotations/PackageVersionStatus.ts +++ b/packages/grpc-js-xds/src/generated/udpa/annotations/PackageVersionStatus.ts @@ -1,4 +1,4 @@ -// Original file: deps/udpa/udpa/annotations/status.proto +// Original file: deps/xds/udpa/annotations/status.proto export enum PackageVersionStatus { /** diff --git a/packages/grpc-js-xds/src/generated/udpa/annotations/StatusAnnotation.ts b/packages/grpc-js-xds/src/generated/udpa/annotations/StatusAnnotation.ts index 7b33ce9c8..f01b45063 100644 --- a/packages/grpc-js-xds/src/generated/udpa/annotations/StatusAnnotation.ts +++ b/packages/grpc-js-xds/src/generated/udpa/annotations/StatusAnnotation.ts @@ -1,4 +1,4 @@ -// Original file: deps/udpa/udpa/annotations/status.proto +// Original file: deps/xds/udpa/annotations/status.proto import type { PackageVersionStatus as _udpa_annotations_PackageVersionStatus } from '../../udpa/annotations/PackageVersionStatus'; diff --git a/packages/grpc-js-xds/src/generated/udpa/annotations/VersioningAnnotation.ts b/packages/grpc-js-xds/src/generated/udpa/annotations/VersioningAnnotation.ts new file mode 100644 index 000000000..7a517a06c --- /dev/null +++ b/packages/grpc-js-xds/src/generated/udpa/annotations/VersioningAnnotation.ts @@ -0,0 +1,20 @@ +// Original file: deps/xds/udpa/annotations/versioning.proto + + +export interface VersioningAnnotation { + /** + * Track the previous message type. E.g. this message might be + * udpa.foo.v3alpha.Foo and it was previously udpa.bar.v2.Bar. This + * information is consumed by UDPA via proto descriptors. + */ + 'previous_message_type'?: (string); +} + +export interface VersioningAnnotation__Output { + /** + * Track the previous message type. E.g. this message might be + * udpa.foo.v3alpha.Foo and it was previously udpa.bar.v2.Bar. This + * information is consumed by UDPA via proto descriptors. + */ + 'previous_message_type': (string); +} diff --git a/packages/grpc-js-xds/src/generated/udpa/type/v1/TypedStruct.ts b/packages/grpc-js-xds/src/generated/udpa/type/v1/TypedStruct.ts new file mode 100644 index 000000000..b080c6348 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/udpa/type/v1/TypedStruct.ts @@ -0,0 +1,77 @@ +// Original file: deps/xds/udpa/type/v1/typed_struct.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../google/protobuf/Struct'; + +/** + * A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that + * describes the type of the serialized message. This is very similar to google.protobuf.Any, + * instead of having protocol buffer binary, this employs google.protobuf.Struct as value. + * + * This message is intended to be embedded inside Any, so it shouldn't be directly referred + * from other UDPA messages. + * + * When packing an opaque extension config, packing the expected type into Any is preferred + * wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor + * is not available, for example if: + * - A control plane sends opaque message that is originally from external source in human readable + * format such as JSON or YAML. + * - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot + * serialize the message in protocol buffer binary format. + * - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension + * uses. This has to be indicated in the DPLB capability negotiation. + * + * When a DPLB receives a TypedStruct in Any, it should: + * - Check if the type_url of the TypedStruct matches the type the extension expects. + * - Convert value to the type described in type_url and perform validation. + * TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link + * protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). + */ +export interface TypedStruct { + /** + * A URL that uniquely identifies the type of the serialize protocol buffer message. + * This has same semantics and format described in google.protobuf.Any: + * https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto + */ + 'type_url'?: (string); + /** + * A JSON representation of the above specified type. + */ + 'value'?: (_google_protobuf_Struct | null); +} + +/** + * A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that + * describes the type of the serialized message. This is very similar to google.protobuf.Any, + * instead of having protocol buffer binary, this employs google.protobuf.Struct as value. + * + * This message is intended to be embedded inside Any, so it shouldn't be directly referred + * from other UDPA messages. + * + * When packing an opaque extension config, packing the expected type into Any is preferred + * wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor + * is not available, for example if: + * - A control plane sends opaque message that is originally from external source in human readable + * format such as JSON or YAML. + * - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot + * serialize the message in protocol buffer binary format. + * - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension + * uses. This has to be indicated in the DPLB capability negotiation. + * + * When a DPLB receives a TypedStruct in Any, it should: + * - Check if the type_url of the TypedStruct matches the type the extension expects. + * - Convert value to the type described in type_url and perform validation. + * TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link + * protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). + */ +export interface TypedStruct__Output { + /** + * A URL that uniquely identifies the type of the serialize protocol buffer message. + * This has same semantics and format described in google.protobuf.Any: + * https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto + */ + 'type_url': (string); + /** + * A JSON representation of the above specified type. + */ + 'value': (_google_protobuf_Struct__Output | null); +} diff --git a/packages/grpc-js-xds/src/generated/validate/DoubleRules.ts b/packages/grpc-js-xds/src/generated/validate/DoubleRules.ts index fead5072a..e756c86b9 100644 --- a/packages/grpc-js-xds/src/generated/validate/DoubleRules.ts +++ b/packages/grpc-js-xds/src/generated/validate/DoubleRules.ts @@ -50,37 +50,37 @@ export interface DoubleRules__Output { /** * Const specifies that this field must be exactly the specified value */ - 'const': (number | string); + 'const': (number); /** * Lt specifies that this field must be less than the specified value, * exclusive */ - 'lt': (number | string); + 'lt': (number); /** * Lte specifies that this field must be less than or equal to the * specified value, inclusive */ - 'lte': (number | string); + 'lte': (number); /** * Gt specifies that this field must be greater than the specified value, * exclusive. If the value of Gt is larger than a specified Lt or Lte, the * range is reversed. */ - 'gt': (number | string); + 'gt': (number); /** * Gte specifies that this field must be greater than or equal to the * specified value, inclusive. If the value of Gte is larger than a * specified Lt or Lte, the range is reversed. */ - 'gte': (number | string); + 'gte': (number); /** * In specifies that this field must be equal to one of the specified * values */ - 'in': (number | string)[]; + 'in': (number)[]; /** * NotIn specifies that this field cannot be equal to one of the specified * values */ - 'not_in': (number | string)[]; + 'not_in': (number)[]; } diff --git a/packages/grpc-js-xds/src/generated/validate/DurationRules.ts b/packages/grpc-js-xds/src/generated/validate/DurationRules.ts index 86b80a34d..879928e20 100644 --- a/packages/grpc-js-xds/src/generated/validate/DurationRules.ts +++ b/packages/grpc-js-xds/src/generated/validate/DurationRules.ts @@ -14,27 +14,27 @@ export interface DurationRules { /** * Const specifies that this field must be exactly the specified value */ - 'const'?: (_google_protobuf_Duration); + 'const'?: (_google_protobuf_Duration | null); /** * Lt specifies that this field must be less than the specified value, * exclusive */ - 'lt'?: (_google_protobuf_Duration); + 'lt'?: (_google_protobuf_Duration | null); /** * Lt specifies that this field must be less than the specified value, * inclusive */ - 'lte'?: (_google_protobuf_Duration); + 'lte'?: (_google_protobuf_Duration | null); /** * Gt specifies that this field must be greater than the specified value, * exclusive */ - 'gt'?: (_google_protobuf_Duration); + 'gt'?: (_google_protobuf_Duration | null); /** * Gte specifies that this field must be greater than the specified value, * inclusive */ - 'gte'?: (_google_protobuf_Duration); + 'gte'?: (_google_protobuf_Duration | null); /** * In specifies that this field must be equal to one of the specified * values @@ -59,27 +59,27 @@ export interface DurationRules__Output { /** * Const specifies that this field must be exactly the specified value */ - 'const'?: (_google_protobuf_Duration__Output); + 'const': (_google_protobuf_Duration__Output | null); /** * Lt specifies that this field must be less than the specified value, * exclusive */ - 'lt'?: (_google_protobuf_Duration__Output); + 'lt': (_google_protobuf_Duration__Output | null); /** * Lt specifies that this field must be less than the specified value, * inclusive */ - 'lte'?: (_google_protobuf_Duration__Output); + 'lte': (_google_protobuf_Duration__Output | null); /** * Gt specifies that this field must be greater than the specified value, * exclusive */ - 'gt'?: (_google_protobuf_Duration__Output); + 'gt': (_google_protobuf_Duration__Output | null); /** * Gte specifies that this field must be greater than the specified value, * inclusive */ - 'gte'?: (_google_protobuf_Duration__Output); + 'gte': (_google_protobuf_Duration__Output | null); /** * In specifies that this field must be equal to one of the specified * values diff --git a/packages/grpc-js-xds/src/generated/validate/FieldRules.ts b/packages/grpc-js-xds/src/generated/validate/FieldRules.ts index dae124bc1..067125775 100644 --- a/packages/grpc-js-xds/src/generated/validate/FieldRules.ts +++ b/packages/grpc-js-xds/src/generated/validate/FieldRules.ts @@ -32,34 +32,34 @@ export interface FieldRules { /** * Scalar Field Types */ - 'float'?: (_validate_FloatRules); - 'double'?: (_validate_DoubleRules); - 'int32'?: (_validate_Int32Rules); - 'int64'?: (_validate_Int64Rules); - 'uint32'?: (_validate_UInt32Rules); - 'uint64'?: (_validate_UInt64Rules); - 'sint32'?: (_validate_SInt32Rules); - 'sint64'?: (_validate_SInt64Rules); - 'fixed32'?: (_validate_Fixed32Rules); - 'fixed64'?: (_validate_Fixed64Rules); - 'sfixed32'?: (_validate_SFixed32Rules); - 'sfixed64'?: (_validate_SFixed64Rules); - 'bool'?: (_validate_BoolRules); - 'string'?: (_validate_StringRules); - 'bytes'?: (_validate_BytesRules); + 'float'?: (_validate_FloatRules | null); + 'double'?: (_validate_DoubleRules | null); + 'int32'?: (_validate_Int32Rules | null); + 'int64'?: (_validate_Int64Rules | null); + 'uint32'?: (_validate_UInt32Rules | null); + 'uint64'?: (_validate_UInt64Rules | null); + 'sint32'?: (_validate_SInt32Rules | null); + 'sint64'?: (_validate_SInt64Rules | null); + 'fixed32'?: (_validate_Fixed32Rules | null); + 'fixed64'?: (_validate_Fixed64Rules | null); + 'sfixed32'?: (_validate_SFixed32Rules | null); + 'sfixed64'?: (_validate_SFixed64Rules | null); + 'bool'?: (_validate_BoolRules | null); + 'string'?: (_validate_StringRules | null); + 'bytes'?: (_validate_BytesRules | null); /** * Complex Field Types */ - 'enum'?: (_validate_EnumRules); - 'message'?: (_validate_MessageRules); - 'repeated'?: (_validate_RepeatedRules); - 'map'?: (_validate_MapRules); + 'enum'?: (_validate_EnumRules | null); + 'message'?: (_validate_MessageRules | null); + 'repeated'?: (_validate_RepeatedRules | null); + 'map'?: (_validate_MapRules | null); /** * Well-Known Field Types */ - 'any'?: (_validate_AnyRules); - 'duration'?: (_validate_DurationRules); - 'timestamp'?: (_validate_TimestampRules); + 'any'?: (_validate_AnyRules | null); + 'duration'?: (_validate_DurationRules | null); + 'timestamp'?: (_validate_TimestampRules | null); 'type'?: "float"|"double"|"int32"|"int64"|"uint32"|"uint64"|"sint32"|"sint64"|"fixed32"|"fixed64"|"sfixed32"|"sfixed64"|"bool"|"string"|"bytes"|"enum"|"repeated"|"map"|"any"|"duration"|"timestamp"; } @@ -71,33 +71,33 @@ export interface FieldRules__Output { /** * Scalar Field Types */ - 'float'?: (_validate_FloatRules__Output); - 'double'?: (_validate_DoubleRules__Output); - 'int32'?: (_validate_Int32Rules__Output); - 'int64'?: (_validate_Int64Rules__Output); - 'uint32'?: (_validate_UInt32Rules__Output); - 'uint64'?: (_validate_UInt64Rules__Output); - 'sint32'?: (_validate_SInt32Rules__Output); - 'sint64'?: (_validate_SInt64Rules__Output); - 'fixed32'?: (_validate_Fixed32Rules__Output); - 'fixed64'?: (_validate_Fixed64Rules__Output); - 'sfixed32'?: (_validate_SFixed32Rules__Output); - 'sfixed64'?: (_validate_SFixed64Rules__Output); - 'bool'?: (_validate_BoolRules__Output); - 'string'?: (_validate_StringRules__Output); - 'bytes'?: (_validate_BytesRules__Output); + 'float'?: (_validate_FloatRules__Output | null); + 'double'?: (_validate_DoubleRules__Output | null); + 'int32'?: (_validate_Int32Rules__Output | null); + 'int64'?: (_validate_Int64Rules__Output | null); + 'uint32'?: (_validate_UInt32Rules__Output | null); + 'uint64'?: (_validate_UInt64Rules__Output | null); + 'sint32'?: (_validate_SInt32Rules__Output | null); + 'sint64'?: (_validate_SInt64Rules__Output | null); + 'fixed32'?: (_validate_Fixed32Rules__Output | null); + 'fixed64'?: (_validate_Fixed64Rules__Output | null); + 'sfixed32'?: (_validate_SFixed32Rules__Output | null); + 'sfixed64'?: (_validate_SFixed64Rules__Output | null); + 'bool'?: (_validate_BoolRules__Output | null); + 'string'?: (_validate_StringRules__Output | null); + 'bytes'?: (_validate_BytesRules__Output | null); /** * Complex Field Types */ - 'enum'?: (_validate_EnumRules__Output); - 'message'?: (_validate_MessageRules__Output); - 'repeated'?: (_validate_RepeatedRules__Output); - 'map'?: (_validate_MapRules__Output); + 'enum'?: (_validate_EnumRules__Output | null); + 'message': (_validate_MessageRules__Output | null); + 'repeated'?: (_validate_RepeatedRules__Output | null); + 'map'?: (_validate_MapRules__Output | null); /** * Well-Known Field Types */ - 'any'?: (_validate_AnyRules__Output); - 'duration'?: (_validate_DurationRules__Output); - 'timestamp'?: (_validate_TimestampRules__Output); + 'any'?: (_validate_AnyRules__Output | null); + 'duration'?: (_validate_DurationRules__Output | null); + 'timestamp'?: (_validate_TimestampRules__Output | null); 'type': "float"|"double"|"int32"|"int64"|"uint32"|"uint64"|"sint32"|"sint64"|"fixed32"|"fixed64"|"sfixed32"|"sfixed64"|"bool"|"string"|"bytes"|"enum"|"repeated"|"map"|"any"|"duration"|"timestamp"; } diff --git a/packages/grpc-js-xds/src/generated/validate/FloatRules.ts b/packages/grpc-js-xds/src/generated/validate/FloatRules.ts index 35aafa809..8d5244c2b 100644 --- a/packages/grpc-js-xds/src/generated/validate/FloatRules.ts +++ b/packages/grpc-js-xds/src/generated/validate/FloatRules.ts @@ -50,37 +50,37 @@ export interface FloatRules__Output { /** * Const specifies that this field must be exactly the specified value */ - 'const': (number | string); + 'const': (number); /** * Lt specifies that this field must be less than the specified value, * exclusive */ - 'lt': (number | string); + 'lt': (number); /** * Lte specifies that this field must be less than or equal to the * specified value, inclusive */ - 'lte': (number | string); + 'lte': (number); /** * Gt specifies that this field must be greater than the specified value, * exclusive. If the value of Gt is larger than a specified Lt or Lte, the * range is reversed. */ - 'gt': (number | string); + 'gt': (number); /** * Gte specifies that this field must be greater than or equal to the * specified value, inclusive. If the value of Gte is larger than a * specified Lt or Lte, the range is reversed. */ - 'gte': (number | string); + 'gte': (number); /** * In specifies that this field must be equal to one of the specified * values */ - 'in': (number | string)[]; + 'in': (number)[]; /** * NotIn specifies that this field cannot be equal to one of the specified * values */ - 'not_in': (number | string)[]; + 'not_in': (number)[]; } diff --git a/packages/grpc-js-xds/src/generated/validate/MapRules.ts b/packages/grpc-js-xds/src/generated/validate/MapRules.ts index 0c89bf2b3..7efe5b390 100644 --- a/packages/grpc-js-xds/src/generated/validate/MapRules.ts +++ b/packages/grpc-js-xds/src/generated/validate/MapRules.ts @@ -25,13 +25,13 @@ export interface MapRules { /** * Keys specifies the constraints to be applied to each key in the field. */ - 'keys'?: (_validate_FieldRules); + 'keys'?: (_validate_FieldRules | null); /** * Values specifies the constraints to be applied to the value of each key * in the field. Message values will still have their validations evaluated * unless skip is specified here. */ - 'values'?: (_validate_FieldRules); + 'values'?: (_validate_FieldRules | null); } /** @@ -56,11 +56,11 @@ export interface MapRules__Output { /** * Keys specifies the constraints to be applied to each key in the field. */ - 'keys'?: (_validate_FieldRules__Output); + 'keys': (_validate_FieldRules__Output | null); /** * Values specifies the constraints to be applied to the value of each key * in the field. Message values will still have their validations evaluated * unless skip is specified here. */ - 'values'?: (_validate_FieldRules__Output); + 'values': (_validate_FieldRules__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/validate/RepeatedRules.ts b/packages/grpc-js-xds/src/generated/validate/RepeatedRules.ts index 1f6d4f0ff..d347b6497 100644 --- a/packages/grpc-js-xds/src/generated/validate/RepeatedRules.ts +++ b/packages/grpc-js-xds/src/generated/validate/RepeatedRules.ts @@ -28,7 +28,7 @@ export interface RepeatedRules { * Repeated message fields will still execute validation against each item * unless skip is specified here. */ - 'items'?: (_validate_FieldRules); + 'items'?: (_validate_FieldRules | null); } /** @@ -56,5 +56,5 @@ export interface RepeatedRules__Output { * Repeated message fields will still execute validation against each item * unless skip is specified here. */ - 'items'?: (_validate_FieldRules__Output); + 'items': (_validate_FieldRules__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/validate/TimestampRules.ts b/packages/grpc-js-xds/src/generated/validate/TimestampRules.ts index 9436cc8ee..69d548126 100644 --- a/packages/grpc-js-xds/src/generated/validate/TimestampRules.ts +++ b/packages/grpc-js-xds/src/generated/validate/TimestampRules.ts @@ -15,27 +15,27 @@ export interface TimestampRules { /** * Const specifies that this field must be exactly the specified value */ - 'const'?: (_google_protobuf_Timestamp); + 'const'?: (_google_protobuf_Timestamp | null); /** * Lt specifies that this field must be less than the specified value, * exclusive */ - 'lt'?: (_google_protobuf_Timestamp); + 'lt'?: (_google_protobuf_Timestamp | null); /** * Lte specifies that this field must be less than the specified value, * inclusive */ - 'lte'?: (_google_protobuf_Timestamp); + 'lte'?: (_google_protobuf_Timestamp | null); /** * Gt specifies that this field must be greater than the specified value, * exclusive */ - 'gt'?: (_google_protobuf_Timestamp); + 'gt'?: (_google_protobuf_Timestamp | null); /** * Gte specifies that this field must be greater than the specified value, * inclusive */ - 'gte'?: (_google_protobuf_Timestamp); + 'gte'?: (_google_protobuf_Timestamp | null); /** * LtNow specifies that this must be less than the current time. LtNow * can only be used with the Within rule. @@ -51,7 +51,7 @@ export interface TimestampRules { * current time. This constraint can be used alone or with the LtNow and * GtNow rules. */ - 'within'?: (_google_protobuf_Duration); + 'within'?: (_google_protobuf_Duration | null); } /** @@ -66,27 +66,27 @@ export interface TimestampRules__Output { /** * Const specifies that this field must be exactly the specified value */ - 'const'?: (_google_protobuf_Timestamp__Output); + 'const': (_google_protobuf_Timestamp__Output | null); /** * Lt specifies that this field must be less than the specified value, * exclusive */ - 'lt'?: (_google_protobuf_Timestamp__Output); + 'lt': (_google_protobuf_Timestamp__Output | null); /** * Lte specifies that this field must be less than the specified value, * inclusive */ - 'lte'?: (_google_protobuf_Timestamp__Output); + 'lte': (_google_protobuf_Timestamp__Output | null); /** * Gt specifies that this field must be greater than the specified value, * exclusive */ - 'gt'?: (_google_protobuf_Timestamp__Output); + 'gt': (_google_protobuf_Timestamp__Output | null); /** * Gte specifies that this field must be greater than the specified value, * inclusive */ - 'gte'?: (_google_protobuf_Timestamp__Output); + 'gte': (_google_protobuf_Timestamp__Output | null); /** * LtNow specifies that this must be less than the current time. LtNow * can only be used with the Within rule. @@ -102,5 +102,5 @@ export interface TimestampRules__Output { * current time. This constraint can be used alone or with the LtNow and * GtNow rules. */ - 'within'?: (_google_protobuf_Duration__Output); + 'within': (_google_protobuf_Duration__Output | null); } diff --git a/packages/grpc-js-xds/src/generated/xds/annotations/v3/FieldStatusAnnotation.ts b/packages/grpc-js-xds/src/generated/xds/annotations/v3/FieldStatusAnnotation.ts new file mode 100644 index 000000000..744e13837 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/annotations/v3/FieldStatusAnnotation.ts @@ -0,0 +1,16 @@ +// Original file: deps/xds/xds/annotations/v3/status.proto + + +export interface FieldStatusAnnotation { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress'?: (boolean); +} + +export interface FieldStatusAnnotation__Output { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/xds/annotations/v3/FileStatusAnnotation.ts b/packages/grpc-js-xds/src/generated/xds/annotations/v3/FileStatusAnnotation.ts new file mode 100644 index 000000000..cbc3ab3f9 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/annotations/v3/FileStatusAnnotation.ts @@ -0,0 +1,16 @@ +// Original file: deps/xds/xds/annotations/v3/status.proto + + +export interface FileStatusAnnotation { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress'?: (boolean); +} + +export interface FileStatusAnnotation__Output { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/xds/annotations/v3/MessageStatusAnnotation.ts b/packages/grpc-js-xds/src/generated/xds/annotations/v3/MessageStatusAnnotation.ts new file mode 100644 index 000000000..f403f6506 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/annotations/v3/MessageStatusAnnotation.ts @@ -0,0 +1,16 @@ +// Original file: deps/xds/xds/annotations/v3/status.proto + + +export interface MessageStatusAnnotation { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress'?: (boolean); +} + +export interface MessageStatusAnnotation__Output { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress': (boolean); +} diff --git a/packages/grpc-js-xds/src/generated/xds/annotations/v3/PackageVersionStatus.ts b/packages/grpc-js-xds/src/generated/xds/annotations/v3/PackageVersionStatus.ts new file mode 100644 index 000000000..e76e2848f --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/annotations/v3/PackageVersionStatus.ts @@ -0,0 +1,21 @@ +// Original file: deps/xds/xds/annotations/v3/status.proto + +export enum PackageVersionStatus { + /** + * Unknown package version status. + */ + UNKNOWN = 0, + /** + * This version of the package is frozen. + */ + FROZEN = 1, + /** + * This version of the package is the active development version. + */ + ACTIVE = 2, + /** + * This version of the package is the candidate for the next major version. It + * is typically machine generated from the active development version. + */ + NEXT_MAJOR_VERSION_CANDIDATE = 3, +} diff --git a/packages/grpc-js-xds/src/generated/xds/annotations/v3/StatusAnnotation.ts b/packages/grpc-js-xds/src/generated/xds/annotations/v3/StatusAnnotation.ts new file mode 100644 index 000000000..58efbd8f7 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/annotations/v3/StatusAnnotation.ts @@ -0,0 +1,25 @@ +// Original file: deps/xds/xds/annotations/v3/status.proto + +import type { PackageVersionStatus as _xds_annotations_v3_PackageVersionStatus } from '../../../xds/annotations/v3/PackageVersionStatus'; + +export interface StatusAnnotation { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress'?: (boolean); + /** + * The entity belongs to a package with the given version status. + */ + 'package_version_status'?: (_xds_annotations_v3_PackageVersionStatus | keyof typeof _xds_annotations_v3_PackageVersionStatus); +} + +export interface StatusAnnotation__Output { + /** + * The entity is work-in-progress and subject to breaking changes. + */ + 'work_in_progress': (boolean); + /** + * The entity belongs to a package with the given version status. + */ + 'package_version_status': (keyof typeof _xds_annotations_v3_PackageVersionStatus); +} diff --git a/packages/grpc-js-xds/src/generated/xds/core/v3/Authority.ts b/packages/grpc-js-xds/src/generated/xds/core/v3/Authority.ts new file mode 100644 index 000000000..9505731d7 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/core/v3/Authority.ts @@ -0,0 +1,16 @@ +// Original file: deps/xds/xds/core/v3/authority.proto + + +/** + * xDS authority information. + */ +export interface Authority { + 'name'?: (string); +} + +/** + * xDS authority information. + */ +export interface Authority__Output { + 'name': (string); +} diff --git a/packages/grpc-js-xds/src/generated/xds/core/v3/CollectionEntry.ts b/packages/grpc-js-xds/src/generated/xds/core/v3/CollectionEntry.ts new file mode 100644 index 000000000..5d2ce9721 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/core/v3/CollectionEntry.ts @@ -0,0 +1,90 @@ +// Original file: deps/xds/xds/core/v3/collection_entry.proto + +import type { ResourceLocator as _xds_core_v3_ResourceLocator, ResourceLocator__Output as _xds_core_v3_ResourceLocator__Output } from '../../../xds/core/v3/ResourceLocator'; +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; + +/** + * Inlined resource entry. + */ +export interface _xds_core_v3_CollectionEntry_InlineEntry { + /** + * Optional name to describe the inlined resource. Resource names must + * [a-zA-Z0-9_-\./]+ (TODO(htuch): turn this into a PGV constraint once + * finalized, probably should be a RFC3986 pchar). This name allows + * reference via the #entry directive in ResourceLocator. + */ + 'name'?: (string); + /** + * The resource's logical version. It is illegal to have the same named xDS + * resource name at a given version with different resource payloads. + */ + 'version'?: (string); + /** + * The resource payload, including type URL. + */ + 'resource'?: (_google_protobuf_Any | null); +} + +/** + * Inlined resource entry. + */ +export interface _xds_core_v3_CollectionEntry_InlineEntry__Output { + /** + * Optional name to describe the inlined resource. Resource names must + * [a-zA-Z0-9_-\./]+ (TODO(htuch): turn this into a PGV constraint once + * finalized, probably should be a RFC3986 pchar). This name allows + * reference via the #entry directive in ResourceLocator. + */ + 'name': (string); + /** + * The resource's logical version. It is illegal to have the same named xDS + * resource name at a given version with different resource payloads. + */ + 'version': (string); + /** + * The resource payload, including type URL. + */ + 'resource': (_google_protobuf_Any__Output | null); +} + +/** + * xDS collection resource wrapper. This encapsulates a xDS resource when + * appearing inside a list collection resource. List collection resources are + * regular Resource messages of type: + * + * message Collection { + * repeated CollectionEntry resources = 1; + * } + */ +export interface CollectionEntry { + /** + * A resource locator describing how the member resource is to be located. + */ + 'locator'?: (_xds_core_v3_ResourceLocator | null); + /** + * The resource is inlined in the list collection. + */ + 'inline_entry'?: (_xds_core_v3_CollectionEntry_InlineEntry | null); + 'resource_specifier'?: "locator"|"inline_entry"; +} + +/** + * xDS collection resource wrapper. This encapsulates a xDS resource when + * appearing inside a list collection resource. List collection resources are + * regular Resource messages of type: + * + * message Collection { + * repeated CollectionEntry resources = 1; + * } + */ +export interface CollectionEntry__Output { + /** + * A resource locator describing how the member resource is to be located. + */ + 'locator'?: (_xds_core_v3_ResourceLocator__Output | null); + /** + * The resource is inlined in the list collection. + */ + 'inline_entry'?: (_xds_core_v3_CollectionEntry_InlineEntry__Output | null); + 'resource_specifier': "locator"|"inline_entry"; +} diff --git a/packages/grpc-js-xds/src/generated/xds/core/v3/ContextParams.ts b/packages/grpc-js-xds/src/generated/xds/core/v3/ContextParams.ts new file mode 100644 index 000000000..19a8a99bb --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/core/v3/ContextParams.ts @@ -0,0 +1,26 @@ +// Original file: deps/xds/xds/core/v3/context_params.proto + + +/** + * Additional parameters that can be used to select resource variants. These include any + * global context parameters, per-resource type client feature capabilities and per-resource + * type functional attributes. All per-resource type attributes will be `xds.resource.` + * prefixed and some of these are documented below: + * `xds.resource.listening_address`: The value is "IP:port" (e.g. "10.1.1.3:8080") which is + * the listening address of a Listener. Used in a Listener resource query. + */ +export interface ContextParams { + 'params'?: ({[key: string]: string}); +} + +/** + * Additional parameters that can be used to select resource variants. These include any + * global context parameters, per-resource type client feature capabilities and per-resource + * type functional attributes. All per-resource type attributes will be `xds.resource.` + * prefixed and some of these are documented below: + * `xds.resource.listening_address`: The value is "IP:port" (e.g. "10.1.1.3:8080") which is + * the listening address of a Listener. Used in a Listener resource query. + */ +export interface ContextParams__Output { + 'params': ({[key: string]: string}); +} diff --git a/packages/grpc-js-xds/src/generated/xds/core/v3/ResourceLocator.ts b/packages/grpc-js-xds/src/generated/xds/core/v3/ResourceLocator.ts new file mode 100644 index 000000000..bb1f822b8 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/core/v3/ResourceLocator.ts @@ -0,0 +1,220 @@ +// Original file: deps/xds/xds/core/v3/resource_locator.proto + +import type { ContextParams as _xds_core_v3_ContextParams, ContextParams__Output as _xds_core_v3_ContextParams__Output } from '../../../xds/core/v3/ContextParams'; +import type { ResourceLocator as _xds_core_v3_ResourceLocator, ResourceLocator__Output as _xds_core_v3_ResourceLocator__Output } from '../../../xds/core/v3/ResourceLocator'; + +/** + * Directives provide information to data-plane load balancers on how xDS + * resource names are to be interpreted and potentially further resolved. For + * example, they may provide alternative resource locators for when primary + * resolution fails. Directives are not part of resource names and do not + * appear in a xDS transport discovery request. + * + * When encoding to URIs, directives take the form: + * + * = + * + * For example, we can have alt=xdstp://foo/bar or entry=some%20thing. Each + * directive value type may have its own string encoding, in the case of + * ResourceLocator there is a recursive URI encoding. + * + * Percent encoding applies to the URI encoding of the directive value. + * Multiple directives are comma-separated, so the reserved characters that + * require percent encoding in a directive value are [',', '#', '[', ']', + * '%']. These are the RFC3986 fragment reserved characters with the addition + * of the xDS scheme specific ','. See + * https://tools.ietf.org/html/rfc3986#page-49 for further details on URI ABNF + * and reserved characters. + */ +export interface _xds_core_v3_ResourceLocator_Directive { + /** + * An alternative resource locator for fallback if the resource is + * unavailable. For example, take the resource locator: + * + * xdstp://foo/some-type/some-route-table#alt=xdstp://bar/some-type/another-route-table + * + * If the data-plane load balancer is unable to reach `foo` to fetch the + * resource, it will fallback to `bar`. Alternative resources do not need + * to have equivalent content, but they should be functional substitutes. + */ + 'alt'?: (_xds_core_v3_ResourceLocator | null); + /** + * List collections support inlining of resources via the entry field in + * Resource. These inlined Resource objects may have an optional name + * field specified. When specified, the entry directive allows + * ResourceLocator to directly reference these inlined resources, e.g. + * xdstp://.../foo#entry=bar. + */ + 'entry'?: (string); + 'directive'?: "alt"|"entry"; +} + +/** + * Directives provide information to data-plane load balancers on how xDS + * resource names are to be interpreted and potentially further resolved. For + * example, they may provide alternative resource locators for when primary + * resolution fails. Directives are not part of resource names and do not + * appear in a xDS transport discovery request. + * + * When encoding to URIs, directives take the form: + * + * = + * + * For example, we can have alt=xdstp://foo/bar or entry=some%20thing. Each + * directive value type may have its own string encoding, in the case of + * ResourceLocator there is a recursive URI encoding. + * + * Percent encoding applies to the URI encoding of the directive value. + * Multiple directives are comma-separated, so the reserved characters that + * require percent encoding in a directive value are [',', '#', '[', ']', + * '%']. These are the RFC3986 fragment reserved characters with the addition + * of the xDS scheme specific ','. See + * https://tools.ietf.org/html/rfc3986#page-49 for further details on URI ABNF + * and reserved characters. + */ +export interface _xds_core_v3_ResourceLocator_Directive__Output { + /** + * An alternative resource locator for fallback if the resource is + * unavailable. For example, take the resource locator: + * + * xdstp://foo/some-type/some-route-table#alt=xdstp://bar/some-type/another-route-table + * + * If the data-plane load balancer is unable to reach `foo` to fetch the + * resource, it will fallback to `bar`. Alternative resources do not need + * to have equivalent content, but they should be functional substitutes. + */ + 'alt'?: (_xds_core_v3_ResourceLocator__Output | null); + /** + * List collections support inlining of resources via the entry field in + * Resource. These inlined Resource objects may have an optional name + * field specified. When specified, the entry directive allows + * ResourceLocator to directly reference these inlined resources, e.g. + * xdstp://.../foo#entry=bar. + */ + 'entry'?: (string); + 'directive': "alt"|"entry"; +} + +// Original file: deps/xds/xds/core/v3/resource_locator.proto + +export enum _xds_core_v3_ResourceLocator_Scheme { + XDSTP = 0, + HTTP = 1, + FILE = 2, +} + +/** + * xDS resource locators identify a xDS resource name and instruct the + * data-plane load balancer on how the resource may be located. + * + * Resource locators have a canonical xdstp:// URI representation: + * + * xdstp://{authority}/{type_url}/{id}?{context_params}{#directive,*} + * + * where context_params take the form of URI query parameters. + * + * Resource locators have a similar canonical http:// URI representation: + * + * http://{authority}/{type_url}/{id}?{context_params}{#directive,*} + * + * Resource locators also have a simplified file:// URI representation: + * + * file:///{id}{#directive,*} + */ +export interface ResourceLocator { + /** + * URI scheme. + */ + 'scheme'?: (_xds_core_v3_ResourceLocator_Scheme | keyof typeof _xds_core_v3_ResourceLocator_Scheme); + /** + * Opaque identifier for the resource. Any '/' will not be escaped during URI + * encoding and will form part of the URI path. This may end + * with ‘*’ for glob collection references. + */ + 'id'?: (string); + /** + * Logical authority for resource (not necessarily transport network address). + * Authorities are opaque in the xDS API, data-plane load balancers will map + * them to concrete network transports such as an xDS management server, e.g. + * via envoy.config.core.v3.ConfigSource. + */ + 'authority'?: (string); + /** + * Fully qualified resource type (as in type URL without types.googleapis.com/ + * prefix). + */ + 'resource_type'?: (string); + /** + * Additional parameters that can be used to select resource variants. + * Matches must be exact, i.e. all context parameters must match exactly and + * there must be no additional context parameters set on the matched + * resource. + */ + 'exact_context'?: (_xds_core_v3_ContextParams | null); + /** + * A list of directives that appear in the xDS resource locator #fragment. + * + * When encoding to URI form, directives are percent encoded with comma + * separation. + */ + 'directives'?: (_xds_core_v3_ResourceLocator_Directive)[]; + 'context_param_specifier'?: "exact_context"; +} + +/** + * xDS resource locators identify a xDS resource name and instruct the + * data-plane load balancer on how the resource may be located. + * + * Resource locators have a canonical xdstp:// URI representation: + * + * xdstp://{authority}/{type_url}/{id}?{context_params}{#directive,*} + * + * where context_params take the form of URI query parameters. + * + * Resource locators have a similar canonical http:// URI representation: + * + * http://{authority}/{type_url}/{id}?{context_params}{#directive,*} + * + * Resource locators also have a simplified file:// URI representation: + * + * file:///{id}{#directive,*} + */ +export interface ResourceLocator__Output { + /** + * URI scheme. + */ + 'scheme': (keyof typeof _xds_core_v3_ResourceLocator_Scheme); + /** + * Opaque identifier for the resource. Any '/' will not be escaped during URI + * encoding and will form part of the URI path. This may end + * with ‘*’ for glob collection references. + */ + 'id': (string); + /** + * Logical authority for resource (not necessarily transport network address). + * Authorities are opaque in the xDS API, data-plane load balancers will map + * them to concrete network transports such as an xDS management server, e.g. + * via envoy.config.core.v3.ConfigSource. + */ + 'authority': (string); + /** + * Fully qualified resource type (as in type URL without types.googleapis.com/ + * prefix). + */ + 'resource_type': (string); + /** + * Additional parameters that can be used to select resource variants. + * Matches must be exact, i.e. all context parameters must match exactly and + * there must be no additional context parameters set on the matched + * resource. + */ + 'exact_context'?: (_xds_core_v3_ContextParams__Output | null); + /** + * A list of directives that appear in the xDS resource locator #fragment. + * + * When encoding to URI form, directives are percent encoded with comma + * separation. + */ + 'directives': (_xds_core_v3_ResourceLocator_Directive__Output)[]; + 'context_param_specifier': "exact_context"; +} diff --git a/packages/grpc-js-xds/src/generated/xds/type/v3/TypedStruct.ts b/packages/grpc-js-xds/src/generated/xds/type/v3/TypedStruct.ts new file mode 100644 index 000000000..a0df831d2 --- /dev/null +++ b/packages/grpc-js-xds/src/generated/xds/type/v3/TypedStruct.ts @@ -0,0 +1,77 @@ +// Original file: deps/xds/xds/type/v3/typed_struct.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../google/protobuf/Struct'; + +/** + * A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that + * describes the type of the serialized message. This is very similar to google.protobuf.Any, + * instead of having protocol buffer binary, this employs google.protobuf.Struct as value. + * + * This message is intended to be embedded inside Any, so it shouldn't be directly referred + * from other UDPA messages. + * + * When packing an opaque extension config, packing the expected type into Any is preferred + * wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor + * is not available, for example if: + * - A control plane sends opaque message that is originally from external source in human readable + * format such as JSON or YAML. + * - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot + * serialize the message in protocol buffer binary format. + * - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension + * uses. This has to be indicated in the DPLB capability negotiation. + * + * When a DPLB receives a TypedStruct in Any, it should: + * - Check if the type_url of the TypedStruct matches the type the extension expects. + * - Convert value to the type described in type_url and perform validation. + * TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link + * protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). + */ +export interface TypedStruct { + /** + * A URL that uniquely identifies the type of the serialize protocol buffer message. + * This has same semantics and format described in google.protobuf.Any: + * https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto + */ + 'type_url'?: (string); + /** + * A JSON representation of the above specified type. + */ + 'value'?: (_google_protobuf_Struct | null); +} + +/** + * A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that + * describes the type of the serialized message. This is very similar to google.protobuf.Any, + * instead of having protocol buffer binary, this employs google.protobuf.Struct as value. + * + * This message is intended to be embedded inside Any, so it shouldn't be directly referred + * from other UDPA messages. + * + * When packing an opaque extension config, packing the expected type into Any is preferred + * wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor + * is not available, for example if: + * - A control plane sends opaque message that is originally from external source in human readable + * format such as JSON or YAML. + * - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot + * serialize the message in protocol buffer binary format. + * - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension + * uses. This has to be indicated in the DPLB capability negotiation. + * + * When a DPLB receives a TypedStruct in Any, it should: + * - Check if the type_url of the TypedStruct matches the type the extension expects. + * - Convert value to the type described in type_url and perform validation. + * TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link + * protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). + */ +export interface TypedStruct__Output { + /** + * A URL that uniquely identifies the type of the serialize protocol buffer message. + * This has same semantics and format described in google.protobuf.Any: + * https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto + */ + 'type_url': (string); + /** + * A JSON representation of the above specified type. + */ + 'value': (_google_protobuf_Struct__Output | null); +} diff --git a/packages/grpc-js-xds/src/http-filter.ts b/packages/grpc-js-xds/src/http-filter.ts new file mode 100644 index 000000000..29ce5958f --- /dev/null +++ b/packages/grpc-js-xds/src/http-filter.ts @@ -0,0 +1,246 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This is a non-public, unstable API, but it's very convenient +import { loadProtosWithOptionsSync } from '@grpc/proto-loader/build/src/util'; +import { experimental, logVerbosity } from '@grpc/grpc-js'; +import { Any__Output } from './generated/google/protobuf/Any'; +import Filter = experimental.Filter; +import FilterFactory = experimental.FilterFactory; +import { TypedStruct__Output as TypedStruct__Output } from './generated/xds/type/v3/TypedStruct'; +import { FilterConfig__Output } from './generated/envoy/config/route/v3/FilterConfig'; +import { HttpFilter__Output } from './generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpFilter'; + +const TRACER_NAME = 'http_filter'; + +function trace(text: string): void { + experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); +} + +const TYPED_STRUCT_UDPA_URL = 'type.googleapis.com/udpa.type.v1.TypedStruct'; +const TYPED_STRUCT_UDPA_NAME = 'udpa.type.v1.TypedStruct'; +const TYPED_STRUCT_XDS_URL = 'type.googleapis.com/xds.type.v3.TypedStruct'; +const TYPED_STRUCT_XDS_NAME = 'xds.type.v3.TypedStruct'; + +const FILTER_CONFIG_URL = 'type.googleapis.com/envoy.config.route.v3.FilterConfig'; +const FILTER_CONFIG_NAME = 'envoy.config.route.v3.FilterConfig'; + +const resourceRoot = loadProtosWithOptionsSync([ + 'udpa/type/v1/typed_struct.proto', + 'xds/type/v3/typed_struct.proto', + 'envoy/config/route/v3/route_components.proto'], { + keepCase: true, + includeDirs: [ + // Paths are relative to src/build + __dirname + '/../../deps/xds/', + __dirname + '/../../deps/envoy-api/', + __dirname + '/../../deps/protoc-gen-validate/' + ], + } +); + +export interface HttpFilterConfig { + typeUrl: string; + config: any; +} + +export interface HttpFilterFactoryConstructor { + new(config: HttpFilterConfig, overrideConfig?: HttpFilterConfig): FilterFactory; +} + +export interface HttpFilterRegistryEntry { + parseTopLevelFilterConfig(encodedConfig: Any__Output): HttpFilterConfig | null; + parseOverrideFilterConfig(encodedConfig: Any__Output): HttpFilterConfig | null; + httpFilterConstructor: HttpFilterFactoryConstructor; +} + +const FILTER_REGISTRY = new Map(); + +export function registerHttpFilter(typeName: string, entry: HttpFilterRegistryEntry) { + trace('Registered filter with type URL ' + typeName); + FILTER_REGISTRY.set(typeName, entry); +} + +const toObjectOptions = { + longs: String, + enums: String, + defaults: true, + oneofs: true +} + +function parseAnyMessage(message: Any__Output): MessageType | null { + const typeName = message.type_url.substring(message.type_url.lastIndexOf('/') + 1); + const messageType = resourceRoot.lookup(typeName); + if (messageType) { + const decodedMessage = (messageType as any).decode(message.value); + return decodedMessage.$type.toObject(decodedMessage, toObjectOptions) as MessageType; + } else { + return null; + } +} + +export function getTopLevelFilterUrl(encodedConfig: Any__Output): string { + let typeUrl: string; + if (encodedConfig.type_url === TYPED_STRUCT_UDPA_URL || encodedConfig.type_url === TYPED_STRUCT_XDS_URL) { + const typedStruct = parseAnyMessage(encodedConfig) + if (typedStruct) { + return typedStruct.type_url; + } else { + throw new Error('Failed to parse TypedStruct'); + } + } else { + return encodedConfig.type_url; + } +} + +export function validateTopLevelFilter(httpFilter: HttpFilter__Output): boolean { + if (!httpFilter.typed_config) { + trace(httpFilter.name + ' validation failed: typed_config unset'); + return false; + } + const encodedConfig = httpFilter.typed_config; + let typeUrl: string; + try { + typeUrl = getTopLevelFilterUrl(encodedConfig); + } catch (e) { + trace(httpFilter.name + ' validation failed with error ' + e.message); + return false; + } + const registryEntry = FILTER_REGISTRY.get(typeUrl); + if (registryEntry) { + const parsedConfig = registryEntry.parseTopLevelFilterConfig(encodedConfig); + if (parsedConfig === null) { + trace(httpFilter.name + ' validation failed: config parsing failed'); + } + return parsedConfig !== null; + } else { + if (httpFilter.is_optional) { + return true; + } else { + trace(httpFilter.name + ' validation failed: filter is not optional and registry does not contain type URL ' + typeUrl); + return false; + } + } +} + +export function validateOverrideFilter(encodedConfig: Any__Output): boolean { + let typeUrl: string; + let realConfig: Any__Output; + let isOptional = false; + if (encodedConfig.type_url === FILTER_CONFIG_URL) { + const filterConfig = parseAnyMessage(encodedConfig); + if (filterConfig) { + isOptional = filterConfig.is_optional; + if (filterConfig.config) { + realConfig = filterConfig.config; + } else { + trace('Override filter validation failed: FilterConfig config field is empty'); + return false; + } + } else { + trace('Override filter validation failed: failed to parse FilterConfig message'); + return false; + } + } else { + realConfig = encodedConfig; + } + if (realConfig.type_url === TYPED_STRUCT_UDPA_URL || realConfig.type_url === TYPED_STRUCT_XDS_URL) { + const typedStruct = parseAnyMessage(encodedConfig); + if (typedStruct) { + typeUrl = typedStruct.type_url; + } else { + trace('Override filter validation failed: failed to parse TypedStruct message'); + return false; + } + } else { + typeUrl = realConfig.type_url; + } + const registryEntry = FILTER_REGISTRY.get(typeUrl); + if (registryEntry) { + const parsedConfig = registryEntry.parseOverrideFilterConfig(encodedConfig); + if (parsedConfig === null) { + trace('Override filter validation failed: config parsing failed. Type URL: ' + typeUrl); + } + return parsedConfig !== null; + } else { + if (isOptional) { + return true; + } else { + trace('Override filter validation failed: filter is not optional and registry does not contain type URL ' + typeUrl); + return false; + } + } +} + +export function parseTopLevelFilterConfig(encodedConfig: Any__Output) { + let typeUrl: string; + try { + typeUrl = getTopLevelFilterUrl(encodedConfig); + } catch (e) { + return null; + } + const registryEntry = FILTER_REGISTRY.get(typeUrl); + if (registryEntry) { + return registryEntry.parseTopLevelFilterConfig(encodedConfig); + } else { + // Filter type URL not found in registry + return null; + } +} + +export function parseOverrideFilterConfig(encodedConfig: Any__Output) { + let typeUrl: string; + let realConfig: Any__Output; + if (encodedConfig.type_url === FILTER_CONFIG_URL) { + const filterConfig = parseAnyMessage(encodedConfig); + if (filterConfig) { + if (filterConfig.config) { + realConfig = filterConfig.config; + } else { + return null; + } + } else { + return null; + } + } else { + realConfig = encodedConfig; + } + if (realConfig.type_url === TYPED_STRUCT_UDPA_URL || realConfig.type_url === TYPED_STRUCT_XDS_URL) { + const typedStruct = parseAnyMessage(encodedConfig); + if (typedStruct) { + typeUrl = typedStruct.type_url; + } else { + return null; + } + } else { + typeUrl = realConfig.type_url; + } + const registryEntry = FILTER_REGISTRY.get(typeUrl); + if (registryEntry) { + return registryEntry.parseOverrideFilterConfig(encodedConfig); + } else { + return null; + } +} + +export function createHttpFilter(config: HttpFilterConfig, overrideConfig?: HttpFilterConfig): FilterFactory | null { + const registryEntry = FILTER_REGISTRY.get(config.typeUrl); + if (registryEntry) { + return new registryEntry.httpFilterConstructor(config, overrideConfig); + } else { + return null; + } +} \ No newline at end of file diff --git a/packages/grpc-js-xds/src/http-filter/fault-injection-filter.ts b/packages/grpc-js-xds/src/http-filter/fault-injection-filter.ts new file mode 100644 index 000000000..b02dfbc80 --- /dev/null +++ b/packages/grpc-js-xds/src/http-filter/fault-injection-filter.ts @@ -0,0 +1,347 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This is a non-public, unstable API, but it's very convenient +import { loadProtosWithOptionsSync } from '@grpc/proto-loader/build/src/util'; +import { experimental, logVerbosity, Metadata, status } from '@grpc/grpc-js'; +import { Any__Output } from '../generated/google/protobuf/Any'; +import Filter = experimental.Filter; +import FilterFactory = experimental.FilterFactory; +import BaseFilter = experimental.BaseFilter; +import CallStream = experimental.CallStream; +import { HttpFilterConfig, registerHttpFilter } from '../http-filter'; +import { HTTPFault__Output } from '../generated/envoy/extensions/filters/http/fault/v3/HTTPFault'; +import { envoyFractionToFraction, Fraction } from '../fraction'; +import { Duration__Output } from '../generated/google/protobuf/Duration'; + +const TRACER_NAME = 'fault_injection'; + +function trace(text: string): void { + experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); +} + +const resourceRoot = loadProtosWithOptionsSync([ + 'envoy/extensions/filters/http/fault/v3/fault.proto'], { + keepCase: true, + includeDirs: [ + // Paths are relative to src/build/http-filter + __dirname + '/../../../deps/xds/', + __dirname + '/../../../deps/envoy-api/', + __dirname + '/../../../deps/protoc-gen-validate/' + ], + } +); + +interface FixedDelayConfig { + kind: 'fixed'; + durationMs: number; + percentage: Fraction; +} + +interface HeaderDelayConfig { + kind: 'header'; + percentage: Fraction; +} + +interface GrpcAbortConfig { + kind: 'grpc'; + code: status; + percentage: Fraction; +} + +interface HeaderAbortConfig { + kind: 'header'; + percentage: Fraction; +} + +interface FaultInjectionConfig { + delay: FixedDelayConfig | HeaderDelayConfig | null; + abort: GrpcAbortConfig | HeaderAbortConfig | null; + maxActiveFaults: number; +} + +interface FaultInjectionFilterConfig extends HttpFilterConfig { + typeUrl: 'type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault'; + config: FaultInjectionConfig; +} + +const FAULT_INJECTION_FILTER_URL = 'type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault'; + +const toObjectOptions = { + longs: String, + enums: String, + defaults: true, + oneofs: true +} + +function parseAnyMessage(message: Any__Output): MessageType | null { + const typeName = message.type_url.substring(message.type_url.lastIndexOf('/') + 1); + const messageType = resourceRoot.lookup(typeName); + if (messageType) { + const decodedMessage = (messageType as any).decode(message.value); + return decodedMessage.$type.toObject(decodedMessage, toObjectOptions) as MessageType; + } else { + return null; + } +} + +function durationToMs(duration: Duration__Output): number { + return Number.parseInt(duration.seconds) * 1000 + duration.nanos / 1_000_000; +} + +function httpCodeToGrpcStatus(code: number): status { + switch (code) { + case 400: return status.INTERNAL; + case 401: return status.UNAUTHENTICATED; + case 403: return status.PERMISSION_DENIED; + case 404: return status.UNIMPLEMENTED; + case 429: return status.UNAVAILABLE; + case 502: return status.UNAVAILABLE; + case 503: return status.UNAVAILABLE; + case 504: return status.UNAVAILABLE; + default: return status.UNKNOWN; + } +} + +function parseHTTPFaultConfig(encodedConfig: Any__Output): FaultInjectionFilterConfig | null { + if (encodedConfig.type_url !== FAULT_INJECTION_FILTER_URL) { + trace('Config parsing failed: unexpected type URL: ' + encodedConfig.type_url); + return null; + } + const parsedMessage = parseAnyMessage(encodedConfig); + if (parsedMessage === null) { + trace('Config parsing failed: failed to parse HTTPFault message'); + return null; + } + trace('Parsing HTTPFault message ' + JSON.stringify(parsedMessage, undefined, 2)); + const result: FaultInjectionConfig = { + delay: null, + abort: null, + maxActiveFaults: Infinity + }; + // Parse delay field + if (parsedMessage.delay !== null) { + if (parsedMessage.delay.percentage === null) { + trace('Config parsing failed: delay.percentage unset'); + return null; + } + const percentage = envoyFractionToFraction(parsedMessage.delay.percentage); + switch (parsedMessage.delay.fault_delay_secifier /* sic */) { + case 'fixed_delay': + result.delay = { + kind: 'fixed', + durationMs: durationToMs(parsedMessage.delay.fixed_delay!), + percentage: percentage + }; + break; + case 'header_delay': + result.delay = { + kind: 'header', + percentage: percentage + }; + break; + default: + trace('Config parsing failed: delay.fault_delay_secifier has unexpected value ' + parsedMessage.delay.fault_delay_secifier); + // Should not be possible + return null; + } + } + // Parse abort field + if (parsedMessage.abort !== null) { + if (parsedMessage.abort.percentage === null) { + trace('Config parsing failed: abort.percentage unset'); + return null; + } + const percentage = envoyFractionToFraction(parsedMessage.abort.percentage); + switch (parsedMessage.abort.error_type) { + case 'http_status': + result.abort = { + kind: 'grpc', + code: httpCodeToGrpcStatus(parsedMessage.abort.http_status!), + percentage: percentage + }; + break; + case 'grpc_status': + result.abort = { + kind: 'grpc', + code: parsedMessage.abort.grpc_status!, + percentage: percentage + } + break; + case 'header_abort': + result.abort = { + kind: 'header', + percentage: percentage + }; + break; + default: + trace('Config parsing failed: abort.error_type has unexpected value ' + parsedMessage.abort.error_type); + // Should not be possible + return null; + } + } + // Parse max_active_faults field + if (parsedMessage.max_active_faults !== null) { + result.maxActiveFaults = parsedMessage.max_active_faults.value; + } + return { + typeUrl: FAULT_INJECTION_FILTER_URL, + config: result + }; +} + +function asyncTimeout(timeMs: number): Promise { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(); + }, timeMs); + }); +} + +/** + * Returns true with probability numerator/denominator. + * @param numerator + * @param denominator + */ +function rollRandomPercentage(numerator: number, denominator: number): boolean { + return Math.random() * denominator < numerator; +} + +const DELAY_DURATION_HEADER_KEY = 'x-envoy-fault-delay-request'; +const DELAY_PERCENTAGE_HEADER_KEY = 'x-envoy-fault-delay-request-percentage'; +const ABORT_GRPC_HEADER_KEY = 'x-envoy-fault-abort-grpc-request'; +const ABORT_HTTP_HEADER_KEY = 'x-envoy-fault-abort-request'; +const ABORT_PERCENTAGE_HEADER_KEY = 'x-envoy-fault-abort-request-percentage'; + +const NUMBER_REGEX = /\d+/; + +let totalActiveFaults = 0; + +class FaultInjectionFilter extends BaseFilter implements Filter { + constructor(private config: FaultInjectionConfig) { + super(); + } + + async sendMetadata(metadataPromise: Promise): Promise { + const metadata = await metadataPromise; + // Handle delay + if (totalActiveFaults < this.config.maxActiveFaults && this.config.delay) { + let duration = 0; + let numerator = this.config.delay.percentage.numerator; + const denominator = this.config.delay.percentage.denominator; + if (this.config.delay.kind === 'fixed') { + duration = this.config.delay.durationMs; + } else { + const durationHeader = metadata.get(DELAY_DURATION_HEADER_KEY); + for (const value of durationHeader) { + if (typeof value !== 'string') { + continue; + } + if (NUMBER_REGEX.test(value)) { + duration = Number.parseInt(value); + break; + } + } + const percentageHeader = metadata.get(DELAY_PERCENTAGE_HEADER_KEY); + for (const value of percentageHeader) { + if (typeof value !== 'string') { + continue; + } + if (NUMBER_REGEX.test(value)) { + numerator = Math.min(numerator, Number.parseInt(value)); + break; + } + } + } + if (rollRandomPercentage(numerator, denominator)) { + totalActiveFaults++; + await asyncTimeout(duration); + totalActiveFaults--; + } + } + // Handle abort + if (totalActiveFaults < this.config.maxActiveFaults && this.config.abort) { + let abortStatus: status | null = null; + let numerator = this.config.abort.percentage.numerator; + const denominator = this.config.abort.percentage.denominator; + if (this.config.abort.kind === 'grpc') { + abortStatus = this.config.abort.code; + } else { + const grpcStatusHeader = metadata.get(ABORT_GRPC_HEADER_KEY); + for (const value of grpcStatusHeader) { + if (typeof value !== 'string') { + continue; + } + if (NUMBER_REGEX.test(value)) { + abortStatus = Number.parseInt(value); + break; + } + } + /* Fall back to looking for HTTP status header if the gRPC status + * header is not present. */ + if (abortStatus === null) { + const httpStatusHeader = metadata.get(ABORT_HTTP_HEADER_KEY); + for (const value of httpStatusHeader) { + if (typeof value !== 'string') { + continue; + } + if (NUMBER_REGEX.test(value)) { + abortStatus = httpCodeToGrpcStatus(Number.parseInt(value)); + break; + } + } + } + const percentageHeader = metadata.get(ABORT_PERCENTAGE_HEADER_KEY); + for (const value of percentageHeader) { + if (typeof value !== 'string') { + continue; + } + if (NUMBER_REGEX.test(value)) { + numerator = Math.min(numerator, Number.parseInt(value)); + break; + } + } + } + if (abortStatus !== null && rollRandomPercentage(numerator, denominator)) { + return Promise.reject({code: abortStatus, details: 'Fault injected', metadata: new Metadata()}); + } + } + return metadata; + } +} + +class FaultInjectionFilterFactory implements FilterFactory { + private config: FaultInjectionConfig; + constructor(config: HttpFilterConfig, overrideConfig?: HttpFilterConfig) { + if (overrideConfig?.typeUrl === FAULT_INJECTION_FILTER_URL) { + this.config = overrideConfig.config; + } else { + this.config = config.config; + } + } + + createFilter(): FaultInjectionFilter { + return new FaultInjectionFilter(this.config); + } +} + +export function setup() { + registerHttpFilter(FAULT_INJECTION_FILTER_URL, { + parseTopLevelFilterConfig: parseHTTPFaultConfig, + parseOverrideFilterConfig: parseHTTPFaultConfig, + httpFilterConstructor: FaultInjectionFilterFactory + }); +} \ No newline at end of file diff --git a/packages/grpc-js-xds/src/http-filter/router-filter.ts b/packages/grpc-js-xds/src/http-filter/router-filter.ts new file mode 100644 index 000000000..172a08740 --- /dev/null +++ b/packages/grpc-js-xds/src/http-filter/router-filter.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { experimental } from '@grpc/grpc-js'; +import { Any__Output } from '../generated/google/protobuf/Any'; +import { HttpFilterConfig, registerHttpFilter } from '../http-filter'; +import Filter = experimental.Filter; +import FilterFactory = experimental.FilterFactory; +import BaseFilter = experimental.BaseFilter; + +class RouterFilter extends BaseFilter implements Filter {} + +class RouterFilterFactory implements FilterFactory { + constructor(config: HttpFilterConfig, overrideConfig?: HttpFilterConfig) {} + + createFilter(): RouterFilter { + return new RouterFilter(); + } +} + +const ROUTER_FILTER_URL = 'type.googleapis.com/envoy.extensions.filters.http.router.v3.Router'; + +function parseConfig(encodedConfig: Any__Output): HttpFilterConfig | null { + return { + typeUrl: ROUTER_FILTER_URL, + config: null + }; +} + +export function setup() { + registerHttpFilter(ROUTER_FILTER_URL, { + parseTopLevelFilterConfig: parseConfig, + parseOverrideFilterConfig: parseConfig, + httpFilterConstructor: RouterFilterFactory + }); +} \ No newline at end of file diff --git a/packages/grpc-js-xds/src/index.ts b/packages/grpc-js-xds/src/index.ts index 1b24d25e6..ca1cf72ef 100644 --- a/packages/grpc-js-xds/src/index.ts +++ b/packages/grpc-js-xds/src/index.ts @@ -22,6 +22,9 @@ import * as load_balancer_lrs from './load-balancer-lrs'; import * as load_balancer_priority from './load-balancer-priority'; import * as load_balancer_weighted_target from './load-balancer-weighted-target'; import * as load_balancer_xds_cluster_manager from './load-balancer-xds-cluster-manager'; +import * as router_filter from './http-filter/router-filter'; +import * as fault_injection_filter from './http-filter/fault-injection-filter'; +import * as csds from './csds'; /** * Register the "xds:" name scheme with the @grpc/grpc-js library. @@ -34,4 +37,7 @@ export function register() { load_balancer_priority.setup(); load_balancer_weighted_target.setup(); load_balancer_xds_cluster_manager.setup(); + router_filter.setup(); + fault_injection_filter.setup(); + csds.setup(); } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/load-balancer-cds.ts b/packages/grpc-js-xds/src/load-balancer-cds.ts index d0fe2338a..243a1e967 100644 --- a/packages/grpc-js-xds/src/load-balancer-cds.ts +++ b/packages/grpc-js-xds/src/load-balancer-cds.ts @@ -17,7 +17,7 @@ import { connectivityState, status, Metadata, logVerbosity, experimental } from '@grpc/grpc-js'; import { getSingletonXdsClient, XdsClient } from './xds-client'; -import { Cluster__Output } from './generated/envoy/api/v2/Cluster'; +import { Cluster__Output } from './generated/envoy/config/cluster/v3/Cluster'; import SubchannelAddress = experimental.SubchannelAddress; import UnavailablePicker = experimental.UnavailablePicker; import ChildLoadBalancerHandler = experimental.ChildLoadBalancerHandler; @@ -25,8 +25,14 @@ import LoadBalancer = experimental.LoadBalancer; import ChannelControlHelper = experimental.ChannelControlHelper; import registerLoadBalancerType = experimental.registerLoadBalancerType; import LoadBalancingConfig = experimental.LoadBalancingConfig; +import OutlierDetectionLoadBalancingConfig = experimental.OutlierDetectionLoadBalancingConfig; +import SuccessRateEjectionConfig = experimental.SuccessRateEjectionConfig; +import FailurePercentageEjectionConfig = experimental.FailurePercentageEjectionConfig; import { EdsLoadBalancingConfig } from './load-balancer-eds'; import { Watcher } from './xds-stream-state/xds-stream-state'; +import { OutlierDetection__Output } from './generated/envoy/config/cluster/v3/OutlierDetection'; +import { Duration__Output } from './generated/google/protobuf/Duration'; +import { EXPERIMENTAL_OUTLIER_DETECTION } from './environment'; const TRACER_NAME = 'cds_balancer'; @@ -64,6 +70,51 @@ export class CdsLoadBalancingConfig implements LoadBalancingConfig { } } +function durationToMs(duration: Duration__Output): number { + return (Number(duration.seconds) * 1_000 + duration.nanos / 1_000_000) | 0; +} + +function translateOutlierDetectionConfig(outlierDetection: OutlierDetection__Output | null): OutlierDetectionLoadBalancingConfig | undefined { + if (!EXPERIMENTAL_OUTLIER_DETECTION) { + return undefined; + } + if (!outlierDetection) { + /* No-op outlier detection config, with all fields unset. */ + return new OutlierDetectionLoadBalancingConfig(null, null, null, null, null, null, []); + } + let successRateConfig: Partial | null = null; + /* Success rate ejection is enabled by default, so we only disable it if + * enforcing_success_rate is set and it has the value 0 */ + if (!outlierDetection.enforcing_success_rate || outlierDetection.enforcing_success_rate.value > 0) { + successRateConfig = { + enforcement_percentage: outlierDetection.enforcing_success_rate?.value, + minimum_hosts: outlierDetection.success_rate_minimum_hosts?.value, + request_volume: outlierDetection.success_rate_request_volume?.value, + stdev_factor: outlierDetection.success_rate_stdev_factor?.value + }; + } + let failurePercentageConfig: Partial | null = null; + /* Failure percentage ejection is disabled by default, so we only enable it + * if enforcing_failure_percentage is set and it has a value greater than 0 */ + if (outlierDetection.enforcing_failure_percentage && outlierDetection.enforcing_failure_percentage.value > 0) { + failurePercentageConfig = { + enforcement_percentage: outlierDetection.enforcing_failure_percentage.value, + minimum_hosts: outlierDetection.failure_percentage_minimum_hosts?.value, + request_volume: outlierDetection.failure_percentage_request_volume?.value, + threshold: outlierDetection.failure_percentage_threshold?.value + } + } + return new OutlierDetectionLoadBalancingConfig( + outlierDetection.interval ? durationToMs(outlierDetection.interval) : null, + outlierDetection.base_ejection_time ? durationToMs(outlierDetection.base_ejection_time) : null, + outlierDetection.max_ejection_time ? durationToMs(outlierDetection.max_ejection_time) : null, + outlierDetection.max_ejection_percent?.value ?? null, + successRateConfig, + failurePercentageConfig, + [] + ); +} + export class CdsLoadBalancer implements LoadBalancer { private childBalancer: ChildLoadBalancerHandler; private watcher: Watcher; @@ -74,17 +125,32 @@ export class CdsLoadBalancer implements LoadBalancer { private latestConfig: CdsLoadBalancingConfig | null = null; private latestAttributes: { [key: string]: unknown } = {}; + private xdsClient: XdsClient | null = null; constructor(private readonly channelControlHelper: ChannelControlHelper) { this.childBalancer = new ChildLoadBalancerHandler(channelControlHelper); this.watcher = { onValidUpdate: (update) => { this.latestCdsUpdate = update; + let maxConcurrentRequests: number | undefined = undefined; + for (const threshold of update.circuit_breakers?.thresholds ?? []) { + if (threshold.priority === 'DEFAULT') { + maxConcurrentRequests = threshold.max_requests?.value; + } + } /* the lrs_server.self field indicates that the same server should be * used for load reporting as for other xDS operations. Setting * lrsLoadReportingServerName to the empty string sets that behavior. * Otherwise, if the field is omitted, load reporting is disabled. */ - const edsConfig: EdsLoadBalancingConfig = new EdsLoadBalancingConfig(update.name, [], [], update.eds_cluster_config!.service_name === '' ? undefined : update.eds_cluster_config!.service_name, update.lrs_server?.self ? '' : undefined); + const edsConfig: EdsLoadBalancingConfig = new EdsLoadBalancingConfig( + /* cluster= */ update.name, + /* localityPickingPolicy= */ [], + /* endpointPickingPolicy= */ [], + /* edsServiceName= */ update.eds_cluster_config!.service_name === '' ? undefined : update.eds_cluster_config!.service_name, + /* lrsLoadReportingServerName= */update.lrs_server?.self ? '' : undefined, + /* maxConcurrentRequests= */ maxConcurrentRequests, + /* outlierDetection= */ translateOutlierDetectionConfig(update.outlier_detection) + ); trace('Child update EDS config: ' + JSON.stringify(edsConfig)); this.childBalancer.updateAddressList( [], @@ -123,6 +189,7 @@ export class CdsLoadBalancer implements LoadBalancer { } trace('Received update with config ' + JSON.stringify(lbConfig, undefined, 2)); this.latestAttributes = attributes; + this.xdsClient = attributes.xdsClient as XdsClient; /* If the cluster is changing, disable the old watcher before adding the new * one */ @@ -131,7 +198,7 @@ export class CdsLoadBalancer implements LoadBalancer { this.latestConfig?.getCluster() !== lbConfig.getCluster() ) { trace('Removing old cluster watcher for cluster name ' + this.latestConfig!.getCluster()); - getSingletonXdsClient().removeClusterWatcher( + this.xdsClient.removeClusterWatcher( this.latestConfig!.getCluster(), this.watcher ); @@ -147,7 +214,7 @@ export class CdsLoadBalancer implements LoadBalancer { if (!this.isWatcherActive) { trace('Adding new cluster watcher for cluster name ' + lbConfig.getCluster()); - getSingletonXdsClient().addClusterWatcher(lbConfig.getCluster(), this.watcher); + this.xdsClient.addClusterWatcher(lbConfig.getCluster(), this.watcher); this.isWatcherActive = true; } } @@ -161,7 +228,7 @@ export class CdsLoadBalancer implements LoadBalancer { trace('Destroying load balancer with cluster name ' + this.latestConfig?.getCluster()); this.childBalancer.destroy(); if (this.isWatcherActive) { - getSingletonXdsClient().removeClusterWatcher( + this.xdsClient?.removeClusterWatcher( this.latestConfig!.getCluster(), this.watcher ); diff --git a/packages/grpc-js-xds/src/load-balancer-eds.ts b/packages/grpc-js-xds/src/load-balancer-eds.ts index 657dc3a82..03a4078ac 100644 --- a/packages/grpc-js-xds/src/load-balancer-eds.ts +++ b/packages/grpc-js-xds/src/load-balancer-eds.ts @@ -15,10 +15,10 @@ * */ -import { connectivityState as ConnectivityState, status as Status, Metadata, logVerbosity as LogVerbosity, experimental } from '@grpc/grpc-js'; +import { connectivityState as ConnectivityState, status as Status, Metadata, logVerbosity as LogVerbosity, experimental, StatusObject } from '@grpc/grpc-js'; import { getSingletonXdsClient, XdsClient, XdsClusterDropStats } from './xds-client'; -import { ClusterLoadAssignment__Output } from './generated/envoy/api/v2/ClusterLoadAssignment'; -import { Locality__Output } from './generated/envoy/api/v2/core/Locality'; +import { ClusterLoadAssignment__Output } from './generated/envoy/config/endpoint/v3/ClusterLoadAssignment'; +import { Locality__Output } from './generated/envoy/config/core/v3/Locality'; import { LocalitySubchannelAddress, PriorityChild, PriorityLoadBalancingConfig } from './load-balancer-priority'; import LoadBalancer = experimental.LoadBalancer; import ChannelControlHelper = experimental.ChannelControlHelper; @@ -34,6 +34,12 @@ import { validateLoadBalancingConfig } from '@grpc/grpc-js/build/src/experimenta import { WeightedTarget, WeightedTargetLoadBalancingConfig } from './load-balancer-weighted-target'; import { LrsLoadBalancingConfig } from './load-balancer-lrs'; import { Watcher } from './xds-stream-state/xds-stream-state'; +import Filter = experimental.Filter; +import BaseFilter = experimental.BaseFilter; +import FilterFactory = experimental.FilterFactory; +import CallStream = experimental.CallStream; +import OutlierDetectionLoadBalancingConfig = experimental.OutlierDetectionLoadBalancingConfig; +import { EXPERIMENTAL_OUTLIER_DETECTION } from './environment'; const TRACER_NAME = 'eds_balancer'; @@ -47,7 +53,10 @@ function localityToName(locality: Locality__Output) { return `{region=${locality.region},zone=${locality.zone},sub_zone=${locality.sub_zone}}`; } +const DEFAULT_MAX_CONCURRENT_REQUESTS = 1024; + export class EdsLoadBalancingConfig implements LoadBalancingConfig { + private maxConcurrentRequests: number; getLoadBalancerName(): string { return TYPE_NAME; } @@ -55,7 +64,8 @@ export class EdsLoadBalancingConfig implements LoadBalancingConfig { const jsonObj: {[key: string]: any} = { cluster: this.cluster, locality_picking_policy: this.localityPickingPolicy.map(policy => policy.toJsonObject()), - endpoint_picking_policy: this.endpointPickingPolicy.map(policy => policy.toJsonObject()) + endpoint_picking_policy: this.endpointPickingPolicy.map(policy => policy.toJsonObject()), + max_concurrent_requests: this.maxConcurrentRequests }; if (this.edsServiceName !== undefined) { jsonObj.eds_service_name = this.edsServiceName; @@ -63,13 +73,16 @@ export class EdsLoadBalancingConfig implements LoadBalancingConfig { if (this.lrsLoadReportingServerName !== undefined) { jsonObj.lrs_load_reporting_server_name = this.lrsLoadReportingServerName; } + if (this.outlierDetection !== undefined) { + jsonObj.outlier_detection = this.outlierDetection.toJsonObject(); + } return { [TYPE_NAME]: jsonObj }; } - constructor(private cluster: string, private localityPickingPolicy: LoadBalancingConfig[], private endpointPickingPolicy: LoadBalancingConfig[], private edsServiceName?: string, private lrsLoadReportingServerName?: string) { - + constructor(private cluster: string, private localityPickingPolicy: LoadBalancingConfig[], private endpointPickingPolicy: LoadBalancingConfig[], private edsServiceName?: string, private lrsLoadReportingServerName?: string, maxConcurrentRequests?: number, private outlierDetection?: OutlierDetectionLoadBalancingConfig) { + this.maxConcurrentRequests = maxConcurrentRequests ?? DEFAULT_MAX_CONCURRENT_REQUESTS; } getCluster() { @@ -92,6 +105,14 @@ export class EdsLoadBalancingConfig implements LoadBalancingConfig { return this.lrsLoadReportingServerName; } + getMaxConcurrentRequests() { + return this.maxConcurrentRequests; + } + + getOutlierDetection() { + return this.outlierDetection; + } + static createFromJson(obj: any): EdsLoadBalancingConfig { if (!('cluster' in obj && typeof obj.cluster === 'string')) { throw new Error('eds config must have a string field cluster'); @@ -108,7 +129,20 @@ export class EdsLoadBalancingConfig implements LoadBalancingConfig { if ('lrs_load_reporting_server_name' in obj && (!obj.lrs_load_reporting_server_name === undefined || typeof obj.lrs_load_reporting_server_name === 'string')) { throw new Error('eds config lrs_load_reporting_server_name must be a string if provided'); } - return new EdsLoadBalancingConfig(obj.cluster, obj.locality_picking_policy.map(validateLoadBalancingConfig), obj.endpoint_picking_policy.map(validateLoadBalancingConfig), obj.eds_service_name, obj.lrs_load_reporting_server_name); + if ('max_concurrent_requests' in obj && (!obj.max_concurrent_requests === undefined || typeof obj.max_concurrent_requests === 'number')) { + throw new Error('eds config max_concurrent_requests must be a number if provided'); + } + let validatedOutlierDetectionConfig: OutlierDetectionLoadBalancingConfig | undefined = undefined; + if (EXPERIMENTAL_OUTLIER_DETECTION) { + if ('outlier_detection' in obj) { + const outlierDetectionConfig = validateLoadBalancingConfig(obj.outlier_detection); + if (!(outlierDetectionConfig instanceof OutlierDetectionLoadBalancingConfig)) { + throw new Error('eds config outlier_detection must be a valid outlier detection config if provided'); + } + validatedOutlierDetectionConfig = outlierDetectionConfig; + } + } + return new EdsLoadBalancingConfig(obj.cluster, obj.locality_picking_policy.map(validateLoadBalancingConfig), obj.endpoint_picking_policy.map(validateLoadBalancingConfig), obj.eds_service_name, obj.lrs_load_reporting_server_name, obj.max_concurrent_requests, validatedOutlierDetectionConfig); } } @@ -133,6 +167,7 @@ export class EdsLoadBalancer implements LoadBalancer { private lastestConfig: EdsLoadBalancingConfig | null = null; private latestAttributes: { [key: string]: unknown } = {}; + private xdsClient: XdsClient | null = null; private latestEdsUpdate: ClusterLoadAssignment__Output | null = null; /** @@ -149,15 +184,10 @@ export class EdsLoadBalancer implements LoadBalancer { private clusterDropStats: XdsClusterDropStats | null = null; + private concurrentRequests: number = 0; + constructor(private readonly channelControlHelper: ChannelControlHelper) { - this.childBalancer = new ChildLoadBalancerHandler({ - createSubchannel: (subchannelAddress, subchannelArgs) => - this.channelControlHelper.createSubchannel( - subchannelAddress, - subchannelArgs - ), - requestReresolution: () => - this.channelControlHelper.requestReresolution(), + this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.channelControlHelper, { updateState: (connectivityState, originalPicker) => { if (this.latestEdsUpdate === null) { return; @@ -169,26 +199,46 @@ export class EdsLoadBalancer implements LoadBalancer { * Otherwise, delegate picking the subchannel to the child * balancer. */ if (dropCategory === null) { - return originalPicker.pick(pickArgs); + const originalPick = originalPicker.pick(pickArgs); + return { + pickResultType: originalPick.pickResultType, + status: originalPick.status, + subchannel: originalPick.subchannel, + onCallStarted: () => { + originalPick.onCallStarted?.(); + this.concurrentRequests += 1; + }, + onCallEnded: status => { + originalPick.onCallEnded?.(status); + this.concurrentRequests -= 1; + } + }; } else { - this.clusterDropStats?.addCallDropped(dropCategory); + let details: string; + if (dropCategory === true) { + details = 'Call dropped by load balancing policy.'; + this.clusterDropStats?.addUncategorizedCallDropped(); + } else { + details = `Call dropped by load balancing policy. Category: ${dropCategory}`; + this.clusterDropStats?.addCallDropped(dropCategory); + } return { pickResultType: PickResultType.DROP, status: { code: Status.UNAVAILABLE, - details: `Call dropped by load balancing policy. Category: ${dropCategory}`, + details: details, metadata: new Metadata(), }, subchannel: null, - extraFilterFactory: null, - onCallStarted: null, + onCallEnded: null, + onCallStarted: null }; } }, }; this.channelControlHelper.updateState(connectivityState, edsPicker); }, - }); + })); this.watcher = { onValidUpdate: (update) => { trace('Received EDS update for ' + this.edsServiceName + ': ' + JSON.stringify(update, undefined, 2)); @@ -218,9 +268,13 @@ export class EdsLoadBalancer implements LoadBalancer { /** * Check whether a single call should be dropped according to the current * policy, based on randomly chosen numbers. Returns the drop category if - * the call should be dropped, and null otherwise. + * the call should be dropped, and null otherwise. true is a valid + * output, as a sentinel value indicating a drop with no category. */ - private checkForDrop(): string | null { + private checkForDrop(): string | true | null { + if (this.lastestConfig && this.concurrentRequests >= this.lastestConfig.getMaxConcurrentRequests()) { + return true; + } if (!this.latestEdsUpdate?.policy) { return null; } @@ -397,10 +451,15 @@ export class EdsLoadBalancer implements LoadBalancer { } } + const weightedTargetConfig = new WeightedTargetLoadBalancingConfig(childTargets); + let outlierDetectionConfig: OutlierDetectionLoadBalancingConfig | undefined; + if (EXPERIMENTAL_OUTLIER_DETECTION) { + outlierDetectionConfig = this.lastestConfig.getOutlierDetection()?.copyWithChildPolicy([weightedTargetConfig]); + } + const priorityChildConfig = outlierDetectionConfig ?? weightedTargetConfig; + priorityChildren.set(newPriorityName, { - config: [ - new WeightedTargetLoadBalancingConfig(childTargets), - ], + config: [priorityChildConfig], }); } /* Contract the priority names array if it is sparse. This config only @@ -430,13 +489,14 @@ export class EdsLoadBalancer implements LoadBalancer { trace('Received update with config: ' + JSON.stringify(lbConfig, undefined, 2)); this.lastestConfig = lbConfig; this.latestAttributes = attributes; + this.xdsClient = attributes.xdsClient as XdsClient; const newEdsServiceName = lbConfig.getEdsServiceName() ?? lbConfig.getCluster(); /* If the name is changing, disable the old watcher before adding the new * one */ if (this.isWatcherActive && this.edsServiceName !== newEdsServiceName) { trace('Removing old endpoint watcher for edsServiceName ' + this.edsServiceName) - getSingletonXdsClient().removeEndpointWatcher(this.edsServiceName!, this.watcher); + this.xdsClient.removeEndpointWatcher(this.edsServiceName!, this.watcher); /* Setting isWatcherActive to false here lets us have one code path for * calling addEndpointWatcher */ this.isWatcherActive = false; @@ -449,12 +509,12 @@ export class EdsLoadBalancer implements LoadBalancer { if (!this.isWatcherActive) { trace('Adding new endpoint watcher for edsServiceName ' + this.edsServiceName); - getSingletonXdsClient().addEndpointWatcher(this.edsServiceName, this.watcher); + this.xdsClient.addEndpointWatcher(this.edsServiceName, this.watcher); this.isWatcherActive = true; } if (lbConfig.getLrsLoadReportingServerName()) { - this.clusterDropStats = getSingletonXdsClient().addClusterDropStats( + this.clusterDropStats = this.xdsClient.addClusterDropStats( lbConfig.getLrsLoadReportingServerName()!, lbConfig.getCluster(), lbConfig.getEdsServiceName() ?? '' @@ -475,7 +535,7 @@ export class EdsLoadBalancer implements LoadBalancer { destroy(): void { trace('Destroying load balancer with edsServiceName ' + this.edsServiceName); if (this.edsServiceName) { - getSingletonXdsClient().removeEndpointWatcher(this.edsServiceName, this.watcher); + this.xdsClient?.removeEndpointWatcher(this.edsServiceName, this.watcher); } this.childBalancer.destroy(); } diff --git a/packages/grpc-js-xds/src/load-balancer-lrs.ts b/packages/grpc-js-xds/src/load-balancer-lrs.ts index 0792b11c2..9610ea834 100644 --- a/packages/grpc-js-xds/src/load-balancer-lrs.ts +++ b/packages/grpc-js-xds/src/load-balancer-lrs.ts @@ -16,7 +16,7 @@ */ import { connectivityState as ConnectivityState, StatusObject, status as Status, experimental } from '@grpc/grpc-js'; -import { Locality__Output } from './generated/envoy/api/v2/core/Locality'; +import { Locality__Output } from './generated/envoy/config/core/v3/Locality'; import { XdsClusterLocalityStats, XdsClient, getSingletonXdsClient } from './xds-client'; import LoadBalancer = experimental.LoadBalancer; import ChannelControlHelper = experimental.ChannelControlHelper; @@ -32,7 +32,6 @@ import PickResult = experimental.PickResult; import Filter = experimental.Filter; import BaseFilter = experimental.BaseFilter; import FilterFactory = experimental.FilterFactory; -import FilterStackFactory = experimental.FilterStackFactory; import Call = experimental.CallStream; import validateLoadBalancingConfig = experimental.validateLoadBalancingConfig @@ -109,29 +108,6 @@ export class LrsLoadBalancingConfig implements LoadBalancingConfig { } } -/** - * Filter class that reports when the call ends. - */ -class CallEndTrackingFilter extends BaseFilter implements Filter { - constructor(private localityStatsReporter: XdsClusterLocalityStats) { - super(); - } - - receiveTrailers(status: StatusObject) { - this.localityStatsReporter.addCallFinished(status.code !== Status.OK); - return status; - } -} - -class CallEndTrackingFilterFactory - implements FilterFactory { - constructor(private localityStatsReporter: XdsClusterLocalityStats) {} - - createFilter(callStream: Call): CallEndTrackingFilter { - return new CallEndTrackingFilter(this.localityStatsReporter); - } -} - /** * Picker that delegates picking to another picker, and reports when calls * created using those picks start and end. @@ -145,17 +121,6 @@ class LoadReportingPicker implements Picker { pick(pickArgs: PickArgs): PickResult { const wrappedPick = this.wrappedPicker.pick(pickArgs); if (wrappedPick.pickResultType === PickResultType.COMPLETE) { - const trackingFilterFactory = new CallEndTrackingFilterFactory( - this.localityStatsReporter - ); - /* In the unlikely event that the wrappedPick already has an - * extraFilterFactory, preserve it in a FilterStackFactory. */ - const extraFilterFactory = wrappedPick.extraFilterFactory - ? new FilterStackFactory([ - wrappedPick.extraFilterFactory, - trackingFilterFactory, - ]) - : trackingFilterFactory; return { pickResultType: PickResultType.COMPLETE, subchannel: wrappedPick.subchannel, @@ -164,7 +129,10 @@ class LoadReportingPicker implements Picker { wrappedPick.onCallStarted?.(); this.localityStatsReporter.addCallStarted(); }, - extraFilterFactory: extraFilterFactory, + onCallEnded: status => { + wrappedPick.onCallEnded?.(status); + this.localityStatsReporter.addCallFinished(status !== Status.OK); + } }; } else { return wrappedPick; @@ -183,20 +151,14 @@ export class LrsLoadBalancer implements LoadBalancer { private localityStatsReporter: XdsClusterLocalityStats | null = null; constructor(private channelControlHelper: ChannelControlHelper) { - this.childBalancer = new ChildLoadBalancerHandler({ - createSubchannel: (subchannelAddress, subchannelArgs) => - channelControlHelper.createSubchannel( - subchannelAddress, - subchannelArgs - ), - requestReresolution: () => channelControlHelper.requestReresolution(), + this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(channelControlHelper, { updateState: (connectivityState: ConnectivityState, picker: Picker) => { if (this.localityStatsReporter !== null) { picker = new LoadReportingPicker(picker, this.localityStatsReporter); } channelControlHelper.updateState(connectivityState, picker); }, - }); + })); } updateAddressList( @@ -207,7 +169,7 @@ export class LrsLoadBalancer implements LoadBalancer { if (!(lbConfig instanceof LrsLoadBalancingConfig)) { return; } - this.localityStatsReporter = getSingletonXdsClient().addClusterLocalityStats( + this.localityStatsReporter = (attributes.xdsClient as XdsClient).addClusterLocalityStats( lbConfig.getLrsLoadReportingServerName(), lbConfig.getClusterName(), lbConfig.getEdsServiceName(), diff --git a/packages/grpc-js-xds/src/load-balancer-priority.ts b/packages/grpc-js-xds/src/load-balancer-priority.ts index 872ed7d1b..12037a777 100644 --- a/packages/grpc-js-xds/src/load-balancer-priority.ts +++ b/packages/grpc-js-xds/src/load-balancer-priority.ts @@ -115,7 +115,6 @@ interface PriorityChildBalancer { resetBackoff(): void; deactivate(): void; maybeReactivate(): void; - cancelFailoverTimer(): void; isFailoverTimerPending(): boolean; getConnectivityState(): ConnectivityState; getPicker(): Picker; @@ -138,31 +137,32 @@ export class PriorityLoadBalancer implements LoadBalancer { private childBalancer: ChildLoadBalancerHandler; private failoverTimer: NodeJS.Timer | null = null; private deactivationTimer: NodeJS.Timer | null = null; + private seenReadyOrIdleSinceTransientFailure = false; constructor(private parent: PriorityLoadBalancer, private name: string) { - this.childBalancer = new ChildLoadBalancerHandler({ - createSubchannel: ( - subchannelAddress: SubchannelAddress, - subchannelArgs: ChannelOptions - ) => { - return this.parent.channelControlHelper.createSubchannel( - subchannelAddress, - subchannelArgs - ); - }, + this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, { updateState: (connectivityState: ConnectivityState, picker: Picker) => { this.updateState(connectivityState, picker); }, - requestReresolution: () => { - this.parent.channelControlHelper.requestReresolution(); - }, - }); + })); this.picker = new QueuePicker(this.childBalancer); + this.startFailoverTimer(); } private updateState(connectivityState: ConnectivityState, picker: Picker) { trace('Child ' + this.name + ' ' + ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[connectivityState]); this.connectivityState = connectivityState; this.picker = picker; + if (connectivityState === ConnectivityState.CONNECTING) { + if (this.seenReadyOrIdleSinceTransientFailure && this.failoverTimer === null) { + this.startFailoverTimer(); + } + } else if (connectivityState === ConnectivityState.READY || connectivityState === ConnectivityState.IDLE) { + this.seenReadyOrIdleSinceTransientFailure = true; + this.cancelFailoverTimer(); + } else if (connectivityState === ConnectivityState.TRANSIENT_FAILURE) { + this.seenReadyOrIdleSinceTransientFailure = false; + this.cancelFailoverTimer(); + } this.parent.onChildStateChange(this); } @@ -186,13 +186,9 @@ export class PriorityLoadBalancer implements LoadBalancer { attributes: { [key: string]: unknown } ): void { this.childBalancer.updateAddressList(addressList, lbConfig, attributes); - this.startFailoverTimer(); } exitIdle() { - if (this.connectivityState === ConnectivityState.IDLE) { - this.startFailoverTimer(); - } this.childBalancer.exitIdle(); } @@ -216,7 +212,7 @@ export class PriorityLoadBalancer implements LoadBalancer { } } - cancelFailoverTimer() { + private cancelFailoverTimer() { if (this.failoverTimer !== null) { clearTimeout(this.failoverTimer); this.failoverTimer = null; @@ -270,14 +266,8 @@ export class PriorityLoadBalancer implements LoadBalancer { * Current chosen priority that requests are sent to */ private currentPriority: number | null = null; - /** - * After an update, this preserves the currently selected child from before - * the update. We continue to use that child until it disconnects, or - * another higher-priority child connects, or it is deleted because it is not - * in the new priority list at all and its retention interval has expired, or - * we try and fail to connect to every child in the new priority list. - */ - private currentChildFromBeforeUpdate: PriorityChildBalancer | null = null; + + private updatesPaused = false; constructor(private channelControlHelper: ChannelControlHelper) {} @@ -298,57 +288,14 @@ export class PriorityLoadBalancer implements LoadBalancer { private onChildStateChange(child: PriorityChildBalancer) { const childState = child.getConnectivityState(); trace('Child ' + child.getName() + ' transitioning to ' + ConnectivityState[childState]); - if (child === this.currentChildFromBeforeUpdate) { - if ( - childState === ConnectivityState.READY || - childState === ConnectivityState.IDLE - ) { - this.updateState(childState, child.getPicker()); - } else { - this.currentChildFromBeforeUpdate = null; - this.tryNextPriority(true); - } - return; - } - const childPriority = this.priorities.indexOf(child.getName()); - if (childPriority < 0) { - // child is not in the priority list, ignore updates - return; - } - if (this.currentPriority !== null && childPriority > this.currentPriority) { - // child is lower priority than the currently selected child, ignore updates - return; - } - if (childState === ConnectivityState.TRANSIENT_FAILURE) { - /* Report connecting if and only if the currently selected child is the - * one entering TRANSIENT_FAILURE */ - this.tryNextPriority(childPriority === this.currentPriority); - return; - } - if (this.currentPriority === null || childPriority < this.currentPriority) { - /* In this case, either there is no currently selected child or this - * child is higher priority than the currently selected child, so we want - * to switch to it if it is READY or IDLE. */ - if ( - childState === ConnectivityState.READY || - childState === ConnectivityState.IDLE - ) { - this.selectPriority(childPriority); - } + if (this.updatesPaused) { return; } - /* The currently selected child has updated state to something other than - * TRANSIENT_FAILURE, so we pass that update along */ - this.updateState(childState, child.getPicker()); + this.choosePriority(); } private deleteChild(child: PriorityChildBalancer) { - if (child === this.currentChildFromBeforeUpdate) { - this.currentChildFromBeforeUpdate = null; - /* If we get to this point, the currentChildFromBeforeUpdate was still in - * use, so we are still trying to connect to the specified priorities */ - this.tryNextPriority(true); - } + this.children.delete(child.getName()); } /** @@ -357,35 +304,31 @@ export class PriorityLoadBalancer implements LoadBalancer { * child connects. * @param priority */ - private selectPriority(priority: number) { + private selectPriority(priority: number, deactivateLowerPriorities: boolean) { this.currentPriority = priority; const chosenChild = this.children.get(this.priorities[priority])!; - chosenChild.cancelFailoverTimer(); this.updateState( chosenChild.getConnectivityState(), chosenChild.getPicker() ); - this.currentChildFromBeforeUpdate = null; - // Deactivate each child of lower priority than the chosen child - for (let i = priority + 1; i < this.priorities.length; i++) { - this.children.get(this.priorities[i])?.deactivate(); + if (deactivateLowerPriorities) { + for (let i = priority + 1; i < this.priorities.length; i++) { + this.children.get(this.priorities[i])?.deactivate(); + } } } - /** - * Check each child in priority order until we find one to use - * @param reportConnecting Whether we should report a CONNECTING state if we - * stop before picking a specific child. This should be true when we have - * not already selected a child. - */ - private tryNextPriority(reportConnecting: boolean) { - for (const [index, childName] of this.priorities.entries()) { + private choosePriority() { + if (this.priorities.length === 0) { + this.updateState(ConnectivityState.TRANSIENT_FAILURE, new UnavailablePicker({code: Status.UNAVAILABLE, details: 'priority policy has empty priority list', metadata: new Metadata()})); + return; + } + + for (const [priority, childName] of this.priorities.entries()) { + trace('Trying priority ' + priority + ' child ' + childName); let child = this.children.get(childName); /* If the child doesn't already exist, create it and update it. */ if (child === undefined) { - if (reportConnecting) { - this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); - } child = new this.PriorityChildImpl(this, childName); this.children.set(childName, child); const childUpdate = this.latestUpdates.get(childName); @@ -396,36 +339,38 @@ export class PriorityLoadBalancer implements LoadBalancer { this.latestAttributes ); } + } else { + /* We're going to try to use this child, so reactivate it if it has been + * deactivated */ + child.maybeReactivate(); } - /* We're going to try to use this child, so reactivate it if it has been - * deactivated */ - child.maybeReactivate(); if ( child.getConnectivityState() === ConnectivityState.READY || child.getConnectivityState() === ConnectivityState.IDLE ) { - this.selectPriority(index); + this.selectPriority(priority, true); return; } if (child.isFailoverTimerPending()) { + this.selectPriority(priority, false); /* This child is still trying to connect. Wait until its failover timer - * has ended to continue to the next one */ - if (reportConnecting) { - this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); - } + * has ended to continue to the next one */ return; } } - this.currentPriority = null; - this.currentChildFromBeforeUpdate = null; - this.updateState( - ConnectivityState.TRANSIENT_FAILURE, - new UnavailablePicker({ - code: Status.UNAVAILABLE, - details: 'No ready priority', - metadata: new Metadata(), - }) - ); + + /* If we didn't find any priority to try, pick the first one in the state + * CONNECTING */ + for (const [priority, childName] of this.priorities.entries()) { + let child = this.children.get(childName)!; + if (child.getConnectivityState() === ConnectivityState.CONNECTING) { + this.selectPriority(priority, false); + return; + } + } + + // Did not find any child in CONNECTING, delegate to last child + this.selectPriority(this.priorities.length - 1, false); } updateAddressList( @@ -467,15 +412,10 @@ export class PriorityLoadBalancer implements LoadBalancer { } childAddressList.push(childAddress); } - if (this.currentPriority !== null) { - this.currentChildFromBeforeUpdate = this.children.get( - this.priorities[this.currentPriority] - )!; - this.currentPriority = null; - } this.latestAttributes = attributes; this.latestUpdates.clear(); this.priorities = lbConfig.getPriorities(); + this.updatesPaused = true; /* Pair up the new child configs with the corresponding address lists, and * update all existing children with their new configs */ for (const [childName, childConfig] of lbConfig.getChildren()) { @@ -504,8 +444,8 @@ export class PriorityLoadBalancer implements LoadBalancer { child.deactivate(); } } - // Only report connecting if there are no existing children - this.tryNextPriority(this.children.size === 0); + this.updatesPaused = false; + this.choosePriority(); } exitIdle(): void { if (this.currentPriority !== null) { @@ -522,8 +462,6 @@ export class PriorityLoadBalancer implements LoadBalancer { child.destroy(); } this.children.clear(); - this.currentChildFromBeforeUpdate?.destroy(); - this.currentChildFromBeforeUpdate = null; } getTypeName(): string { return TYPE_NAME; diff --git a/packages/grpc-js-xds/src/load-balancer-weighted-target.ts b/packages/grpc-js-xds/src/load-balancer-weighted-target.ts index 44a6acf11..7cd92d98b 100644 --- a/packages/grpc-js-xds/src/load-balancer-weighted-target.ts +++ b/packages/grpc-js-xds/src/load-balancer-weighted-target.ts @@ -119,31 +119,16 @@ class WeightedTargetPicker implements Picker { pick(pickArgs: PickArgs): PickResult { // num | 0 is equivalent to floor(num) const selection = (Math.random() * this.rangeTotal) | 0; - - /* Binary search for the element of the list such that - * pickerList[index - 1].rangeEnd <= selection < pickerList[index].rangeEnd - */ - let mid = 0; - let startIndex = 0; - let endIndex = this.pickerList.length - 1; - let index = 0; - while (endIndex > startIndex) { - mid = ((startIndex + endIndex) / 2) | 0; - if (this.pickerList[mid].rangeEnd > selection) { - endIndex = mid; - } else if (this.pickerList[mid].rangeEnd < selection) { - startIndex = mid + 1; - } else { - // + 1 here because the range is exclusive at the top end - index = mid + 1; - break; + + for (const entry of this.pickerList) { + if (selection < entry.rangeEnd) { + return entry.picker.pick(pickArgs); } } - if (index === 0) { - index = startIndex; - } - return this.pickerList[index].picker.pick(pickArgs); + /* Default to first element if the iteration doesn't find anything for some + * reason. */ + return this.pickerList[0].picker.pick(pickArgs); } } @@ -168,17 +153,11 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { private weight: number = 0; constructor(private parent: WeightedTargetLoadBalancer, private name: string) { - this.childBalancer = new ChildLoadBalancerHandler({ - createSubchannel: (subchannelAddress, subchannelOptions) => { - return this.parent.channelControlHelper.createSubchannel(subchannelAddress, subchannelOptions); - }, - updateState: (connectivityState, picker) => { + this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, { + updateState: (connectivityState: ConnectivityState, picker: Picker) => { this.updateState(connectivityState, picker); }, - requestReresolution: () => { - this.parent.channelControlHelper.requestReresolution(); - } - }); + })); this.picker = new QueuePicker(this.childBalancer); } @@ -187,7 +166,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { trace('Target ' + this.name + ' ' + ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[connectivityState]); this.connectivityState = connectivityState; this.picker = picker; - this.parent.updateState(); + this.parent.maybeUpdateState(); } updateAddressList(addressList: SubchannelAddress[], lbConfig: WeightedTarget, attributes: { [key: string]: unknown; }): void { @@ -244,9 +223,16 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { * List of current target names. */ private targetList: string[] = []; + private updatesPaused = false; constructor(private channelControlHelper: ChannelControlHelper) {} + private maybeUpdateState() { + if (!this.updatesPaused) { + this.updateState() + } + } + private updateState() { const pickerList: WeightedPicker[] = []; let end = 0; @@ -349,6 +335,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { childAddressList.push(childAddress); } + this.updatesPaused = true; this.targetList = Array.from(lbConfig.getTargets().keys()); for (const [targetName, targetConfig] of lbConfig.getTargets()) { let target = this.targets.get(targetName); @@ -370,6 +357,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer { target.deactivate(); } } + this.updatesPaused = false; this.updateState(); } diff --git a/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts b/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts index 920a43db9..bfdb4dccc 100644 --- a/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts +++ b/packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts @@ -107,8 +107,8 @@ class XdsClusterManagerPicker implements Picker { metadata: new Metadata(), }, subchannel: null, - extraFilterFactory: null, - onCallStarted: null + onCallStarted: null, + onCallEnded: null }; } } @@ -131,17 +131,11 @@ class XdsClusterManager implements LoadBalancer { private childBalancer: ChildLoadBalancerHandler; constructor(private parent: XdsClusterManager, private name: string) { - this.childBalancer = new ChildLoadBalancerHandler({ - createSubchannel: (subchannelAddress, subchannelOptions) => { - return this.parent.channelControlHelper.createSubchannel(subchannelAddress, subchannelOptions); - }, - updateState: (connectivityState, picker) => { + this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, { + updateState: (connectivityState: ConnectivityState, picker: Picker) => { this.updateState(connectivityState, picker); }, - requestReresolution: () => { - this.parent.channelControlHelper.requestReresolution(); - } - }); + })); this.picker = new QueuePicker(this.childBalancer); } @@ -150,7 +144,7 @@ class XdsClusterManager implements LoadBalancer { trace('Child ' + this.name + ' ' + ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[connectivityState]); this.connectivityState = connectivityState; this.picker = picker; - this.parent.updateState(); + this.parent.maybeUpdateState(); } updateAddressList(addressList: SubchannelAddress[], lbConfig: ClusterManagerChild, attributes: { [key: string]: unknown; }): void { const childConfig = getFirstUsableConfig(lbConfig.child_policy); @@ -179,8 +173,15 @@ class XdsClusterManager implements LoadBalancer { private children: Map = new Map(); // Shutdown is a placeholder value that will never appear in normal operation. private currentState: ConnectivityState = ConnectivityState.SHUTDOWN; + private updatesPaused = false; constructor(private channelControlHelper: ChannelControlHelper) {} + private maybeUpdateState() { + if (!this.updatesPaused) { + this.updateState(); + } + } + private updateState() { const pickerMap: Map = new Map(); let anyReady = false; @@ -256,6 +257,7 @@ class XdsClusterManager implements LoadBalancer { namesToRemove.push(name); } } + this.updatesPaused = true; for (const name of namesToRemove) { this.children.get(name)!.destroy(); this.children.delete(name); @@ -268,6 +270,7 @@ class XdsClusterManager implements LoadBalancer { this.children.set(name, newChild); } } + this.updatesPaused = false; this.updateState(); } exitIdle(): void { diff --git a/packages/grpc-js-xds/src/matcher.ts b/packages/grpc-js-xds/src/matcher.ts index 14cb7f672..b173c30e0 100644 --- a/packages/grpc-js-xds/src/matcher.ts +++ b/packages/grpc-js-xds/src/matcher.ts @@ -16,6 +16,7 @@ import { Metadata } from "@grpc/grpc-js"; import { RE2 } from "re2-wasm"; +import { Fraction, fractionToString } from "./fraction"; /** * An object representing a predicate that determines whether a given @@ -210,15 +211,6 @@ export class PathSafeRegexValueMatcher { } } -export interface Fraction { - numerator: number; - denominator: number; -} - -function fractionToString(fraction: Fraction): string { - return `${fraction.numerator}/${fraction.denominator}`; -} - export class FullMatcher implements Matcher { constructor(private pathMatcher: ValueMatcher, private headerMatchers: Matcher[], private fraction: Fraction | null) {} diff --git a/packages/grpc-js-xds/src/protobuf-any.ts b/packages/grpc-js-xds/src/protobuf-any.ts new file mode 100644 index 000000000..cfee35f91 --- /dev/null +++ b/packages/grpc-js-xds/src/protobuf-any.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This is a non-public, unstable API, but it's very convenient +import { loadProtosWithOptionsSync } from '@grpc/proto-loader/build/src/util'; +import { Any__Output } from './generated/google/protobuf/Any'; + +function parseAnyMessage(encodedMessage: Any__Output) { + +} \ No newline at end of file diff --git a/packages/grpc-js-xds/src/resolver-xds.ts b/packages/grpc-js-xds/src/resolver-xds.ts index aee7290bb..9879a2c6e 100644 --- a/packages/grpc-js-xds/src/resolver-xds.ts +++ b/packages/grpc-js-xds/src/resolver-xds.ts @@ -26,20 +26,29 @@ import ResolverListener = experimental.ResolverListener; import uriToString = experimental.uriToString; import ServiceConfig = experimental.ServiceConfig; import registerResolver = experimental.registerResolver; -import { Listener__Output } from './generated/envoy/api/v2/Listener'; +import { Listener__Output } from './generated/envoy/config/listener/v3/Listener'; import { Watcher } from './xds-stream-state/xds-stream-state'; -import { RouteConfiguration__Output } from './generated/envoy/api/v2/RouteConfiguration'; -import { HttpConnectionManager__Output } from './generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager'; +import { RouteConfiguration__Output } from './generated/envoy/config/route/v3/RouteConfiguration'; +import { HttpConnectionManager__Output } from './generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager'; import { CdsLoadBalancingConfig } from './load-balancer-cds'; -import { VirtualHost__Output } from './generated/envoy/api/v2/route/VirtualHost'; -import { RouteMatch__Output } from './generated/envoy/api/v2/route/RouteMatch'; -import { HeaderMatcher__Output } from './generated/envoy/api/v2/route/HeaderMatcher'; +import { VirtualHost__Output } from './generated/envoy/config/route/v3/VirtualHost'; +import { RouteMatch__Output } from './generated/envoy/config/route/v3/RouteMatch'; +import { HeaderMatcher__Output } from './generated/envoy/config/route/v3/HeaderMatcher'; import ConfigSelector = experimental.ConfigSelector; import LoadBalancingConfig = experimental.LoadBalancingConfig; import { XdsClusterManagerLoadBalancingConfig } from './load-balancer-xds-cluster-manager'; -import { ExactValueMatcher, Fraction, FullMatcher, HeaderMatcher, Matcher, PathExactValueMatcher, PathPrefixValueMatcher, PathSafeRegexValueMatcher, PrefixValueMatcher, PresentValueMatcher, RangeValueMatcher, RejectValueMatcher, SafeRegexValueMatcher, SuffixValueMatcher, ValueMatcher } from './matcher'; +import { ExactValueMatcher, FullMatcher, HeaderMatcher, Matcher, PathExactValueMatcher, PathPrefixValueMatcher, PathSafeRegexValueMatcher, PrefixValueMatcher, PresentValueMatcher, RangeValueMatcher, RejectValueMatcher, SafeRegexValueMatcher, SuffixValueMatcher, ValueMatcher } from './matcher'; +import { envoyFractionToFraction, Fraction } from "./fraction"; import { RouteAction, SingleClusterRouteAction, WeightedCluster, WeightedClusterRouteAction } from './route-action'; -import { LogVerbosity } from '@grpc/grpc-js/build/src/constants'; +import { decodeSingleResource, HTTP_CONNECTION_MANGER_TYPE_URL } from './resources'; +import Duration = experimental.Duration; +import { Duration__Output } from './generated/google/protobuf/Duration'; +import { createHttpFilter, HttpFilterConfig, parseOverrideFilterConfig, parseTopLevelFilterConfig } from './http-filter'; +import { EXPERIMENTAL_FAULT_INJECTION, EXPERIMENTAL_RETRY } from './environment'; +import Filter = experimental.Filter; +import FilterFactory = experimental.FilterFactory; +import RetryPolicy = experimental.RetryPolicy; +import { validateBootstrapConfig } from './xds-bootstrap'; const TRACER_NAME = 'xds_resolver'; @@ -152,12 +161,6 @@ function getPredicateForHeaderMatcher(headerMatch: HeaderMatcher__Output): Match return new HeaderMatcher(headerMatch.name, valueChecker, headerMatch.invert_match); } -const RUNTIME_FRACTION_DENOMINATOR_VALUES = { - HUNDRED: 100, - TEN_THOUSAND: 10_000, - MILLION: 1_000_000 -} - function getPredicateForMatcher(routeMatch: RouteMatch__Output): Matcher { let pathMatcher: ValueMatcher; const caseInsensitive = routeMatch.case_sensitive?.value === false; @@ -179,14 +182,45 @@ function getPredicateForMatcher(routeMatch: RouteMatch__Output): Matcher { if (!routeMatch.runtime_fraction?.default_value) { runtimeFraction = null; } else { - runtimeFraction = { - numerator: routeMatch.runtime_fraction.default_value.numerator, - denominator: RUNTIME_FRACTION_DENOMINATOR_VALUES[routeMatch.runtime_fraction.default_value.denominator] - }; + runtimeFraction = envoyFractionToFraction(routeMatch.runtime_fraction.default_value) } return new FullMatcher(pathMatcher, headerMatchers, runtimeFraction); } +/** + * Convert a Duration protobuf message object to a Duration object as used in + * the ServiceConfig definition. The difference is that the protobuf message + * defines seconds as a long, which is represented as a string in JavaScript, + * and the one used in the service config defines it as a number. + * @param duration + */ +function protoDurationToDuration(duration: Duration__Output): Duration { + return { + seconds: Number.parseInt(duration.seconds), + nanos: duration.nanos + } +} + +function protoDurationToSecondsString(duration: Duration__Output): string { + return `${duration.seconds + duration.nanos / 1_000_000_000}s`; +} + +const DEFAULT_RETRY_BASE_INTERVAL = '0.025s' + +function getDefaultRetryMaxInterval(baseInterval: string): string { + return `${Number.parseFloat(baseInterval.substring(0, baseInterval.length - 1)) * 10}s`; +} + +const BOOTSTRAP_CONFIG_KEY = 'grpc.TEST_ONLY_DO_NOT_USE_IN_PROD.xds_bootstrap_config'; + +const RETRY_CODES: {[key: string]: status} = { + 'cancelled': status.CANCELLED, + 'deadline-exceeded': status.DEADLINE_EXCEEDED, + 'internal': status.INTERNAL, + 'resource-exhausted': status.RESOURCE_EXHAUSTED, + 'unavailable': status.UNAVAILABLE +}; + class XdsResolver implements Resolver { private hasReportedSuccess = false; @@ -203,31 +237,58 @@ class XdsResolver implements Resolver { private clusterRefcounts = new Map(); + private latestDefaultTimeout: Duration | undefined = undefined; + + private ldsHttpFilterConfigs: {name: string, config: HttpFilterConfig}[] = []; + + private xdsClient: XdsClient; + constructor( private target: GrpcUri, private listener: ResolverListener, private channelOptions: ChannelOptions ) { + if (channelOptions[BOOTSTRAP_CONFIG_KEY]) { + const parsedConfig = JSON.parse(channelOptions[BOOTSTRAP_CONFIG_KEY]); + const validatedConfig = validateBootstrapConfig(parsedConfig); + this.xdsClient = new XdsClient(validatedConfig); + } else { + this.xdsClient = getSingletonXdsClient(); + } this.ldsWatcher = { onValidUpdate: (update: Listener__Output) => { - const httpConnectionManager = update.api_listener! - .api_listener as protoLoader.AnyExtension & - HttpConnectionManager__Output; + const httpConnectionManager = decodeSingleResource(HTTP_CONNECTION_MANGER_TYPE_URL, update.api_listener!.api_listener!.value); + const defaultTimeout = httpConnectionManager.common_http_protocol_options?.idle_timeout; + if (defaultTimeout === null || defaultTimeout === undefined) { + this.latestDefaultTimeout = undefined; + } else { + this.latestDefaultTimeout = protoDurationToDuration(defaultTimeout); + } + if (EXPERIMENTAL_FAULT_INJECTION) { + this.ldsHttpFilterConfigs = []; + for (const filter of httpConnectionManager.http_filters) { + // typed_config must be set here, or validation would have failed + const filterConfig = parseTopLevelFilterConfig(filter.typed_config!); + if (filterConfig) { + this.ldsHttpFilterConfigs.push({name: filter.name, config: filterConfig}); + } + } + } switch (httpConnectionManager.route_specifier) { case 'rds': { const routeConfigName = httpConnectionManager.rds!.route_config_name; if (this.latestRouteConfigName !== routeConfigName) { if (this.latestRouteConfigName !== null) { - getSingletonXdsClient().removeRouteWatcher(this.latestRouteConfigName, this.rdsWatcher); + this.xdsClient.removeRouteWatcher(this.latestRouteConfigName, this.rdsWatcher); } - getSingletonXdsClient().addRouteWatcher(httpConnectionManager.rds!.route_config_name, this.rdsWatcher); + this.xdsClient.addRouteWatcher(httpConnectionManager.rds!.route_config_name, this.rdsWatcher); this.latestRouteConfigName = routeConfigName; } break; } case 'route_config': if (this.latestRouteConfigName) { - getSingletonXdsClient().removeRouteWatcher(this.latestRouteConfigName, this.rdsWatcher); + this.xdsClient.removeRouteWatcher(this.latestRouteConfigName, this.rdsWatcher); } this.handleRouteConfig(httpConnectionManager.route_config!); break; @@ -287,33 +348,155 @@ class XdsResolver implements Resolver { private handleRouteConfig(routeConfig: RouteConfiguration__Output) { this.latestRouteConfig = routeConfig; - const virtualHost = findVirtualHostForDomain(routeConfig.virtual_hosts, this.target.path); + /* Select the virtual host using the default authority override if it + * exists, and the channel target otherwise. */ + const hostDomain = this.channelOptions['grpc.default_authority'] ?? this.target.path; + const virtualHost = findVirtualHostForDomain(routeConfig.virtual_hosts, hostDomain); if (virtualHost === null) { - this.reportResolutionError('No matching route found'); + this.reportResolutionError('No matching route found for ' + hostDomain); return; } + const virtualHostHttpFilterOverrides = new Map(); + if (EXPERIMENTAL_FAULT_INJECTION) { + for (const [name, filter] of Object.entries(virtualHost.typed_per_filter_config ?? {})) { + const parsedConfig = parseOverrideFilterConfig(filter); + if (parsedConfig) { + virtualHostHttpFilterOverrides.set(name, parsedConfig); + } + } + } trace('Received virtual host config ' + JSON.stringify(virtualHost, undefined, 2)); const allConfigClusters = new Set(); const matchList: {matcher: Matcher, action: RouteAction}[] = []; for (const route of virtualHost.routes) { let routeAction: RouteAction; + let timeout: Duration | undefined; + /* For field prioritization see + * https://github.com/grpc/proposal/blob/master/A31-xds-timeout-support-and-config-selector.md#supported-fields + */ + if (route.route?.max_stream_duration?.grpc_timeout_header_max) { + timeout = protoDurationToDuration(route.route.max_stream_duration.grpc_timeout_header_max); + } else if (route.route?.max_stream_duration?.max_stream_duration) { + timeout = protoDurationToDuration(route.route.max_stream_duration.max_stream_duration); + } else { + timeout = this.latestDefaultTimeout; + } + // "A value of 0 indicates the application's deadline is used without modification." + if (timeout?.seconds === 0 && timeout.nanos === 0) { + timeout = undefined; + } + const routeHttpFilterOverrides = new Map(); + if (EXPERIMENTAL_FAULT_INJECTION) { + for (const [name, filter] of Object.entries(route.typed_per_filter_config ?? {})) { + const parsedConfig = parseOverrideFilterConfig(filter); + if (parsedConfig) { + routeHttpFilterOverrides.set(name, parsedConfig); + } + } + } + let retryPolicy: RetryPolicy | undefined = undefined; + if (EXPERIMENTAL_RETRY) { + const retryConfig = route.route!.retry_policy ?? virtualHost.retry_policy; + if (retryConfig) { + const retryableStatusCodes = []; + for (const code of retryConfig.retry_on.split(',')) { + if (RETRY_CODES[code]) { + retryableStatusCodes.push(RETRY_CODES[code]); + } + } + if (retryableStatusCodes.length > 0) { + const baseInterval = retryConfig.retry_back_off?.base_interval ? + protoDurationToSecondsString(retryConfig.retry_back_off.base_interval) : + DEFAULT_RETRY_BASE_INTERVAL; + const maxInterval = retryConfig.retry_back_off?.max_interval ? + protoDurationToSecondsString(retryConfig.retry_back_off.max_interval) : + getDefaultRetryMaxInterval(baseInterval); + retryPolicy = { + backoffMultiplier: 2, + initialBackoff: baseInterval, + maxBackoff: maxInterval, + maxAttempts: (retryConfig.num_retries?.value ?? 1) + 1, + retryableStatusCodes: retryableStatusCodes + }; + } + } + } switch (route.route!.cluster_specifier) { case 'cluster_header': continue; case 'cluster':{ const cluster = route.route!.cluster!; allConfigClusters.add(cluster); - routeAction = new SingleClusterRouteAction(cluster); + const extraFilterFactories: FilterFactory[] = []; + if (EXPERIMENTAL_FAULT_INJECTION) { + for (const filterConfig of this.ldsHttpFilterConfigs) { + if (routeHttpFilterOverrides.has(filterConfig.name)) { + const filter = createHttpFilter(filterConfig.config, routeHttpFilterOverrides.get(filterConfig.name)!); + if (filter) { + extraFilterFactories.push(filter); + } + } else if (virtualHostHttpFilterOverrides.has(filterConfig.name)) { + const filter = createHttpFilter(filterConfig.config, virtualHostHttpFilterOverrides.get(filterConfig.name)!); + if (filter) { + extraFilterFactories.push(filter); + } + } else { + const filter = createHttpFilter(filterConfig.config); + if (filter) { + extraFilterFactories.push(filter); + } + } + } + } + routeAction = new SingleClusterRouteAction(cluster, {name: [], timeout: timeout, retryPolicy: retryPolicy}, extraFilterFactories); break; } case 'weighted_clusters': { const weightedClusters: WeightedCluster[] = []; for (const clusterWeight of route.route!.weighted_clusters!.clusters) { allConfigClusters.add(clusterWeight.name); - weightedClusters.push({name: clusterWeight.name, weight: clusterWeight.weight?.value ?? 0}); + const extraFilterFactories: FilterFactory[] = []; + const clusterHttpFilterOverrides = new Map(); + if (EXPERIMENTAL_FAULT_INJECTION) { + for (const [name, filter] of Object.entries(clusterWeight.typed_per_filter_config ?? {})) { + const parsedConfig = parseOverrideFilterConfig(filter); + if (parsedConfig) { + clusterHttpFilterOverrides.set(name, parsedConfig); + } + } + for (const filterConfig of this.ldsHttpFilterConfigs) { + if (clusterHttpFilterOverrides.has(filterConfig.name)) { + const filter = createHttpFilter(filterConfig.config, clusterHttpFilterOverrides.get(filterConfig.name)!); + if (filter) { + extraFilterFactories.push(filter); + } + } else if (routeHttpFilterOverrides.has(filterConfig.name)) { + const filter = createHttpFilter(filterConfig.config, routeHttpFilterOverrides.get(filterConfig.name)!); + if (filter) { + extraFilterFactories.push(filter); + } + } else if (virtualHostHttpFilterOverrides.has(filterConfig.name)) { + const filter = createHttpFilter(filterConfig.config, virtualHostHttpFilterOverrides.get(filterConfig.name)!); + if (filter) { + extraFilterFactories.push(filter); + } + } else { + const filter = createHttpFilter(filterConfig.config); + if (filter) { + extraFilterFactories.push(filter); + } + } + } + } + weightedClusters.push({name: clusterWeight.name, weight: clusterWeight.weight?.value ?? 0, dynamicFilterFactories: extraFilterFactories}); } - routeAction = new WeightedClusterRouteAction(weightedClusters, route.route!.weighted_clusters!.total_weight?.value ?? 100); + routeAction = new WeightedClusterRouteAction(weightedClusters, route.route!.weighted_clusters!.total_weight?.value ?? 100, {name: [], timeout: timeout, retryPolicy: retryPolicy}); + break; } + default: + /* The validation logic should prevent us from reaching this point. + * This is just for the type checker. */ + continue; } const routeMatcher = getPredicateForMatcher(route.match!); matchList.push({matcher: routeMatcher, action: routeAction}); @@ -339,16 +522,17 @@ class XdsResolver implements Resolver { const configSelector: ConfigSelector = (methodName, metadata) => { for (const {matcher, action} of matchList) { if (matcher.apply(methodName, metadata)) { - const clusterName = action.getCluster(); - this.refCluster(clusterName); + const clusterResult = action.getCluster(); + this.refCluster(clusterResult.name); const onCommitted = () => { - this.unrefCluster(clusterName); + this.unrefCluster(clusterResult.name); } return { - methodConfig: {name: []}, + methodConfig: clusterResult.methodConfig, onCommitted: onCommitted, - pickInformation: {cluster: clusterName}, - status: status.OK + pickInformation: {cluster: clusterResult.name}, + status: status.OK, + dynamicFilterFactories: clusterResult.dynamicFilterFactories }; } } @@ -356,7 +540,8 @@ class XdsResolver implements Resolver { methodConfig: {name: []}, // cluster won't be used here, but it's set because of some TypeScript weirdness pickInformation: {cluster: ''}, - status: status.UNAVAILABLE + status: status.UNAVAILABLE, + dynamicFilterFactories: [] }; }; trace('Created ConfigSelector with configuration:'); @@ -373,7 +558,7 @@ class XdsResolver implements Resolver { methodConfig: [], loadBalancingConfig: [lbPolicyConfig] } - this.listener.onSuccessfulResolution([], serviceConfig, null, configSelector, {}); + this.listener.onSuccessfulResolution([], serviceConfig, null, configSelector, {xdsClient: this.xdsClient}); } private reportResolutionError(reason: string) { @@ -390,15 +575,15 @@ class XdsResolver implements Resolver { // Wait until updateResolution is called once to start the xDS requests if (!this.isLdsWatcherActive) { trace('Starting resolution for target ' + uriToString(this.target)); - getSingletonXdsClient().addListenerWatcher(this.target.path, this.ldsWatcher); + this.xdsClient.addListenerWatcher(this.target.path, this.ldsWatcher); this.isLdsWatcherActive = true; } } destroy() { - getSingletonXdsClient().removeListenerWatcher(this.target.path, this.ldsWatcher); + this.xdsClient.removeListenerWatcher(this.target.path, this.ldsWatcher); if (this.latestRouteConfigName) { - getSingletonXdsClient().removeRouteWatcher(this.latestRouteConfigName, this.rdsWatcher); + this.xdsClient.removeRouteWatcher(this.latestRouteConfigName, this.rdsWatcher); } } diff --git a/packages/grpc-js-xds/src/resources.ts b/packages/grpc-js-xds/src/resources.ts new file mode 100644 index 000000000..0972ce97d --- /dev/null +++ b/packages/grpc-js-xds/src/resources.ts @@ -0,0 +1,89 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// This is a non-public, unstable API, but it's very convenient +import { loadProtosWithOptionsSync } from '@grpc/proto-loader/build/src/util'; +import { Cluster__Output } from './generated/envoy/config/cluster/v3/Cluster'; +import { ClusterLoadAssignment__Output } from './generated/envoy/config/endpoint/v3/ClusterLoadAssignment'; +import { Listener__Output } from './generated/envoy/config/listener/v3/Listener'; +import { RouteConfiguration__Output } from './generated/envoy/config/route/v3/RouteConfiguration'; +import { HttpConnectionManager__Output } from './generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager'; + +export const EDS_TYPE_URL = 'type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment'; +export const CDS_TYPE_URL = 'type.googleapis.com/envoy.config.cluster.v3.Cluster'; +export const LDS_TYPE_URL = 'type.googleapis.com/envoy.config.listener.v3.Listener'; +export const RDS_TYPE_URL = 'type.googleapis.com/envoy.config.route.v3.RouteConfiguration'; + +export type EdsTypeUrl = 'type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment'; +export type CdsTypeUrl = 'type.googleapis.com/envoy.config.cluster.v3.Cluster'; +export type LdsTypeUrl = 'type.googleapis.com/envoy.config.listener.v3.Listener'; +export type RdsTypeUrl = 'type.googleapis.com/envoy.config.route.v3.RouteConfiguration'; + +export type AdsTypeUrl = EdsTypeUrl | CdsTypeUrl | RdsTypeUrl | LdsTypeUrl; + +export const HTTP_CONNECTION_MANGER_TYPE_URL = + 'type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager'; + +export type HttpConnectionManagerTypeUrl = 'type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager'; + +/** + * Map type URLs to their corresponding message types + */ +export type AdsOutputType = T extends EdsTypeUrl + ? ClusterLoadAssignment__Output + : T extends CdsTypeUrl + ? Cluster__Output + : T extends RdsTypeUrl + ? RouteConfiguration__Output + : T extends LdsTypeUrl + ? Listener__Output + : HttpConnectionManager__Output; + +const resourceRoot = loadProtosWithOptionsSync([ + 'envoy/config/listener/v3/listener.proto', + 'envoy/config/route/v3/route.proto', + 'envoy/config/cluster/v3/cluster.proto', + 'envoy/config/endpoint/v3/endpoint.proto', + 'envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto'], { + keepCase: true, + includeDirs: [ + // Paths are relative to src/build + __dirname + '/../../deps/envoy-api/', + __dirname + '/../../deps/xds/', + __dirname + '/../../deps/googleapis/', + __dirname + '/../../deps/protoc-gen-validate/', + ], + } +); + +const toObjectOptions = { + longs: String, + enums: String, + defaults: true, + oneofs: true +} + +export function decodeSingleResource(targetTypeUrl: T, message: Buffer): AdsOutputType { + const name = targetTypeUrl.substring(targetTypeUrl.lastIndexOf('/') + 1); + const type = resourceRoot.lookup(name); + if (type) { + const decodedMessage = (type as any).decode(message); + return decodedMessage.$type.toObject(decodedMessage, toObjectOptions) as AdsOutputType; + } else { + throw new Error(`ADS Error: unknown resource type ${targetTypeUrl}`); + } +} \ No newline at end of file diff --git a/packages/grpc-js-xds/src/route-action.ts b/packages/grpc-js-xds/src/route-action.ts index 4ba2b5908..5ae5885af 100644 --- a/packages/grpc-js-xds/src/route-action.ts +++ b/packages/grpc-js-xds/src/route-action.ts @@ -14,31 +14,58 @@ * limitations under the License. */ +import { experimental } from '@grpc/grpc-js'; +import Duration = experimental.Duration; +import Filter = experimental.Filter; +import FilterFactory = experimental.FilterFactory; +import MethodConfig = experimental.MethodConfig; + +export interface ClusterResult { + name: string; + methodConfig: MethodConfig; + dynamicFilterFactories: FilterFactory[]; +} + export interface RouteAction { toString(): string; - getCluster(): string; + getCluster(): ClusterResult; +} + +function durationToLogString(duration: Duration) { + const millis = Math.floor(duration.nanos / 1_000_000); + if (millis > 0) { + return duration.seconds + '.' + millis; + } else { + return '' + duration.seconds; + } } export class SingleClusterRouteAction implements RouteAction { - constructor(private cluster: string) {} + constructor(private cluster: string, private methodConfig: MethodConfig, private extraFilterFactories: FilterFactory[]) {} getCluster() { - return this.cluster; + return { + name: this.cluster, + methodConfig: this.methodConfig, + dynamicFilterFactories: this.extraFilterFactories + }; } toString() { - return 'SingleCluster(' + this.cluster + ')'; + return 'SingleCluster(' + this.cluster + ', ' + JSON.stringify(this.methodConfig) + ')'; } } export interface WeightedCluster { name: string; weight: number; + dynamicFilterFactories: FilterFactory[]; } interface ClusterChoice { name: string; numerator: number; + dynamicFilterFactories: FilterFactory[]; } export class WeightedClusterRouteAction implements RouteAction { @@ -46,12 +73,12 @@ export class WeightedClusterRouteAction implements RouteAction { * The weighted cluster choices represented as a CDF */ private clusterChoices: ClusterChoice[]; - constructor(private clusters: WeightedCluster[], private totalWeight: number) { + constructor(private clusters: WeightedCluster[], private totalWeight: number, private methodConfig: MethodConfig) { this.clusterChoices = []; let lastNumerator = 0; for (const clusterWeight of clusters) { lastNumerator += clusterWeight.weight; - this.clusterChoices.push({name: clusterWeight.name, numerator: lastNumerator}); + this.clusterChoices.push({name: clusterWeight.name, numerator: lastNumerator, dynamicFilterFactories: clusterWeight.dynamicFilterFactories}); } } @@ -59,14 +86,19 @@ export class WeightedClusterRouteAction implements RouteAction { const randomNumber = Math.random() * this.totalWeight; for (const choice of this.clusterChoices) { if (randomNumber < choice.numerator) { - return choice.name; + return { + name: choice.name, + methodConfig: this.methodConfig, + dynamicFilterFactories: choice.dynamicFilterFactories + }; } } // This should be prevented by the validation rules - return ''; + return {name: '', methodConfig: this.methodConfig, dynamicFilterFactories: []}; } toString() { - return 'WeightedCluster(' + this.clusters.map(({name, weight}) => '(' + name + ':' + weight + ')').join(', ') + ')'; + const clusterListString = this.clusters.map(({name, weight}) => '(' + name + ':' + weight + ')').join(', ') + return 'WeightedCluster(' + clusterListString + ', ' + JSON.stringify(this.methodConfig) + ')'; } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-bootstrap.ts b/packages/grpc-js-xds/src/xds-bootstrap.ts index 00e13d09f..72a0ca375 100644 --- a/packages/grpc-js-xds/src/xds-bootstrap.ts +++ b/packages/grpc-js-xds/src/xds-bootstrap.ts @@ -17,11 +17,23 @@ import * as fs from 'fs'; import { Struct } from './generated/google/protobuf/Struct'; -import { Node } from './generated/envoy/api/v2/core/Node'; import { Value } from './generated/google/protobuf/Value'; /* eslint-disable @typescript-eslint/no-explicit-any */ +export interface Locality { + region?: string; + zone?: string; + sub_zone?: string; +} + +export interface Node { + id: string, + locality: Locality; + cluster?: string; + metadata?: Struct; +} + export interface ChannelCredsConfig { type: string; config?: object; @@ -30,6 +42,7 @@ export interface ChannelCredsConfig { export interface XdsServerConfig { serverUri: string; channelCreds: ChannelCredsConfig[]; + serverFeatures: string[]; } export interface BootstrapInfo { @@ -81,9 +94,22 @@ function validateXdsServerConfig(obj: any): XdsServerConfig { 'xds_servers.channel_creds field: at least one entry is required' ); } + if ('server_features' in obj) { + if (!Array.isArray(obj.server_features)) { + throw new Error( + `xds_servers.server_features field: expected array, got ${typeof obj.server_features}` + ); + } + for (const feature of obj.server_features) { + if (typeof feature !== 'string') { + `xds_servers.server_features field element: expected string, got ${typeof feature}` + } + } + } return { serverUri: obj.server_uri, channelCreds: obj.channel_creds.map(validateChannelCredsConfig), + serverFeatures: obj.server_features ?? [] }; } @@ -149,7 +175,10 @@ function getStructFromJson(obj: any): Struct { * @param obj */ function validateNode(obj: any): Node { - const result: Node = {}; + const result: Node = { + id: '', + locality: {} + }; if (!('id' in obj)) { throw new Error('id field missing in node element'); } @@ -202,7 +231,7 @@ function validateNode(obj: any): Node { return result; } -function validateBootstrapFile(obj: any): BootstrapInfo { +export function validateBootstrapConfig(obj: any): BootstrapInfo { return { xdsServers: obj.xds_servers.map(validateXdsServerConfig), node: validateNode(obj.node), @@ -215,34 +244,66 @@ export async function loadBootstrapInfo(): Promise { if (loadedBootstrapInfo !== null) { return loadedBootstrapInfo; } + + /** + * If GRPC_XDS_BOOTSTRAP exists + * then use its value as the name of the bootstrap file. + * + * If the file is missing or the contents of the file are malformed, + * return an error. + */ const bootstrapPath = process.env.GRPC_XDS_BOOTSTRAP; - if (bootstrapPath === undefined) { - return Promise.reject( - new Error( - 'The GRPC_XDS_BOOTSTRAP environment variable needs to be set to the path to the bootstrap file to use xDS' - ) - ); - } - loadedBootstrapInfo = new Promise((resolve, reject) => { - fs.readFile(bootstrapPath, { encoding: 'utf8' }, (err, data) => { - if (err) { - reject( - new Error( - `Failed to read xDS bootstrap file from path ${bootstrapPath} with error ${err.message}` - ) - ); - } - try { - const parsedFile = JSON.parse(data); - resolve(validateBootstrapFile(parsedFile)); - } catch (e) { - reject( - new Error( - `Failed to parse xDS bootstrap file at path ${bootstrapPath} with error ${e.message}` - ) - ); - } + if (bootstrapPath) { + loadedBootstrapInfo = new Promise((resolve, reject) => { + fs.readFile(bootstrapPath, { encoding: 'utf8' }, (err, data) => { + if (err) { + reject( + new Error( + `Failed to read xDS bootstrap file from path ${bootstrapPath} with error ${err.message}` + ) + ); + } + try { + const parsedFile = JSON.parse(data); + resolve(validateBootstrapConfig(parsedFile)); + } catch (e) { + reject( + new Error( + `Failed to parse xDS bootstrap file at path ${bootstrapPath} with error ${e.message}` + ) + ); + } + }); }); - }); - return loadedBootstrapInfo; + return loadedBootstrapInfo; + } + + /** + * Else, if GRPC_XDS_BOOTSTRAP_CONFIG exists + * then use its value as the bootstrap config. + * + * If the value is malformed, return an error. + * + * See: https://github.com/grpc/grpc-node/issues/1868 + */ + const bootstrapConfig = process.env.GRPC_XDS_BOOTSTRAP_CONFIG; + if (bootstrapConfig) { + try { + const parsedConfig = JSON.parse(bootstrapConfig); + const loadedBootstrapInfoValue = validateBootstrapConfig(parsedConfig); + loadedBootstrapInfo = Promise.resolve(loadedBootstrapInfoValue); + } catch (e) { + throw new Error( + `Failed to parse xDS bootstrap config from environment variable GRPC_XDS_BOOTSTRAP_CONFIG with error ${e.message}` + ); + } + + return loadedBootstrapInfo; + } + + return Promise.reject( + new Error( + 'The GRPC_XDS_BOOTSTRAP or GRPC_XDS_BOOTSTRAP_CONFIG environment variables need to be set to the path to the bootstrap file to use xDS' + ) + ); } diff --git a/packages/grpc-js-xds/src/xds-client.ts b/packages/grpc-js-xds/src/xds-client.ts index 22d816a03..20c914a1c 100644 --- a/packages/grpc-js-xds/src/xds-client.ts +++ b/packages/grpc-js-xds/src/xds-client.ts @@ -16,35 +16,21 @@ */ import * as protoLoader from '@grpc/proto-loader'; -import { loadPackageDefinition, StatusObject, status, logVerbosity, Metadata, experimental, ChannelOptions, ClientDuplexStream, ServiceError, ChannelCredentials } from '@grpc/grpc-js'; +// This is a non-public, unstable API, but it's very convenient +import { loadProtosWithOptionsSync } from '@grpc/proto-loader/build/src/util'; +import { loadPackageDefinition, StatusObject, status, logVerbosity, Metadata, experimental, ChannelOptions, ClientDuplexStream, ServiceError, ChannelCredentials, Channel, connectivityState } from '@grpc/grpc-js'; import * as adsTypes from './generated/ads'; import * as lrsTypes from './generated/lrs'; -import { loadBootstrapInfo } from './xds-bootstrap'; -import { isIPv4, isIPv6 } from 'net'; -import { Node } from './generated/envoy/api/v2/core/Node'; -import { AggregatedDiscoveryServiceClient } from './generated/envoy/service/discovery/v2/AggregatedDiscoveryService'; -import { DiscoveryRequest } from './generated/envoy/api/v2/DiscoveryRequest'; -import { DiscoveryResponse__Output } from './generated/envoy/api/v2/DiscoveryResponse'; -import { - ClusterLoadAssignment__Output, - ClusterLoadAssignment, -} from './generated/envoy/api/v2/ClusterLoadAssignment'; -import { Cluster__Output } from './generated/envoy/api/v2/Cluster'; -import { LoadReportingServiceClient } from './generated/envoy/service/load_stats/v2/LoadReportingService'; -import { LoadStatsRequest } from './generated/envoy/service/load_stats/v2/LoadStatsRequest'; -import { LoadStatsResponse__Output } from './generated/envoy/service/load_stats/v2/LoadStatsResponse'; -import { - Locality__Output, - Locality, -} from './generated/envoy/api/v2/core/Locality'; -import { - ClusterStats, - _envoy_api_v2_endpoint_ClusterStats_DroppedRequests, -} from './generated/envoy/api/v2/endpoint/ClusterStats'; -import { UpstreamLocalityStats } from './generated/envoy/api/v2/endpoint/UpstreamLocalityStats'; -import { Listener__Output } from './generated/envoy/api/v2/Listener'; -import { HttpConnectionManager__Output } from './generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager'; -import { RouteConfiguration__Output } from './generated/envoy/api/v2/RouteConfiguration'; +import { BootstrapInfo, loadBootstrapInfo } from './xds-bootstrap'; +import { Node } from './generated/envoy/config/core/v3/Node'; +import { AggregatedDiscoveryServiceClient } from './generated/envoy/service/discovery/v3/AggregatedDiscoveryService'; +import { DiscoveryRequest } from './generated/envoy/service/discovery/v3/DiscoveryRequest'; +import { DiscoveryResponse__Output } from './generated/envoy/service/discovery/v3/DiscoveryResponse'; +import { LoadReportingServiceClient } from './generated/envoy/service/load_stats/v3/LoadReportingService'; +import { LoadStatsRequest } from './generated/envoy/service/load_stats/v3/LoadStatsRequest'; +import { LoadStatsResponse__Output } from './generated/envoy/service/load_stats/v3/LoadStatsResponse'; +import { Locality, Locality__Output } from './generated/envoy/config/core/v3/Locality'; +import { Listener__Output } from './generated/envoy/config/listener/v3/Listener'; import { Any__Output } from './generated/google/protobuf/Any'; import BackoffTimeout = experimental.BackoffTimeout; import ServiceConfig = experimental.ServiceConfig; @@ -54,7 +40,13 @@ import { EdsState } from './xds-stream-state/eds-state'; import { CdsState } from './xds-stream-state/cds-state'; import { RdsState } from './xds-stream-state/rds-state'; import { LdsState } from './xds-stream-state/lds-state'; -import { Watcher } from './xds-stream-state/xds-stream-state'; +import { HandleResponseResult, ResourcePair, Watcher } from './xds-stream-state/xds-stream-state'; +import { ClusterLoadAssignment__Output } from './generated/envoy/config/endpoint/v3/ClusterLoadAssignment'; +import { Cluster__Output } from './generated/envoy/config/cluster/v3/Cluster'; +import { RouteConfiguration__Output } from './generated/envoy/config/route/v3/RouteConfiguration'; +import { Duration } from './generated/google/protobuf/Duration'; +import { AdsOutputType, AdsTypeUrl, CDS_TYPE_URL, decodeSingleResource, EDS_TYPE_URL, LDS_TYPE_URL, RDS_TYPE_URL } from './resources'; +import { setCsdsClientNode, updateCsdsRequestedNameList, updateCsdsResourceResponse } from './csds'; const TRACER_NAME = 'xds_client'; @@ -64,21 +56,6 @@ function trace(text: string): void { const clientVersion = require('../../package.json').version; -const EDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.ClusterLoadAssignment'; -const CDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.Cluster'; -const LDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.Listener'; -const RDS_TYPE_URL = 'type.googleapis.com/envoy.api.v2.RouteConfiguration'; - -type EdsTypeUrl = 'type.googleapis.com/envoy.api.v2.ClusterLoadAssignment'; -type CdsTypeUrl = 'type.googleapis.com/envoy.api.v2.Cluster'; -type LdsTypeUrl = 'type.googleapis.com/envoy.api.v2.Listener'; -type RdsTypeUrl = 'type.googleapis.com/envoy.api.v2.RouteConfiguration'; - -type AdsTypeUrl = EdsTypeUrl | CdsTypeUrl | RdsTypeUrl | LdsTypeUrl; - -const HTTP_CONNECTION_MANGER_TYPE_URL = - 'type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager'; - let loadedProtos: Promise< adsTypes.ProtoGrpcType & lrsTypes.ProtoGrpcType > | null = null; @@ -92,13 +69,8 @@ function loadAdsProtos(): Promise< loadedProtos = protoLoader .load( [ - 'envoy/service/discovery/v2/ads.proto', - 'envoy/service/load_stats/v2/lrs.proto', - 'envoy/api/v2/listener.proto', - 'envoy/api/v2/route.proto', - 'envoy/api/v2/cluster.proto', - 'envoy/api/v2/endpoint.proto', - 'envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto', + 'envoy/service/discovery/v3/ads.proto', + 'envoy/service/load_stats/v3/lrs.proto', ], { keepCase: true, @@ -110,7 +82,7 @@ function loadAdsProtos(): Promise< includeDirs: [ // Paths are relative to src/build __dirname + '/../../deps/envoy-api/', - __dirname + '/../../deps/udpa/', + __dirname + '/../../deps/xds/', __dirname + '/../../deps/googleapis/', __dirname + '/../../deps/protoc-gen-validate/', ], @@ -137,6 +109,7 @@ function localityEqual( } export interface XdsClusterDropStats { + addUncategorizedCallDropped(): void; addCallDropped(category: string): void; } @@ -145,6 +118,32 @@ export interface XdsClusterLocalityStats { addCallFinished(fail: boolean): void; } +interface DroppedRequests { + category: string; + dropped_count: number; +} + +interface UpstreamLocalityStats { + locality: Locality; + total_issued_requests: number; + total_successful_requests: number; + total_error_requests: number; + total_requests_in_progress: number; +} + +/** + * An interface representing the ClusterStats message type, restricted to the + * fields used in this module to ensure compatibility with both v2 and v3 APIs. + */ +interface ClusterStats { + cluster_name: string; + cluster_service_name: string; + dropped_requests: DroppedRequests[]; + total_dropped_requests: number; + upstream_locality_stats: UpstreamLocalityStats[]; + load_report_interval: Duration +} + interface ClusterLocalityStats { locality: Locality__Output; callsStarted: number; @@ -155,6 +154,7 @@ interface ClusterLocalityStats { interface ClusterLoadReport { callsDropped: Map; + uncategorizedCallsDropped: number; localityStats: ClusterLocalityStats[]; intervalStart: [number, number]; } @@ -192,6 +192,7 @@ class ClusterLoadReportMap { } const newStats: ClusterLoadReport = { callsDropped: new Map(), + uncategorizedCallsDropped: 0, localityStats: [], intervalStart: process.hrtime(), }; @@ -218,52 +219,43 @@ class ClusterLoadReportMap { } } +type AdsServiceKind = 'eds' | 'cds' | 'rds' | 'lds'; + interface AdsState { - [EDS_TYPE_URL]: EdsState; - [CDS_TYPE_URL]: CdsState; - [RDS_TYPE_URL]: RdsState; - [LDS_TYPE_URL]: LdsState; + eds: EdsState; + cds: CdsState; + rds: RdsState; + lds: LdsState; } -/** - * Map type URLs to their corresponding message types - */ -type OutputType = T extends EdsTypeUrl - ? ClusterLoadAssignment__Output - : T extends CdsTypeUrl - ? Cluster__Output - : T extends RdsTypeUrl - ? RouteConfiguration__Output - : Listener__Output; - function getResponseMessages( - typeUrl: T, + targetTypeUrl: T, resources: Any__Output[] -): OutputType[] { - const result: OutputType[] = []; +): ResourcePair>[] { + const result: ResourcePair>[] = []; for (const resource of resources) { - if (protoLoader.isAnyExtension(resource) && resource['@type'] === typeUrl) { - result.push(resource as protoLoader.AnyExtension & OutputType); - } else { + if (resource.type_url !== targetTypeUrl) { throw new Error( - `ADS Error: Invalid resource type ${ - protoLoader.isAnyExtension(resource) - ? resource['@type'] - : resource.type_url - }, expected ${typeUrl}` + `ADS Error: Invalid resource type ${resource.type_url}, expected ${targetTypeUrl}` ); } + result.push({ + resource: decodeSingleResource(targetTypeUrl, resource.value), + raw: resource + }); } return result; } export class XdsClient { + private adsNode: Node | null = null; private adsClient: AggregatedDiscoveryServiceClient | null = null; private adsCall: ClientDuplexStream< DiscoveryRequest, DiscoveryResponse__Output > | null = null; + private receivedAdsResponseOnCurrentStream = false; private lrsNode: Node | null = null; private lrsClient: LoadReportingServiceClient | null = null; @@ -272,6 +264,7 @@ export class XdsClient { LoadStatsResponse__Output > | null = null; private latestLrsSettings: LoadStatsResponse__Output | null = null; + private receivedLrsSettingsForCurrentStream = false; private clusterStatsMap: ClusterLoadReportMap = new ClusterLoadReportMap(); private statsTimer: NodeJS.Timer; @@ -283,24 +276,24 @@ export class XdsClient { private adsBackoff: BackoffTimeout; private lrsBackoff: BackoffTimeout; - constructor() { + constructor(bootstrapInfoOverride?: BootstrapInfo) { const edsState = new EdsState(() => { - this.updateNames(EDS_TYPE_URL); + this.updateNames('eds'); }); - const cdsState = new CdsState(edsState, () => { - this.updateNames(CDS_TYPE_URL); + const cdsState = new CdsState(() => { + this.updateNames('cds'); }); const rdsState = new RdsState(() => { - this.updateNames(RDS_TYPE_URL); + this.updateNames('rds'); }); const ldsState = new LdsState(rdsState, () => { - this.updateNames(LDS_TYPE_URL); + this.updateNames('lds'); }); this.adsState = { - [EDS_TYPE_URL]: edsState, - [CDS_TYPE_URL]: cdsState, - [RDS_TYPE_URL]: rdsState, - [LDS_TYPE_URL]: ldsState, + eds: edsState, + cds: cdsState, + rds: rdsState, + lds: ldsState, }; const channelArgs = { @@ -317,24 +310,50 @@ export class XdsClient { }); this.lrsBackoff.unref(); - Promise.all([loadBootstrapInfo(), loadAdsProtos()]).then( + async function getBootstrapInfo(): Promise { + if (bootstrapInfoOverride) { + return bootstrapInfoOverride; + } else { + return loadBootstrapInfo(); + } + } + + Promise.all([getBootstrapInfo(), loadAdsProtos()]).then( ([bootstrapInfo, protoDefinitions]) => { if (this.hasShutdown) { return; } - const node: Node = { - ...bootstrapInfo.node, - build_version: `gRPC Node Pure JS ${clientVersion}`, - user_agent_name: 'gRPC Node Pure JS', - }; + trace('Loaded bootstrap info: ' + JSON.stringify(bootstrapInfo, undefined, 2)); + if (bootstrapInfo.xdsServers.length < 1) { + trace('Failed to initialize xDS Client. No servers provided in bootstrap info.'); + // Bubble this error up to any listeners + this.reportStreamError({ + code: status.INTERNAL, + details: 'Failed to initialize xDS Client. No servers provided in bootstrap info.', + metadata: new Metadata(), + }); + return; + } + if (bootstrapInfo.xdsServers[0].serverFeatures.indexOf('ignore_resource_deletion') >= 0) { + this.adsState.lds.enableIgnoreResourceDeletion(); + this.adsState.cds.enableIgnoreResourceDeletion(); + } + const userAgentName = 'gRPC Node Pure JS'; this.adsNode = { - ...node, + ...bootstrapInfo.node, + user_agent_name: userAgentName, + user_agent_version: clientVersion, client_features: ['envoy.lb.does_not_support_overprovisioning'], }; this.lrsNode = { - ...node, + ...bootstrapInfo.node, + user_agent_name: userAgentName, + user_agent_version: clientVersion, client_features: ['envoy.lrs.supports_send_all_clusters'], }; + setCsdsClientNode(this.adsNode); + trace('ADS Node: ' + JSON.stringify(this.adsNode, undefined, 2)); + trace('LRS Node: ' + JSON.stringify(this.lrsNode, undefined, 2)); const credentialsConfigs = bootstrapInfo.xdsServers[0].channelCreds; let channelCreds: ChannelCredentials | null = null; for (const config of credentialsConfigs) { @@ -356,22 +375,26 @@ export class XdsClient { }); return; } + const serverUri = bootstrapInfo.xdsServers[0].serverUri trace('Starting xDS client connected to server URI ' + bootstrapInfo.xdsServers[0].serverUri); - this.adsClient = new protoDefinitions.envoy.service.discovery.v2.AggregatedDiscoveryService( - bootstrapInfo.xdsServers[0].serverUri, + const channel = new Channel(serverUri, channelCreds, channelArgs); + this.adsClient = new protoDefinitions.envoy.service.discovery.v3.AggregatedDiscoveryService( + serverUri, channelCreds, - channelArgs + {channelOverride: channel} ); this.maybeStartAdsStream(); + channel.watchConnectivityState(channel.getConnectivityState(false), Infinity, () => { + this.handleAdsConnectivityStateUpdate(); + }) - this.lrsClient = new protoDefinitions.envoy.service.load_stats.v2.LoadReportingService( - bootstrapInfo.xdsServers[0].serverUri, + this.lrsClient = new protoDefinitions.envoy.service.load_stats.v3.LoadReportingService( + serverUri, channelCreds, - {channelOverride: this.adsClient.getChannel()} + {channelOverride: channel} ); this.maybeStartLrsStream(); - }, - (error) => { + }).catch((error) => { trace('Failed to initialize xDS Client. ' + error.message); // Bubble this error up to any listeners this.reportStreamError({ @@ -385,115 +408,186 @@ export class XdsClient { clearInterval(this.statsTimer); } + private handleAdsConnectivityStateUpdate() { + if (!this.adsClient) { + return; + } + const state = this.adsClient.getChannel().getConnectivityState(false); + if (state === connectivityState.READY && this.adsCall) { + this.reportAdsStreamStarted(); + } + if (state === connectivityState.TRANSIENT_FAILURE) { + this.reportStreamError({ + code: status.UNAVAILABLE, + details: 'No connection established to xDS server', + metadata: new Metadata() + }); + } + this.adsClient.getChannel().watchConnectivityState(state, Infinity, () => { + this.handleAdsConnectivityStateUpdate(); + }); + } + private handleAdsResponse(message: DiscoveryResponse__Output) { - let errorString: string | null; - /* The cases in this switch statement look redundant but separating them - * out like this is necessary for the typechecker to validate the types - * as narrowly as we need it to. */ - switch (message.type_url) { - case EDS_TYPE_URL: - errorString = this.adsState[message.type_url].handleResponses( - getResponseMessages(message.type_url, message.resources) - ); - break; - case CDS_TYPE_URL: - errorString = this.adsState[message.type_url].handleResponses( - getResponseMessages(message.type_url, message.resources) - ); - break; - case RDS_TYPE_URL: - errorString = this.adsState[message.type_url].handleResponses( - getResponseMessages(message.type_url, message.resources) - ); - break; - case LDS_TYPE_URL: - errorString = this.adsState[message.type_url].handleResponses( - getResponseMessages(message.type_url, message.resources) - ); - break; - default: - errorString = `Unknown type_url ${message.type_url}`; - } - if (errorString === null) { - trace('Acking message with type URL ' + message.type_url); - /* errorString can only be null in one of the first 4 cases, which - * implies that message.type_url is one of the 4 known type URLs, which - * means that this type assertion is valid. */ - const typeUrl = message.type_url as AdsTypeUrl; - this.adsState[typeUrl].nonce = message.nonce; - this.adsState[typeUrl].versionInfo = message.version_info; - this.ack(typeUrl); + this.receivedAdsResponseOnCurrentStream = true; + this.adsBackoff.reset(); + let handleResponseResult: { + result: HandleResponseResult; + serviceKind: AdsServiceKind; + } | null = null; + try { + switch (message.type_url) { + case EDS_TYPE_URL: + handleResponseResult = { + result: this.adsState.eds.handleResponses( + getResponseMessages(EDS_TYPE_URL, message.resources) + ), + serviceKind: 'eds' + }; + break; + case CDS_TYPE_URL: + handleResponseResult = { + result: this.adsState.cds.handleResponses( + getResponseMessages(CDS_TYPE_URL, message.resources) + ), + serviceKind: 'cds' + }; + break; + case RDS_TYPE_URL: + handleResponseResult = { + result: this.adsState.rds.handleResponses( + getResponseMessages(RDS_TYPE_URL, message.resources) + ), + serviceKind: 'rds' + }; + break; + case LDS_TYPE_URL: + handleResponseResult = { + result: this.adsState.lds.handleResponses( + getResponseMessages(LDS_TYPE_URL, message.resources) + ), + serviceKind: 'lds' + } + break; + } + } catch (e) { + trace('Nacking message with protobuf parsing error: ' + e.message); + this.nack(message.type_url, e.message); + return; + } + if (handleResponseResult === null) { + // Null handleResponseResult means that the type_url was unrecognized + trace('Nacking message with unknown type URL ' + message.type_url); + this.nack(message.type_url, `Unknown type_url ${message.type_url}`); } else { - trace('Nacking message with type URL ' + message.type_url + ': "' + errorString + '"'); - this.nack(message.type_url, errorString); + updateCsdsResourceResponse(message.type_url as AdsTypeUrl, message.version_info, handleResponseResult.result); + if (handleResponseResult.result.rejected.length > 0) { + // rejected.length > 0 means that at least one message validation failed + const errorString = `${handleResponseResult.serviceKind.toUpperCase()} Error: ${handleResponseResult.result.rejected[0].error}`; + trace('Nacking message with type URL ' + message.type_url + ': ' + errorString); + this.nack(message.type_url, errorString); + } else { + // If we get here, all message validation succeeded + trace('Acking message with type URL ' + message.type_url); + const serviceKind = handleResponseResult.serviceKind; + this.adsState[serviceKind].nonce = message.nonce; + this.adsState[serviceKind].versionInfo = message.version_info; + this.ack(serviceKind); + } + } + } + + private handleAdsCallStatus(streamStatus: StatusObject) { + trace( + 'ADS stream ended. code=' + streamStatus.code + ' details= ' + streamStatus.details + ); + this.adsCall = null; + if (streamStatus.code !== status.OK && !this.receivedAdsResponseOnCurrentStream) { + this.reportStreamError(streamStatus); + } + /* If the backoff timer is no longer running, we do not need to wait any + * more to start the new call. */ + if (!this.adsBackoff.isRunning()) { + this.maybeStartAdsStream(); } } /** * Start the ADS stream if the client exists and there is not already an - * existing stream, and there + * existing stream, and there are resources to request. */ private maybeStartAdsStream() { - if (this.adsClient === null) { + if (this.hasShutdown) { return; } - if (this.adsCall !== null) { + if (this.adsState.eds.getResourceNames().length === 0 && + this.adsState.cds.getResourceNames().length === 0 && + this.adsState.rds.getResourceNames().length === 0 && + this.adsState.lds.getResourceNames().length === 0) { return; } - if (this.hasShutdown) { + if (this.adsClient === null) { return; } - if (this.adsState[EDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[CDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[RDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[LDS_TYPE_URL].getResourceNames().length === 0) { + if (this.adsCall !== null) { return; } - trace('Starting ADS stream'); - // Backoff relative to when we start the request - this.adsBackoff.runOnce(); - this.adsCall = this.adsClient.StreamAggregatedResources(); + this.receivedAdsResponseOnCurrentStream = false; + const metadata = new Metadata({waitForReady: true}); + this.adsCall = this.adsClient.StreamAggregatedResources(metadata); this.adsCall.on('data', (message: DiscoveryResponse__Output) => { this.handleAdsResponse(message); }); - this.adsCall.on('error', (error: ServiceError) => { - trace( - 'ADS stream ended. code=' + error.code + ' details= ' + error.details - ); - this.adsCall = null; - this.reportStreamError(error); - /* If the backoff timer is no longer running, we do not need to wait any - * more to start the new call. */ - if (!this.adsBackoff.isRunning()) { - this.maybeStartAdsStream(); - } + this.adsCall.on('status', (status: StatusObject) => { + this.handleAdsCallStatus(status); }); + this.adsCall.on('error', () => {}); + trace('Started ADS stream'); + // Backoff relative to when we start the request + this.adsBackoff.runOnce(); - const allTypeUrls: AdsTypeUrl[] = [ - EDS_TYPE_URL, - CDS_TYPE_URL, - RDS_TYPE_URL, - LDS_TYPE_URL, - ]; - for (const typeUrl of allTypeUrls) { - const state = this.adsState[typeUrl]; + const allServiceKinds: AdsServiceKind[] = ['eds', 'cds', 'rds', 'lds']; + for (const service of allServiceKinds) { + const state = this.adsState[service]; if (state.getResourceNames().length > 0) { - this.updateNames(typeUrl); + this.updateNames(service); } } + if (this.adsClient.getChannel().getConnectivityState(false) === connectivityState.READY) { + this.reportAdsStreamStarted(); + } + } + + private maybeSendAdsMessage(typeUrl: string, resourceNames: string[], responseNonce: string, versionInfo: string, errorMessage?: string) { + this.adsCall?.write({ + node: this.adsNode!, + type_url: typeUrl, + resource_names: resourceNames, + response_nonce: responseNonce, + version_info: versionInfo, + error_detail: errorMessage ? { message: errorMessage } : undefined + }); + } + + private getTypeUrl(serviceKind: AdsServiceKind): AdsTypeUrl { + switch (serviceKind) { + case 'eds': + return EDS_TYPE_URL; + case 'cds': + return CDS_TYPE_URL; + case 'rds': + return RDS_TYPE_URL; + case 'lds': + return LDS_TYPE_URL; + } } /** * Acknowledge an update. This should be called after the local nonce and * version info are updated so that it sends the post-update values. */ - ack(typeUrl: AdsTypeUrl) { - /* An ack is the best indication of a successful interaction between the - * client and the server, so we can reset the backoff timer here. */ - this.adsBackoff.stop(); - this.adsBackoff.reset(); - - this.updateNames(typeUrl); + ack(serviceKind: AdsServiceKind) { + this.updateNames(serviceKind); } /** @@ -504,135 +598,188 @@ export class XdsClient { let resourceNames: string[]; let nonce: string; let versionInfo: string; + let serviceKind: AdsServiceKind | null; switch (typeUrl) { case EDS_TYPE_URL: + serviceKind = 'eds'; + break; case CDS_TYPE_URL: + serviceKind = 'cds'; + break; case RDS_TYPE_URL: + serviceKind = 'rds'; + break; case LDS_TYPE_URL: - resourceNames = this.adsState[typeUrl].getResourceNames(); - nonce = this.adsState[typeUrl].nonce; - versionInfo = this.adsState[typeUrl].versionInfo; + serviceKind = 'lds'; break; default: - resourceNames = []; - nonce = ''; - versionInfo = ''; + serviceKind = null; + break; } - this.adsCall?.write({ - node: this.adsNode!, - type_url: typeUrl, - resource_names: resourceNames, - response_nonce: nonce, - version_info: versionInfo, - error_detail: { - message: message, - }, - }); + if (serviceKind) { + this.adsState[serviceKind].reportStreamError({ + code: status.UNAVAILABLE, + details: message + ' Node ID=' + this.adsNode!.id, + metadata: new Metadata() + }); + resourceNames = this.adsState[serviceKind].getResourceNames(); + nonce = this.adsState[serviceKind].nonce; + versionInfo = this.adsState[serviceKind].versionInfo; + } else { + resourceNames = []; + nonce = ''; + versionInfo = ''; + } + this.maybeSendAdsMessage(typeUrl, resourceNames, nonce, versionInfo, message); } - private updateNames(typeUrl: AdsTypeUrl) { - if (this.adsState[EDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[CDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[RDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[LDS_TYPE_URL].getResourceNames().length === 0) { + private updateNames(serviceKind: AdsServiceKind) { + if (this.adsState.eds.getResourceNames().length === 0 && + this.adsState.cds.getResourceNames().length === 0 && + this.adsState.rds.getResourceNames().length === 0 && + this.adsState.lds.getResourceNames().length === 0) { this.adsCall?.end(); + this.adsCall = null; this.lrsCall?.end(); + this.lrsCall = null; return; } this.maybeStartAdsStream(); this.maybeStartLrsStream(); - trace('Sending update for type URL ' + typeUrl + ' with names ' + this.adsState[typeUrl].getResourceNames()); - this.adsCall?.write({ - node: this.adsNode!, - type_url: typeUrl, - resource_names: this.adsState[typeUrl].getResourceNames(), - response_nonce: this.adsState[typeUrl].nonce, - version_info: this.adsState[typeUrl].versionInfo, - }); + if (!this.adsCall) { + /* If the stream is not set up yet at this point, shortcut the rest + * becuase nothing will actually be sent. This would mainly happen if + * the bootstrap file has not been read yet. In that case, the output + * of getTypeUrl is garbage and everything after that is invalid. */ + return; + } + trace('Sending update for ' + serviceKind + ' with names ' + this.adsState[serviceKind].getResourceNames()); + const typeUrl = this.getTypeUrl(serviceKind); + updateCsdsRequestedNameList(typeUrl, this.adsState[serviceKind].getResourceNames()); + this.maybeSendAdsMessage(typeUrl, this.adsState[serviceKind].getResourceNames(), this.adsState[serviceKind].nonce, this.adsState[serviceKind].versionInfo); } private reportStreamError(status: StatusObject) { - this.adsState[EDS_TYPE_URL].reportStreamError(status); - this.adsState[CDS_TYPE_URL].reportStreamError(status); - this.adsState[RDS_TYPE_URL].reportStreamError(status); - this.adsState[LDS_TYPE_URL].reportStreamError(status); + status = {...status, details: status.details + ' Node ID=' + this.adsNode!.id}; + this.adsState.eds.reportStreamError(status); + this.adsState.cds.reportStreamError(status); + this.adsState.rds.reportStreamError(status); + this.adsState.lds.reportStreamError(status); } - private maybeStartLrsStream() { + private reportAdsStreamStarted() { + this.adsState.eds.reportAdsStreamStart(); + this.adsState.cds.reportAdsStreamStart(); + this.adsState.rds.reportAdsStreamStart(); + this.adsState.lds.reportAdsStreamStart(); + } + + private handleLrsResponse(message: LoadStatsResponse__Output) { + trace('Received LRS response'); + /* Once we get any response from the server, we assume that the stream is + * in a good state, so we can reset the backoff timer. */ + this.lrsBackoff.reset(); + if ( + !this.receivedLrsSettingsForCurrentStream || + message.load_reporting_interval?.seconds !== + this.latestLrsSettings?.load_reporting_interval?.seconds || + message.load_reporting_interval?.nanos !== + this.latestLrsSettings?.load_reporting_interval?.nanos + ) { + /* Only reset the timer if the interval has changed or was not set + * before. */ + clearInterval(this.statsTimer); + /* Convert a google.protobuf.Duration to a number of milliseconds for + * use with setInterval. */ + const loadReportingIntervalMs = + Number.parseInt(message.load_reporting_interval!.seconds) * 1000 + + message.load_reporting_interval!.nanos / 1_000_000; + trace('Received LRS response with load reporting interval ' + loadReportingIntervalMs + ' ms'); + this.statsTimer = setInterval(() => { + this.sendStats(); + }, loadReportingIntervalMs); + } + this.latestLrsSettings = message; + this.receivedLrsSettingsForCurrentStream = true; + } + + private handleLrsCallStatus(streamStatus: StatusObject) { + trace( + 'LRS stream ended. code=' + streamStatus.code + ' details= ' + streamStatus.details + ); + this.lrsCall = null; + clearInterval(this.statsTimer); + /* If the backoff timer is no longer running, we do not need to wait any + * more to start the new call. */ + if (!this.lrsBackoff.isRunning()) { + this.maybeStartLrsStream(); + } + } + + private maybeStartLrsStreamV3(): boolean { if (!this.lrsClient) { - return; + return false; } if (this.lrsCall) { - return; + return false; } + this.lrsCall = this.lrsClient.streamLoadStats(); + this.receivedLrsSettingsForCurrentStream = false; + this.lrsCall.on('data', (message: LoadStatsResponse__Output) => { + this.handleLrsResponse(message); + }); + this.lrsCall.on('status', (status: StatusObject) => { + this.handleLrsCallStatus(status); + }); + this.lrsCall.on('error', () => {}); + return true; + } + + private maybeStartLrsStream() { if (this.hasShutdown) { return; } - if (this.adsState[EDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[CDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[RDS_TYPE_URL].getResourceNames().length === 0 && - this.adsState[LDS_TYPE_URL].getResourceNames().length === 0) { + if (this.adsState.eds.getResourceNames().length === 0 && + this.adsState.cds.getResourceNames().length === 0 && + this.adsState.rds.getResourceNames().length === 0 && + this.adsState.lds.getResourceNames().length === 0) { + return; + } + if (!this.lrsClient) { + return; + } + if (this.lrsCall) { return; } - - trace('Starting LRS stream'); - - this.lrsBackoff.runOnce(); this.lrsCall = this.lrsClient.streamLoadStats(); - let receivedSettingsForThisStream = false; + this.receivedLrsSettingsForCurrentStream = false; this.lrsCall.on('data', (message: LoadStatsResponse__Output) => { - /* Once we get any response from the server, we assume that the stream is - * in a good state, so we can reset the backoff timer. */ - this.lrsBackoff.stop(); - this.lrsBackoff.reset(); - if ( - !receivedSettingsForThisStream || - message.load_reporting_interval?.seconds !== - this.latestLrsSettings?.load_reporting_interval?.seconds || - message.load_reporting_interval?.nanos !== - this.latestLrsSettings?.load_reporting_interval?.nanos - ) { - /* Only reset the timer if the interval has changed or was not set - * before. */ - clearInterval(this.statsTimer); - /* Convert a google.protobuf.Duration to a number of milliseconds for - * use with setInterval. */ - const loadReportingIntervalMs = - Number.parseInt(message.load_reporting_interval!.seconds) * 1000 + - message.load_reporting_interval!.nanos / 1_000_000; - trace('Received LRS request with load reporting interval ' + loadReportingIntervalMs + ' ms'); - this.statsTimer = setInterval(() => { - this.sendStats(); - }, loadReportingIntervalMs); - } - this.latestLrsSettings = message; - receivedSettingsForThisStream = true; + this.handleLrsResponse(message); }); - this.lrsCall.on('error', (error: ServiceError) => { - trace( - 'LRS stream ended. code=' + error.code + ' details= ' + error.details - ); - this.lrsCall = null; - clearInterval(this.statsTimer); - /* If the backoff timer is no longer running, we do not need to wait any - * more to start the new call. */ - if (!this.lrsBackoff.isRunning()) { - this.maybeStartLrsStream(); - } + this.lrsCall.on('status', (status: StatusObject) => { + this.handleLrsCallStatus(status); }); + this.lrsCall.on('error', () => {}); + trace('Starting LRS stream'); + this.lrsBackoff.runOnce(); /* Send buffered stats information when starting LRS stream. If there is no - * buffered stats information, it will still send the node field. */ + * buffered stats information, it will still send the node field. */ this.sendStats(); } + private maybeSendLrsMessage(clusterStats: ClusterStats[]) { + this.lrsCall?.write({ + node: this.lrsNode!, + cluster_stats: clusterStats + }); + } + private sendStats() { - if (!this.lrsCall) { + if (this.lrsCall === null) { return; } if (!this.latestLrsSettings) { - this.lrsCall.write({ - node: this.lrsNode!, - }); + this.maybeSendLrsMessage([]); return; } const clusterStats: ClusterStats[] = []; @@ -664,7 +811,7 @@ export class XdsClient { localityStats.callsFailed = 0; } } - const droppedRequests: _envoy_api_v2_endpoint_ClusterStats_DroppedRequests[] = []; + const droppedRequests: DroppedRequests[] = []; let totalDroppedRequests = 0; for (const [category, count] of stats.callsDropped.entries()) { if (count > 0) { @@ -675,8 +822,10 @@ export class XdsClient { totalDroppedRequests += count; } } + totalDroppedRequests += stats.uncategorizedCallsDropped; // Clear out dropped call stats after sending them stats.callsDropped.clear(); + stats.uncategorizedCallsDropped = 0; const interval = process.hrtime(stats.intervalStart); stats.intervalStart = process.hrtime(); // Skip clusters with 0 requests @@ -696,10 +845,7 @@ export class XdsClient { } } trace('Sending LRS stats ' + JSON.stringify(clusterStats, undefined, 2)); - this.lrsCall.write({ - node: this.lrsNode!, - cluster_stats: clusterStats, - }); + this.maybeSendLrsMessage(clusterStats); } addEndpointWatcher( @@ -707,7 +853,7 @@ export class XdsClient { watcher: Watcher ) { trace('Watcher added for endpoint ' + edsServiceName); - this.adsState[EDS_TYPE_URL].addWatcher(edsServiceName, watcher); + this.adsState.eds.addWatcher(edsServiceName, watcher); } removeEndpointWatcher( @@ -715,37 +861,37 @@ export class XdsClient { watcher: Watcher ) { trace('Watcher removed for endpoint ' + edsServiceName); - this.adsState[EDS_TYPE_URL].removeWatcher(edsServiceName, watcher); + this.adsState.eds.removeWatcher(edsServiceName, watcher); } addClusterWatcher(clusterName: string, watcher: Watcher) { trace('Watcher added for cluster ' + clusterName); - this.adsState[CDS_TYPE_URL].addWatcher(clusterName, watcher); + this.adsState.cds.addWatcher(clusterName, watcher); } removeClusterWatcher(clusterName: string, watcher: Watcher) { trace('Watcher removed for cluster ' + clusterName); - this.adsState[CDS_TYPE_URL].removeWatcher(clusterName, watcher); + this.adsState.cds.removeWatcher(clusterName, watcher); } addRouteWatcher(routeConfigName: string, watcher: Watcher) { trace('Watcher added for route ' + routeConfigName); - this.adsState[RDS_TYPE_URL].addWatcher(routeConfigName, watcher); + this.adsState.rds.addWatcher(routeConfigName, watcher); } removeRouteWatcher(routeConfigName: string, watcher: Watcher) { trace('Watcher removed for route ' + routeConfigName); - this.adsState[RDS_TYPE_URL].removeWatcher(routeConfigName, watcher); + this.adsState.rds.removeWatcher(routeConfigName, watcher); } addListenerWatcher(targetName: string, watcher: Watcher) { trace('Watcher added for listener ' + targetName); - this.adsState[LDS_TYPE_URL].addWatcher(targetName, watcher); + this.adsState.lds.addWatcher(targetName, watcher); } removeListenerWatcher(targetName: string, watcher: Watcher) { trace('Watcher removed for listener ' + targetName); - this.adsState[LDS_TYPE_URL].removeWatcher(targetName, watcher); + this.adsState.lds.removeWatcher(targetName, watcher); } /** @@ -764,6 +910,7 @@ export class XdsClient { trace('addClusterDropStats(lrsServer=' + lrsServer + ', clusterName=' + clusterName + ', edsServiceName=' + edsServiceName + ')'); if (lrsServer !== '') { return { + addUncategorizedCallDropped: () => {}, addCallDropped: (category) => {}, }; } @@ -772,6 +919,9 @@ export class XdsClient { edsServiceName ); return { + addUncategorizedCallDropped: () => { + clusterStats.uncategorizedCallsDropped += 1; + }, addCallDropped: (category) => { const prevCount = clusterStats.callsDropped.get(category) ?? 0; clusterStats.callsDropped.set(category, prevCount + 1); diff --git a/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts index 343089958..9fd12d6ed 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/cds-state.ts @@ -15,91 +15,44 @@ * */ -import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; -import { Cluster__Output } from "../generated/envoy/api/v2/Cluster"; -import { EdsState } from "./eds-state"; -import { Watcher, XdsStreamState } from "./xds-stream-state"; +import { EXPERIMENTAL_OUTLIER_DETECTION } from "../environment"; +import { Cluster__Output } from "../generated/envoy/config/cluster/v3/Cluster"; +import { Duration__Output } from "../generated/google/protobuf/Duration"; +import { UInt32Value__Output } from "../generated/google/protobuf/UInt32Value"; +import { BaseXdsStreamState, XdsStreamState } from "./xds-stream-state"; -const TRACER_NAME = 'xds_client'; - -function trace(text: string): void { - experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); -} - -export class CdsState implements XdsStreamState { - versionInfo = ''; - nonce = ''; - - private watchers: Map[]> = new Map< - string, - Watcher[] - >(); - - private latestResponses: Cluster__Output[] = []; - - constructor( - private edsState: EdsState, - private updateResourceNames: () => void - ) {} - - /** - * Add the watcher to the watcher list. Returns true if the list of resource - * names has changed, and false otherwise. - * @param clusterName - * @param watcher - */ - addWatcher(clusterName: string, watcher: Watcher): void { - trace('Adding CDS watcher for clusterName ' + clusterName); - let watchersEntry = this.watchers.get(clusterName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(clusterName, watchersEntry); - } - watchersEntry.push(watcher); - - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - for (const message of this.latestResponses) { - if (message.name === clusterName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing CDS update for new watcher for clusterName ' + clusterName); - watcher.onValidUpdate(message); - }); - } - } - if (addedServiceName) { - this.updateResourceNames(); - } +export class CdsState extends BaseXdsStreamState implements XdsStreamState { + protected isStateOfTheWorld(): boolean { + return true; + } + protected getResourceName(resource: Cluster__Output): string { + return resource.name; + } + protected getProtocolName(): string { + return 'CDS'; } - removeWatcher(clusterName: string, watcher: Watcher): void { - trace('Removing CDS watcher for clusterName ' + clusterName); - const watchersEntry = this.watchers.get(clusterName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - watchersEntry.splice(entryIndex, 1); - } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(clusterName); - } - } - if (removedServiceName) { - this.updateResourceNames(); + private validateNonnegativeDuration(duration: Duration__Output | null): boolean { + if (!duration) { + return true; } + /* The maximum values here come from the official Protobuf documentation: + * https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Duration + */ + return Number(duration.seconds) >= 0 && + Number(duration.seconds) <= 315_576_000_000 && + duration.nanos >= 0 && + duration.nanos <= 999_999_999; } - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); + private validatePercentage(percentage: UInt32Value__Output | null): boolean { + if (!percentage) { + return true; + } + return percentage.value >=0 && percentage.value <= 100; } - private validateResponse(message: Cluster__Output): boolean { + public validateResponse(message: Cluster__Output): boolean { if (message.type !== 'EDS') { return false; } @@ -114,58 +67,31 @@ export class CdsState implements XdsStreamState { return false; } } - return true; - } - - /** - * Given a list of clusterNames (which may actually be the cluster name), - * for each watcher watching a name not on the list, call that watcher's - * onResourceDoesNotExist method. - * @param allClusterNames - */ - private handleMissingNames(allClusterNames: Set) { - for (const [clusterName, watcherList] of this.watchers.entries()) { - if (!allClusterNames.has(clusterName)) { - trace('Reporting CDS resource does not exist for clusterName ' + clusterName); - for (const watcher of watcherList) { - watcher.onResourceDoesNotExist(); + if (EXPERIMENTAL_OUTLIER_DETECTION) { + if (message.outlier_detection) { + if (!this.validateNonnegativeDuration(message.outlier_detection.interval)) { + return false; + } + if (!this.validateNonnegativeDuration(message.outlier_detection.base_ejection_time)) { + return false; + } + if (!this.validateNonnegativeDuration(message.outlier_detection.max_ejection_time)) { + return false; + } + if (!this.validatePercentage(message.outlier_detection.max_ejection_percent)) { + return false; + } + if (!this.validatePercentage(message.outlier_detection.enforcing_success_rate)) { + return false; + } + if (!this.validatePercentage(message.outlier_detection.failure_percentage_threshold)) { + return false; + } + if (!this.validatePercentage(message.outlier_detection.enforcing_failure_percentage)) { + return false; } } } - } - - handleResponses(responses: Cluster__Output[]): string | null { - for (const message of responses) { - if (!this.validateResponse(message)) { - trace('CDS validation failed for message ' + JSON.stringify(message)); - return 'CDS Error: Cluster validation failed'; - } - } - this.latestResponses = responses; - const allEdsServiceNames: Set = new Set(); - const allClusterNames: Set = new Set(); - for (const message of responses) { - allClusterNames.add(message.name); - const edsServiceName = message.eds_cluster_config?.service_name ?? ''; - allEdsServiceNames.add( - edsServiceName === '' ? message.name : edsServiceName - ); - const watchers = this.watchers.get(message.name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message); - } - } - trace('Received CDS updates for cluster names ' + Array.from(allClusterNames)); - this.handleMissingNames(allClusterNames); - this.edsState.handleMissingNames(allEdsServiceNames); - return null; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); - } - } + return true; } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts index c9beef292..b043ebbc0 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/eds-state.ts @@ -17,90 +17,37 @@ import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; import { isIPv4, isIPv6 } from "net"; -import { ClusterLoadAssignment__Output } from "../generated/envoy/api/v2/ClusterLoadAssignment"; -import { Watcher, XdsStreamState } from "./xds-stream-state"; +import { Locality__Output } from "../generated/envoy/config/core/v3/Locality"; +import { SocketAddress__Output } from "../generated/envoy/config/core/v3/SocketAddress"; +import { ClusterLoadAssignment__Output } from "../generated/envoy/config/endpoint/v3/ClusterLoadAssignment"; +import { Any__Output } from "../generated/google/protobuf/Any"; +import { BaseXdsStreamState, HandleResponseResult, RejectedResourceEntry, ResourcePair, Watcher, XdsStreamState } from "./xds-stream-state"; const TRACER_NAME = 'xds_client'; +const UINT32_MAX = 0xFFFFFFFF; + function trace(text: string): void { experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); } -export class EdsState implements XdsStreamState { - public versionInfo = ''; - public nonce = ''; - - private watchers: Map< - string, - Watcher[] - > = new Map[]>(); - - private latestResponses: ClusterLoadAssignment__Output[] = []; - - constructor(private updateResourceNames: () => void) {} +function localitiesEqual(a: Locality__Output, b: Locality__Output) { + return a.region === b.region && a.sub_zone === b.sub_zone && a.zone === b.zone; +} - /** - * Add the watcher to the watcher list. Returns true if the list of resource - * names has changed, and false otherwise. - * @param edsServiceName - * @param watcher - */ - addWatcher( - edsServiceName: string, - watcher: Watcher - ): void { - let watchersEntry = this.watchers.get(edsServiceName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(edsServiceName, watchersEntry); - } - trace('Adding EDS watcher (' + watchersEntry.length + ' ->' + (watchersEntry.length + 1) + ') for edsServiceName ' + edsServiceName); - watchersEntry.push(watcher); +function addressesEqual(a: SocketAddress__Output, b: SocketAddress__Output) { + return a.address === b.address && a.port_value === b.port_value; +} - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - for (const message of this.latestResponses) { - if (message.cluster_name === edsServiceName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing EDS update for new watcher for edsServiceName ' + edsServiceName); - watcher.onValidUpdate(message); - }); - } - } - if (addedServiceName) { - this.updateResourceNames(); - } +export class EdsState extends BaseXdsStreamState implements XdsStreamState { + protected getResourceName(resource: ClusterLoadAssignment__Output): string { + return resource.cluster_name; } - - removeWatcher( - edsServiceName: string, - watcher: Watcher - ): void { - trace('Removing EDS watcher for edsServiceName ' + edsServiceName); - const watchersEntry = this.watchers.get(edsServiceName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - trace('Removed EDS watcher (' + watchersEntry.length + ' -> ' + (watchersEntry.length - 1) + ') for edsServiceName ' + edsServiceName); - watchersEntry.splice(entryIndex, 1); - } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(edsServiceName); - } - } - if (removedServiceName) { - this.updateResourceNames(); - } + protected getProtocolName(): string { + return 'EDS'; } - - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); + protected isStateOfTheWorld(): boolean { + return false; } /** @@ -108,67 +55,58 @@ export class EdsState implements XdsStreamState { * https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md#clusterloadassignment-proto * @param message */ - private validateResponse(message: ClusterLoadAssignment__Output) { + public validateResponse(message: ClusterLoadAssignment__Output) { + const seenLocalities: {locality: Locality__Output, priority: number}[] = []; + const seenAddresses: SocketAddress__Output[] = []; + const priorityTotalWeights: Map = new Map(); for (const endpoint of message.endpoints) { + if (!endpoint.locality) { + trace('EDS validation: endpoint locality unset'); + return false; + } + for (const {locality, priority} of seenLocalities) { + if (localitiesEqual(endpoint.locality, locality) && endpoint.priority === priority) { + trace('EDS validation: endpoint locality duplicated: ' + JSON.stringify(locality) + ', priority=' + priority); + return false; + } + } + seenLocalities.push({locality: endpoint.locality, priority: endpoint.priority}); for (const lb of endpoint.lb_endpoints) { const socketAddress = lb.endpoint?.address?.socket_address; if (!socketAddress) { + trace('EDS validation: endpoint socket_address not set'); return false; } if (socketAddress.port_specifier !== 'port_value') { + trace('EDS validation: socket_address.port_specifier !== "port_value"'); return false; } if (!(isIPv4(socketAddress.address) || isIPv6(socketAddress.address))) { + trace('EDS validation: address not a valid IPv4 or IPv6 address: ' + socketAddress.address); return false; } - } - } - return true; - } - - /** - * Given a list of edsServiceNames (which may actually be the cluster name), - * for each watcher watching a name not on the list, call that watcher's - * onResourceDoesNotExist method. - * @param allClusterNames - */ - handleMissingNames(allEdsServiceNames: Set) { - for (const [edsServiceName, watcherList] of this.watchers.entries()) { - if (!allEdsServiceNames.has(edsServiceName)) { - trace('Reporting EDS resource does not exist for edsServiceName ' + edsServiceName); - for (const watcher of watcherList) { - watcher.onResourceDoesNotExist(); + for (const address of seenAddresses) { + if (addressesEqual(socketAddress, address)) { + trace('EDS validation: duplicate address seen: ' + address); + return false; + } } + seenAddresses.push(socketAddress); } + priorityTotalWeights.set(endpoint.priority, (priorityTotalWeights.get(endpoint.priority) ?? 0) + (endpoint.load_balancing_weight?.value ?? 0)); } - } - - handleResponses(responses: ClusterLoadAssignment__Output[]) { - for (const message of responses) { - if (!this.validateResponse(message)) { - trace('EDS validation failed for message ' + JSON.stringify(message)); - return 'EDS Error: ClusterLoadAssignment validation failed'; + for (const totalWeight of priorityTotalWeights.values()) { + if (totalWeight > UINT32_MAX) { + trace('EDS validation: total weight > UINT32_MAX') + return false; } } - this.latestResponses = responses; - const allClusterNames: Set = new Set(); - for (const message of responses) { - allClusterNames.add(message.cluster_name); - const watchers = this.watchers.get(message.cluster_name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message); - } - } - trace('Received EDS updates for cluster names ' + Array.from(allClusterNames)); - this.handleMissingNames(allClusterNames); - return null; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); + for (const priority of priorityTotalWeights.keys()) { + if (priority > 0 && !priorityTotalWeights.has(priority - 1)) { + trace('EDS validation: priorities not contiguous'); + return false; } } + return true; } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts index 554712727..c215076db 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/lds-state.ts @@ -15,12 +15,13 @@ * */ -import * as protoLoader from '@grpc/proto-loader'; -import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; -import { Listener__Output } from "../generated/envoy/api/v2/Listener"; +import { experimental, logVerbosity } from "@grpc/grpc-js"; +import { Listener__Output } from '../generated/envoy/config/listener/v3/Listener'; import { RdsState } from "./rds-state"; -import { Watcher, XdsStreamState } from "./xds-stream-state"; -import { HttpConnectionManager__Output } from '../generated/envoy/config/filter/network/http_connection_manager/v2/HttpConnectionManager'; +import { BaseXdsStreamState, XdsStreamState } from "./xds-stream-state"; +import { decodeSingleResource, HTTP_CONNECTION_MANGER_TYPE_URL } from '../resources'; +import { getTopLevelFilterUrl, validateTopLevelFilter } from '../http-filter'; +import { EXPERIMENTAL_FAULT_INJECTION } from '../environment'; const TRACER_NAME = 'xds_client'; @@ -28,83 +29,61 @@ function trace(text: string): void { experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); } -const HTTP_CONNECTION_MANGER_TYPE_URL = - 'type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager'; +const ROUTER_FILTER_URL = 'type.googleapis.com/envoy.extensions.filters.http.router.v3.Router'; -export class LdsState implements XdsStreamState { - versionInfo = ''; - nonce = ''; - - private watchers: Map[]> = new Map[]>(); - private latestResponses: Listener__Output[] = []; - - constructor(private rdsState: RdsState, private updateResourceNames: () => void) {} - - addWatcher(targetName: string, watcher: Watcher) { - trace('Adding RDS watcher for targetName ' + targetName); - let watchersEntry = this.watchers.get(targetName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(targetName, watchersEntry); - } - watchersEntry.push(watcher); - - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - for (const message of this.latestResponses) { - if (message.name === targetName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing RDS update for new watcher for targetName ' + targetName); - watcher.onValidUpdate(message); - }); - } - } - if (addedServiceName) { - this.updateResourceNames(); - } +export class LdsState extends BaseXdsStreamState implements XdsStreamState { + protected getResourceName(resource: Listener__Output): string { + return resource.name; } - - removeWatcher(targetName: string, watcher: Watcher): void { - trace('Removing RDS watcher for targetName ' + targetName); - const watchersEntry = this.watchers.get(targetName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - watchersEntry.splice(entryIndex, 1); - } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(targetName); - } - } - if (removedServiceName) { - this.updateResourceNames(); - } + protected getProtocolName(): string { + return 'LDS'; + } + protected isStateOfTheWorld(): boolean { + return true; } - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); + constructor(private rdsState: RdsState, updateResourceNames: () => void) { + super(updateResourceNames); } - private validateResponse(message: Listener__Output): boolean { + public validateResponse(message: Listener__Output): boolean { if ( !( message.api_listener?.api_listener && - protoLoader.isAnyExtension(message.api_listener.api_listener) && - message.api_listener?.api_listener['@type'] === - HTTP_CONNECTION_MANGER_TYPE_URL + message.api_listener.api_listener.type_url === HTTP_CONNECTION_MANGER_TYPE_URL ) ) { return false; } - const httpConnectionManager = message.api_listener - ?.api_listener as protoLoader.AnyExtension & - HttpConnectionManager__Output; + const httpConnectionManager = decodeSingleResource(HTTP_CONNECTION_MANGER_TYPE_URL, message.api_listener!.api_listener.value); + if (EXPERIMENTAL_FAULT_INJECTION) { + const filterNames = new Set(); + for (const [index, httpFilter] of httpConnectionManager.http_filters.entries()) { + if (filterNames.has(httpFilter.name)) { + trace('LDS response validation failed: duplicate HTTP filter name ' + httpFilter.name); + return false; + } + filterNames.add(httpFilter.name); + if (!validateTopLevelFilter(httpFilter)) { + trace('LDS response validation failed: ' + httpFilter.name + ' filter validation failed'); + return false; + } + /* Validate that the last filter, and only the last filter, is the + * router filter. */ + const filterUrl = getTopLevelFilterUrl(httpFilter.typed_config!) + if (index < httpConnectionManager.http_filters.length - 1) { + if (filterUrl === ROUTER_FILTER_URL) { + trace('LDS response validation failed: router filter is before end of list'); + return false; + } + } else { + if (filterUrl !== ROUTER_FILTER_URL) { + trace('LDS response validation failed: final filter is ' + filterUrl); + return false; + } + } + } + } switch (httpConnectionManager.route_specifier) { case 'rds': return !!httpConnectionManager.rds?.config_source?.ads; @@ -113,43 +92,4 @@ export class LdsState implements XdsStreamState { } return false; } - - private handleMissingNames(allTargetNames: Set) { - for (const [targetName, watcherList] of this.watchers.entries()) { - if (!allTargetNames.has(targetName)) { - for (const watcher of watcherList) { - watcher.onResourceDoesNotExist(); - } - } - } - } - - handleResponses(responses: Listener__Output[]): string | null { - for (const message of responses) { - if (!this.validateResponse(message)) { - trace('LDS validation failed for message ' + JSON.stringify(message)); - return 'LDS Error: Route validation failed'; - } - } - this.latestResponses = responses; - const allTargetNames = new Set(); - for (const message of responses) { - allTargetNames.add(message.name); - const watchers = this.watchers.get(message.name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message); - } - } - trace('Received RDS response with route config names ' + Array.from(allTargetNames)); - this.handleMissingNames(allTargetNames); - return null; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); - } - } - } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts b/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts index 8f795e0f5..fef694517 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/rds-state.ts @@ -15,17 +15,12 @@ * */ -import { experimental, logVerbosity, StatusObject } from "@grpc/grpc-js"; -import { RouteConfiguration__Output } from "../generated/envoy/api/v2/RouteConfiguration"; -import { CdsLoadBalancingConfig } from "../load-balancer-cds"; -import { Watcher, XdsStreamState } from "./xds-stream-state"; -import ServiceConfig = experimental.ServiceConfig; - -const TRACER_NAME = 'xds_client'; - -function trace(text: string): void { - experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text); -} +import { EXPERIMENTAL_FAULT_INJECTION, EXPERIMENTAL_RETRY } from "../environment"; +import { RetryPolicy__Output } from "../generated/envoy/config/route/v3/RetryPolicy"; +import { RouteConfiguration__Output } from "../generated/envoy/config/route/v3/RouteConfiguration"; +import { Duration__Output } from "../generated/google/protobuf/Duration"; +import { validateOverrideFilter } from "../http-filter"; +import { BaseXdsStreamState, XdsStreamState } from "./xds-stream-state"; const SUPPORTED_PATH_SPECIFIERS = ['prefix', 'path', 'safe_regex']; const SUPPPORTED_HEADER_MATCH_SPECIFIERS = [ @@ -37,64 +32,45 @@ const SUPPPORTED_HEADER_MATCH_SPECIFIERS = [ 'suffix_match']; const SUPPORTED_CLUSTER_SPECIFIERS = ['cluster', 'weighted_clusters', 'cluster_header']; -export class RdsState implements XdsStreamState { - versionInfo = ''; - nonce = ''; +const UINT32_MAX = 0xFFFFFFFF; - private watchers: Map[]> = new Map[]>(); - private latestResponses: RouteConfiguration__Output[] = []; - - constructor(private updateResourceNames: () => void) {} +function durationToMs(duration: Duration__Output | null): number | null { + if (duration === null) { + return null; + } + return (Number.parseInt(duration.seconds) * 1000 + duration.nanos / 1_000_000) | 0; +} - addWatcher(routeConfigName: string, watcher: Watcher) { - trace('Adding RDS watcher for routeConfigName ' + routeConfigName); - let watchersEntry = this.watchers.get(routeConfigName); - let addedServiceName = false; - if (watchersEntry === undefined) { - addedServiceName = true; - watchersEntry = []; - this.watchers.set(routeConfigName, watchersEntry); - } - watchersEntry.push(watcher); +export class RdsState extends BaseXdsStreamState implements XdsStreamState { + protected isStateOfTheWorld(): boolean { + return false; + } + protected getResourceName(resource: RouteConfiguration__Output): string { + return resource.name; + } + protected getProtocolName(): string { + return 'RDS'; + } - /* If we have already received an update for the requested edsServiceName, - * immediately pass that update along to the watcher */ - for (const message of this.latestResponses) { - if (message.name === routeConfigName) { - /* These updates normally occur asynchronously, so we ensure that - * the same happens here */ - process.nextTick(() => { - trace('Reporting existing RDS update for new watcher for routeConfigName ' + routeConfigName); - watcher.onValidUpdate(message); - }); - } + private validateRetryPolicy(policy: RetryPolicy__Output | null): boolean { + if (policy === null) { + return true; } - if (addedServiceName) { - this.updateResourceNames(); + const numRetries = policy.num_retries?.value ?? 1 + if (numRetries < 1) { + return false; } - } - - removeWatcher(routeConfigName: string, watcher: Watcher): void { - trace('Removing RDS watcher for routeConfigName ' + routeConfigName); - const watchersEntry = this.watchers.get(routeConfigName); - let removedServiceName = false; - if (watchersEntry !== undefined) { - const entryIndex = watchersEntry.indexOf(watcher); - if (entryIndex >= 0) { - watchersEntry.splice(entryIndex, 1); + if (policy.retry_back_off) { + if (!policy.retry_back_off.base_interval) { + return false; } - if (watchersEntry.length === 0) { - removedServiceName = true; - this.watchers.delete(routeConfigName); + const baseInterval = durationToMs(policy.retry_back_off.base_interval)!; + const maxInterval = durationToMs(policy.retry_back_off.max_interval) ?? (10 * baseInterval); + if (!(maxInterval >= baseInterval) && (baseInterval > 0)) { + return false; } } - if (removedServiceName) { - this.updateResourceNames(); - } - } - - getResourceNames(): string[] { - return Array.from(this.watchers.keys()); + return true; } validateResponse(message: RouteConfiguration__Output): boolean { @@ -112,6 +88,18 @@ export class RdsState implements XdsStreamState { return false; } } + if (EXPERIMENTAL_FAULT_INJECTION) { + for (const filterConfig of Object.values(virtualHost.typed_per_filter_config ?? {})) { + if (!validateOverrideFilter(filterConfig)) { + return false; + } + } + } + if (EXPERIMENTAL_RETRY) { + if (!this.validateRetryPolicy(virtualHost.retry_policy)) { + return false; + } + } for (const route of virtualHost.routes) { const match = route.match; if (!match) { @@ -128,59 +116,41 @@ export class RdsState implements XdsStreamState { if (route.action !== 'route') { return false; } - if ((route.route === undefined) || SUPPORTED_CLUSTER_SPECIFIERS.indexOf(route.route.cluster_specifier) < 0) { + if ((route.route === undefined) || (route.route === null) || SUPPORTED_CLUSTER_SPECIFIERS.indexOf(route.route.cluster_specifier) < 0) { return false; } + if (EXPERIMENTAL_FAULT_INJECTION) { + for (const [name, filterConfig] of Object.entries(route.typed_per_filter_config ?? {})) { + if (!validateOverrideFilter(filterConfig)) { + return false; + } + } + } + if (EXPERIMENTAL_RETRY) { + if (!this.validateRetryPolicy(route.route.retry_policy)) { + return false; + } + } if (route.route!.cluster_specifier === 'weighted_clusters') { let weightSum = 0; for (const clusterWeight of route.route.weighted_clusters!.clusters) { weightSum += clusterWeight.weight?.value ?? 0; } - if (weightSum !== route.route.weighted_clusters!.total_weight?.value ?? 100) { + if (weightSum === 0 || weightSum > UINT32_MAX) { return false; } + if (EXPERIMENTAL_FAULT_INJECTION) { + for (const weightedCluster of route.route!.weighted_clusters!.clusters) { + for (const filterConfig of Object.values(weightedCluster.typed_per_filter_config ?? {})) { + if (!validateOverrideFilter(filterConfig)) { + return false; + } + } + } + } } } } return true; } - - private handleMissingNames(allRouteConfigNames: Set) { - for (const [routeConfigName, watcherList] of this.watchers.entries()) { - if (!allRouteConfigNames.has(routeConfigName)) { - for (const watcher of watcherList) { - watcher.onResourceDoesNotExist(); - } - } - } - } - - handleResponses(responses: RouteConfiguration__Output[]): string | null { - for (const message of responses) { - if (!this.validateResponse(message)) { - trace('RDS validation failed for message ' + JSON.stringify(message)); - return 'RDS Error: Route validation failed'; - } - } - this.latestResponses = responses; - const allRouteConfigNames = new Set(); - for (const message of responses) { - allRouteConfigNames.add(message.name); - const watchers = this.watchers.get(message.name) ?? []; - for (const watcher of watchers) { - watcher.onValidUpdate(message); - } - } - trace('Received RDS response with route config names ' + Array.from(allRouteConfigNames)); - this.handleMissingNames(allRouteConfigNames); - return null; - } - - reportStreamError(status: StatusObject): void { - for (const watcherList of this.watchers.values()) { - for (const watcher of watcherList) { - watcher.onTransientError(status); - } - } - } } \ No newline at end of file diff --git a/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts b/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts index 83db1781e..b04adb79a 100644 --- a/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts +++ b/packages/grpc-js-xds/src/xds-stream-state/xds-stream-state.ts @@ -15,14 +15,44 @@ * */ -import { StatusObject } from "@grpc/grpc-js"; +import { experimental, logVerbosity, Metadata, status, StatusObject } from "@grpc/grpc-js"; +import { Any__Output } from "../generated/google/protobuf/Any"; + +const TRACER_NAME = 'xds_client'; export interface Watcher { + /* Including the isV2 flag here is a bit of a kludge. It would probably be + * better for XdsStreamState#handleResponses to transform the protobuf + * message type into a library-specific configuration object type, to + * remove a lot of duplicate logic, including logic for handling that + * flag. */ onValidUpdate(update: UpdateType): void; onTransientError(error: StatusObject): void; onResourceDoesNotExist(): void; } +export interface ResourcePair { + resource: ResourceType; + raw: Any__Output; +} + +export interface AcceptedResourceEntry { + name: string; + raw: Any__Output; +} + +export interface RejectedResourceEntry { + name: string; + raw: Any__Output; + error: string; +} + +export interface HandleResponseResult { + accepted: AcceptedResourceEntry[]; + rejected: RejectedResourceEntry[]; + missing: string[]; +} + export interface XdsStreamState { versionInfo: string; nonce: string; @@ -32,7 +62,221 @@ export interface XdsStreamState { * or null if it should be acked. * @param responses */ - handleResponses(responses: ResponseType[]): string | null; + handleResponses(responses: ResourcePair[], isV2: boolean): HandleResponseResult; reportStreamError(status: StatusObject): void; + reportAdsStreamStart(): void; + + addWatcher(name: string, watcher: Watcher): void; + removeWatcher(resourceName: string, watcher: Watcher): void; +} + +interface SubscriptionEntry { + watchers: Watcher[]; + cachedResponse: ResponseType | null; + resourceTimer: NodeJS.Timer; + deletionIgnored: boolean; +} + +const RESOURCE_TIMEOUT_MS = 15_000; + +export abstract class BaseXdsStreamState implements XdsStreamState { + versionInfo = ''; + nonce = ''; + + private subscriptions: Map> = new Map>(); + private isAdsStreamRunning = false; + private ignoreResourceDeletion = false; + + constructor(private updateResourceNames: () => void) {} + + protected trace(text: string) { + experimental.trace(logVerbosity.DEBUG, TRACER_NAME, this.getProtocolName() + ' | ' + text); + } + + private startResourceTimer(subscriptionEntry: SubscriptionEntry) { + clearTimeout(subscriptionEntry.resourceTimer); + subscriptionEntry.resourceTimer = setTimeout(() => { + for (const watcher of subscriptionEntry.watchers) { + watcher.onResourceDoesNotExist(); + } + }, RESOURCE_TIMEOUT_MS); + } + + addWatcher(name: string, watcher: Watcher): void { + this.trace('Adding watcher for name ' + name); + let subscriptionEntry = this.subscriptions.get(name); + let addedName = false; + if (subscriptionEntry === undefined) { + addedName = true; + subscriptionEntry = { + watchers: [], + cachedResponse: null, + resourceTimer: setTimeout(() => {}, 0), + deletionIgnored: false + }; + if (this.isAdsStreamRunning) { + this.startResourceTimer(subscriptionEntry); + } + this.subscriptions.set(name, subscriptionEntry); + } + subscriptionEntry.watchers.push(watcher); + if (subscriptionEntry.cachedResponse !== null) { + const cachedResponse = subscriptionEntry.cachedResponse; + /* These updates normally occur asynchronously, so we ensure that + * the same happens here */ + process.nextTick(() => { + this.trace('Reporting existing update for new watcher for name ' + name); + watcher.onValidUpdate(cachedResponse); + }); + } + if (addedName) { + this.updateResourceNames(); + } + } + removeWatcher(resourceName: string, watcher: Watcher): void { + this.trace('Removing watcher for name ' + resourceName); + const subscriptionEntry = this.subscriptions.get(resourceName); + if (subscriptionEntry !== undefined) { + const entryIndex = subscriptionEntry.watchers.indexOf(watcher); + if (entryIndex >= 0) { + subscriptionEntry.watchers.splice(entryIndex, 1); + } + if (subscriptionEntry.watchers.length === 0) { + clearTimeout(subscriptionEntry.resourceTimer); + if (subscriptionEntry.deletionIgnored) { + experimental.log(logVerbosity.INFO, 'Unsubscribing from resource with previously ignored deletion: ' + resourceName); + } + this.subscriptions.delete(resourceName); + this.updateResourceNames(); + } + } + } + + getResourceNames(): string[] { + return Array.from(this.subscriptions.keys()); + } + handleResponses(responses: ResourcePair[]): HandleResponseResult { + let result: HandleResponseResult = { + accepted: [], + rejected: [], + missing: [] + } + const allResourceNames = new Set(); + for (const {resource, raw} of responses) { + const resourceName = this.getResourceName(resource); + allResourceNames.add(resourceName); + const subscriptionEntry = this.subscriptions.get(resourceName); + if (this.validateResponse(resource)) { + result.accepted.push({ + name: resourceName, + raw: raw}); + if (subscriptionEntry) { + for (const watcher of subscriptionEntry.watchers) { + watcher.onValidUpdate(resource); + } + clearTimeout(subscriptionEntry.resourceTimer); + subscriptionEntry.cachedResponse = resource; + if (subscriptionEntry.deletionIgnored) { + experimental.log(logVerbosity.INFO, `Received resource with previously ignored deletion: ${resourceName}`); + subscriptionEntry.deletionIgnored = false; + } + } + } else { + this.trace('Validation failed for message ' + JSON.stringify(resource)); + result.rejected.push({ + name: resourceName, + raw: raw, + error: `Validation failed for resource ${resourceName}` + }); + if (subscriptionEntry) { + for (const watcher of subscriptionEntry.watchers) { + watcher.onTransientError({ + code: status.UNAVAILABLE, + details: `Validation failed for resource ${resourceName}`, + metadata: new Metadata() + }); + } + clearTimeout(subscriptionEntry.resourceTimer); + } + } + } + result.missing = this.handleMissingNames(allResourceNames); + this.trace('Received response with resource names [' + Array.from(allResourceNames) + ']'); + return result; + } + reportStreamError(status: StatusObject): void { + for (const subscriptionEntry of this.subscriptions.values()) { + for (const watcher of subscriptionEntry.watchers) { + watcher.onTransientError(status); + } + clearTimeout(subscriptionEntry.resourceTimer); + } + this.isAdsStreamRunning = false; + this.nonce = ''; + } + + reportAdsStreamStart() { + if (this.isAdsStreamRunning) { + return; + } + this.isAdsStreamRunning = true; + for (const subscriptionEntry of this.subscriptions.values()) { + if (subscriptionEntry.cachedResponse === null) { + this.startResourceTimer(subscriptionEntry); + } + } + } + + private handleMissingNames(allResponseNames: Set): string[] { + if (this.isStateOfTheWorld()) { + const missingNames: string[] = []; + for (const [resourceName, subscriptionEntry] of this.subscriptions.entries()) { + if (!allResponseNames.has(resourceName) && subscriptionEntry.cachedResponse !== null) { + if (this.ignoreResourceDeletion) { + if (!subscriptionEntry.deletionIgnored) { + experimental.log(logVerbosity.ERROR, 'Ignoring nonexistent resource ' + resourceName); + subscriptionEntry.deletionIgnored = true; + } + } else { + this.trace('Reporting resource does not exist named ' + resourceName); + missingNames.push(resourceName); + for (const watcher of subscriptionEntry.watchers) { + watcher.onResourceDoesNotExist(); + } + subscriptionEntry.cachedResponse = null; + } + } + } + return missingNames; + } else { + return []; + } + } + + enableIgnoreResourceDeletion() { + this.ignoreResourceDeletion = true; + } + + /** + * Apply the validation rules for this resource type to this resource + * instance. + * This function is public so that the LDS validateResponse can call into + * the RDS validateResponse. + * @param resource The resource object sent by the xDS server + */ + public abstract validateResponse(resource: ResponseType): boolean; + /** + * Get the name of a resource object. The name is some field of the object, so + * getting it depends on the specific type. + * @param resource + */ + protected abstract getResourceName(resource: ResponseType): string; + protected abstract getProtocolName(): string; + /** + * Indicates whether responses are "state of the world", i.e. that they + * contain all resources and that omitted previously-seen resources should + * be treated as removed. + */ + protected abstract isStateOfTheWorld(): boolean; } \ No newline at end of file diff --git a/packages/grpc-js-xds/test/backend.ts b/packages/grpc-js-xds/test/backend.ts new file mode 100644 index 000000000..ce509c556 --- /dev/null +++ b/packages/grpc-js-xds/test/backend.ts @@ -0,0 +1,105 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { loadPackageDefinition, sendUnaryData, Server, ServerCredentials, ServerUnaryCall, UntypedServiceImplementation } from "@grpc/grpc-js"; +import { loadSync } from "@grpc/proto-loader"; +import { ProtoGrpcType } from "./generated/echo"; +import { EchoRequest__Output } from "./generated/grpc/testing/EchoRequest"; +import { EchoResponse } from "./generated/grpc/testing/EchoResponse"; + +const loadedProtos = loadPackageDefinition(loadSync( + [ + 'grpc/testing/echo.proto' + ], + { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + json: true, + includeDirs: [ + // Paths are relative to build/test + __dirname + '/../../proto/' + ], + })) as unknown as ProtoGrpcType; + +export class Backend { + private server: Server; + private receivedCallCount = 0; + private callListeners: (() => void)[] = []; + private port: number | null = null; + constructor() { + this.server = new Server(); + this.server.addService(loadedProtos.grpc.testing.EchoTestService.service, this as unknown as UntypedServiceImplementation); + } + Echo(call: ServerUnaryCall, callback: sendUnaryData) { + // call.request.params is currently ignored + this.addCall(); + callback(null, {message: call.request.message}); + } + + addCall() { + this.receivedCallCount++; + this.callListeners.forEach(listener => listener()); + } + + onCall(listener: () => void) { + this.callListeners.push(listener); + } + + start(callback: (error: Error | null, port: number) => void) { + this.server.bindAsync('localhost:0', ServerCredentials.createInsecure(), (error, port) => { + if (!error) { + this.port = port; + this.server.start(); + } + callback(error, port); + }) + } + + startAsync(): Promise { + return new Promise((resolve, reject) => { + this.start((error, port) => { + if (error) { + reject(error); + } else { + resolve(port); + } + }); + }); + } + + getPort(): number { + if (this.port === null) { + throw new Error('Port not set. Backend not yet started.'); + } + return this.port; + } + + getCallCount() { + return this.receivedCallCount; + } + + resetCallCount() { + this.receivedCallCount = 0; + } + + shutdown(callback: (error?: Error) => void) { + this.server.tryShutdown(callback); + } +} \ No newline at end of file diff --git a/packages/grpc-js-xds/test/client.ts b/packages/grpc-js-xds/test/client.ts new file mode 100644 index 000000000..6404a3eb2 --- /dev/null +++ b/packages/grpc-js-xds/test/client.ts @@ -0,0 +1,72 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { credentials, loadPackageDefinition } from "@grpc/grpc-js"; +import { loadSync } from "@grpc/proto-loader"; +import { ProtoGrpcType } from "./generated/echo"; +import { EchoTestServiceClient } from "./generated/grpc/testing/EchoTestService"; +import { XdsServer } from "./xds-server"; + +const loadedProtos = loadPackageDefinition(loadSync( + [ + 'grpc/testing/echo.proto' + ], + { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + json: true, + includeDirs: [ + // Paths are relative to build/test + __dirname + '/../../proto/' + ], + })) as unknown as ProtoGrpcType; + +const BOOTSTRAP_CONFIG_KEY = 'grpc.TEST_ONLY_DO_NOT_USE_IN_PROD.xds_bootstrap_config'; + +export class XdsTestClient { + private client: EchoTestServiceClient; + private callInterval: NodeJS.Timer; + + constructor(targetName: string, xdsServer: XdsServer) { + this.client = new loadedProtos.grpc.testing.EchoTestService(`xds:///${targetName}`, credentials.createInsecure(), {[BOOTSTRAP_CONFIG_KEY]: xdsServer.getBootstrapInfoString()}); + this.callInterval = setInterval(() => {}, 0); + clearInterval(this.callInterval); + } + + startCalls(interval: number) { + clearInterval(this.callInterval); + this.callInterval = setInterval(() => { + this.client.echo({message: 'test'}, (error, value) => { + if (error) { + throw error; + } + }); + }, interval); + } + + stopCalls() { + clearInterval(this.callInterval); + } + + close() { + this.stopCalls(); + this.client.close(); + } +} \ No newline at end of file diff --git a/packages/grpc-js-xds/test/framework.ts b/packages/grpc-js-xds/test/framework.ts new file mode 100644 index 000000000..945b08a3a --- /dev/null +++ b/packages/grpc-js-xds/test/framework.ts @@ -0,0 +1,208 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { ClusterLoadAssignment } from "../src/generated/envoy/config/endpoint/v3/ClusterLoadAssignment"; +import { Cluster } from "../src/generated/envoy/config/cluster/v3/Cluster"; +import { Backend } from "./backend"; +import { Locality } from "../src/generated/envoy/config/core/v3/Locality"; +import { RouteConfiguration } from "../src/generated/envoy/config/route/v3/RouteConfiguration"; +import { Route } from "../src/generated/envoy/config/route/v3/Route"; +import { Listener } from "../src/generated/envoy/config/listener/v3/Listener"; +import { HttpConnectionManager } from "../src/generated/envoy/extensions/filters/network/http_connection_manager/v3/HttpConnectionManager"; +import { AnyExtension } from "@grpc/proto-loader"; +import { HTTP_CONNECTION_MANGER_TYPE_URL } from "../src/resources"; +import { LocalityLbEndpoints } from "../src/generated/envoy/config/endpoint/v3/LocalityLbEndpoints"; +import { LbEndpoint } from "../src/generated/envoy/config/endpoint/v3/LbEndpoint"; + +interface Endpoint { + locality: Locality; + backends: Backend[]; + weight?: number; + priority?: number; +} + +function getLbEndpoint(backend: Backend): LbEndpoint { + return { + health_status: "HEALTHY", + endpoint: { + address: { + socket_address: { + address: '::1', + port_value: backend.getPort() + } + } + } + }; +} + +function getLocalityLbEndpoints(endpoint: Endpoint): LocalityLbEndpoints { + return { + lb_endpoints: endpoint.backends.map(getLbEndpoint), + locality: endpoint.locality, + load_balancing_weight: {value: endpoint.weight ?? 1}, + priority: endpoint.priority ?? 0 + } +} + +export class FakeCluster { + constructor(private name: string, private endpoints: Endpoint[]) {} + + getEndpointConfig(): ClusterLoadAssignment { + return { + cluster_name: this.name, + endpoints: this.endpoints.map(getLocalityLbEndpoints) + }; + } + + getClusterConfig(): Cluster { + return { + name: this.name, + type: 'EDS', + eds_cluster_config: {eds_config: {ads: {}}}, + lb_policy: 'ROUND_ROBIN' + } + } + + getName() { + return this.name; + } + + startAllBackends(): Promise { + return Promise.all(this.endpoints.map(endpoint => Promise.all(endpoint.backends.map(backend => backend.startAsync())))); + } + + private haveAllBackendsReceivedTraffic(): boolean { + for (const endpoint of this.endpoints) { + for (const backend of endpoint.backends) { + if (backend.getCallCount() < 1) { + return false; + } + } + } + return true; + } + + waitForAllBackendsToReceiveTraffic(): Promise { + for (const endpoint of this.endpoints) { + for (const backend of endpoint.backends) { + backend.resetCallCount(); + } + } + return new Promise((resolve, reject) => { + let finishedPromise = false; + for (const endpoint of this.endpoints) { + for (const backend of endpoint.backends) { + backend.onCall(() => { + if (finishedPromise) { + return; + } + if (this.haveAllBackendsReceivedTraffic()) { + finishedPromise = true; + resolve(); + } + }); + } + } + }); + } +} + +interface FakeRoute { + cluster?: FakeCluster; + weightedClusters?: [{cluster: FakeCluster, weight: number}]; +} + +function createRouteConfig(route: FakeRoute): Route { + if (route.cluster) { + return { + match: { + prefix: '' + }, + route: { + cluster: route.cluster.getName() + } + }; + } else { + return { + match: { + prefix: '' + }, + route: { + weighted_clusters: { + clusters: route.weightedClusters!.map(clusterWeight => ({ + name: clusterWeight.cluster.getName(), + weight: {value: clusterWeight.weight} + })) + } + } + } + } +} + +export class FakeRouteGroup { + constructor(private name: string, private routes: FakeRoute[]) {} + + getRouteConfiguration(): RouteConfiguration { + return { + name: this.name, + virtual_hosts: [{ + domains: ['*'], + routes: this.routes.map(createRouteConfig) + }] + }; + } + + getListener(): Listener { + const httpConnectionManager: HttpConnectionManager & AnyExtension = { + '@type': HTTP_CONNECTION_MANGER_TYPE_URL, + rds: { + route_config_name: this.name, + config_source: {ads: {}} + } + } + return { + name: this.name, + api_listener: { + api_listener: httpConnectionManager + } + }; + } + + startAllBackends(): Promise { + return Promise.all(this.routes.map(route => { + if (route.cluster) { + return route.cluster.startAllBackends(); + } else if (route.weightedClusters) { + return Promise.all(route.weightedClusters.map(clusterWeight => clusterWeight.cluster.startAllBackends())); + } else { + return Promise.resolve(); + } + })); + } + + waitForAllBackendsToReceiveTraffic(): Promise { + return Promise.all(this.routes.map(route => { + if (route.cluster) { + return route.cluster.waitForAllBackendsToReceiveTraffic(); + } else if (route.weightedClusters) { + return Promise.all(route.weightedClusters.map(clusterWeight => clusterWeight.cluster.waitForAllBackendsToReceiveTraffic())).then(() => {}); + } else { + return Promise.resolve(); + } + })); + } +} \ No newline at end of file diff --git a/packages/grpc-js-xds/test/generated/echo.ts b/packages/grpc-js-xds/test/generated/echo.ts new file mode 100644 index 000000000..537a49cfa --- /dev/null +++ b/packages/grpc-js-xds/test/generated/echo.ts @@ -0,0 +1,46 @@ +import type * as grpc from '@grpc/grpc-js'; +import type { MessageTypeDefinition } from '@grpc/proto-loader'; + +import type { EchoTest1ServiceClient as _grpc_testing_EchoTest1ServiceClient, EchoTest1ServiceDefinition as _grpc_testing_EchoTest1ServiceDefinition } from './grpc/testing/EchoTest1Service'; +import type { EchoTest2ServiceClient as _grpc_testing_EchoTest2ServiceClient, EchoTest2ServiceDefinition as _grpc_testing_EchoTest2ServiceDefinition } from './grpc/testing/EchoTest2Service'; +import type { EchoTestServiceClient as _grpc_testing_EchoTestServiceClient, EchoTestServiceDefinition as _grpc_testing_EchoTestServiceDefinition } from './grpc/testing/EchoTestService'; +import type { NoRpcServiceClient as _grpc_testing_NoRpcServiceClient, NoRpcServiceDefinition as _grpc_testing_NoRpcServiceDefinition } from './grpc/testing/NoRpcService'; +import type { UnimplementedEchoServiceClient as _grpc_testing_UnimplementedEchoServiceClient, UnimplementedEchoServiceDefinition as _grpc_testing_UnimplementedEchoServiceDefinition } from './grpc/testing/UnimplementedEchoService'; + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + grpc: { + testing: { + DebugInfo: MessageTypeDefinition + EchoRequest: MessageTypeDefinition + EchoResponse: MessageTypeDefinition + EchoTest1Service: SubtypeConstructor & { service: _grpc_testing_EchoTest1ServiceDefinition } + EchoTest2Service: SubtypeConstructor & { service: _grpc_testing_EchoTest2ServiceDefinition } + EchoTestService: SubtypeConstructor & { service: _grpc_testing_EchoTestServiceDefinition } + ErrorStatus: MessageTypeDefinition + /** + * A service without any rpc defined to test coverage. + */ + NoRpcService: SubtypeConstructor & { service: _grpc_testing_NoRpcServiceDefinition } + RequestParams: MessageTypeDefinition + ResponseParams: MessageTypeDefinition + SimpleRequest: MessageTypeDefinition + SimpleResponse: MessageTypeDefinition + StringValue: MessageTypeDefinition + UnimplementedEchoService: SubtypeConstructor & { service: _grpc_testing_UnimplementedEchoServiceDefinition } + } + } + xds: { + data: { + orca: { + v3: { + OrcaLoadReport: MessageTypeDefinition + } + } + } + } +} + diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/DebugInfo.ts b/packages/grpc-js-xds/test/generated/grpc/testing/DebugInfo.ts new file mode 100644 index 000000000..123188fe3 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/DebugInfo.ts @@ -0,0 +1,18 @@ +// Original file: proto/grpc/testing/echo_messages.proto + + +/** + * Message to be echoed back serialized in trailer. + */ +export interface DebugInfo { + 'stack_entries'?: (string)[]; + 'detail'?: (string); +} + +/** + * Message to be echoed back serialized in trailer. + */ +export interface DebugInfo__Output { + 'stack_entries': (string)[]; + 'detail': (string); +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/EchoRequest.ts b/packages/grpc-js-xds/test/generated/grpc/testing/EchoRequest.ts new file mode 100644 index 000000000..cadf04f7a --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/EchoRequest.ts @@ -0,0 +1,13 @@ +// Original file: proto/grpc/testing/echo_messages.proto + +import type { RequestParams as _grpc_testing_RequestParams, RequestParams__Output as _grpc_testing_RequestParams__Output } from '../../grpc/testing/RequestParams'; + +export interface EchoRequest { + 'message'?: (string); + 'param'?: (_grpc_testing_RequestParams | null); +} + +export interface EchoRequest__Output { + 'message': (string); + 'param': (_grpc_testing_RequestParams__Output | null); +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/EchoResponse.ts b/packages/grpc-js-xds/test/generated/grpc/testing/EchoResponse.ts new file mode 100644 index 000000000..d54beaf4f --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/EchoResponse.ts @@ -0,0 +1,13 @@ +// Original file: proto/grpc/testing/echo_messages.proto + +import type { ResponseParams as _grpc_testing_ResponseParams, ResponseParams__Output as _grpc_testing_ResponseParams__Output } from '../../grpc/testing/ResponseParams'; + +export interface EchoResponse { + 'message'?: (string); + 'param'?: (_grpc_testing_ResponseParams | null); +} + +export interface EchoResponse__Output { + 'message': (string); + 'param': (_grpc_testing_ResponseParams__Output | null); +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/EchoTest1Service.ts b/packages/grpc-js-xds/test/generated/grpc/testing/EchoTest1Service.ts new file mode 100644 index 000000000..a2b1947f6 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/EchoTest1Service.ts @@ -0,0 +1,117 @@ +// Original file: proto/grpc/testing/echo.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { EchoRequest as _grpc_testing_EchoRequest, EchoRequest__Output as _grpc_testing_EchoRequest__Output } from '../../grpc/testing/EchoRequest'; +import type { EchoResponse as _grpc_testing_EchoResponse, EchoResponse__Output as _grpc_testing_EchoResponse__Output } from '../../grpc/testing/EchoResponse'; +import type { SimpleRequest as _grpc_testing_SimpleRequest, SimpleRequest__Output as _grpc_testing_SimpleRequest__Output } from '../../grpc/testing/SimpleRequest'; +import type { SimpleResponse as _grpc_testing_SimpleResponse, SimpleResponse__Output as _grpc_testing_SimpleResponse__Output } from '../../grpc/testing/SimpleResponse'; + +export interface EchoTest1ServiceClient extends grpc.Client { + BidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + BidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + bidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + bidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + + Echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + Echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + Echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + RequestStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + + ResponseStream(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + ResponseStream(argument: _grpc_testing_EchoRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + responseStream(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + responseStream(argument: _grpc_testing_EchoRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + +} + +export interface EchoTest1ServiceHandlers extends grpc.UntypedServiceImplementation { + BidiStream: grpc.handleBidiStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + CheckClientInitialMetadata: grpc.handleUnaryCall<_grpc_testing_SimpleRequest__Output, _grpc_testing_SimpleResponse>; + + Echo: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Echo1: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Echo2: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + RequestStream: grpc.handleClientStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + ResponseStream: grpc.handleServerStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Unimplemented: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + +} + +export interface EchoTest1ServiceDefinition extends grpc.ServiceDefinition { + BidiStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + CheckClientInitialMetadata: MethodDefinition<_grpc_testing_SimpleRequest, _grpc_testing_SimpleResponse, _grpc_testing_SimpleRequest__Output, _grpc_testing_SimpleResponse__Output> + Echo: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Echo1: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Echo2: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + RequestStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + ResponseStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Unimplemented: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/EchoTest2Service.ts b/packages/grpc-js-xds/test/generated/grpc/testing/EchoTest2Service.ts new file mode 100644 index 000000000..033e70143 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/EchoTest2Service.ts @@ -0,0 +1,117 @@ +// Original file: proto/grpc/testing/echo.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { EchoRequest as _grpc_testing_EchoRequest, EchoRequest__Output as _grpc_testing_EchoRequest__Output } from '../../grpc/testing/EchoRequest'; +import type { EchoResponse as _grpc_testing_EchoResponse, EchoResponse__Output as _grpc_testing_EchoResponse__Output } from '../../grpc/testing/EchoResponse'; +import type { SimpleRequest as _grpc_testing_SimpleRequest, SimpleRequest__Output as _grpc_testing_SimpleRequest__Output } from '../../grpc/testing/SimpleRequest'; +import type { SimpleResponse as _grpc_testing_SimpleResponse, SimpleResponse__Output as _grpc_testing_SimpleResponse__Output } from '../../grpc/testing/SimpleResponse'; + +export interface EchoTest2ServiceClient extends grpc.Client { + BidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + BidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + bidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + bidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + + Echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + Echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + Echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + RequestStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + + ResponseStream(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + ResponseStream(argument: _grpc_testing_EchoRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + responseStream(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + responseStream(argument: _grpc_testing_EchoRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + +} + +export interface EchoTest2ServiceHandlers extends grpc.UntypedServiceImplementation { + BidiStream: grpc.handleBidiStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + CheckClientInitialMetadata: grpc.handleUnaryCall<_grpc_testing_SimpleRequest__Output, _grpc_testing_SimpleResponse>; + + Echo: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Echo1: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Echo2: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + RequestStream: grpc.handleClientStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + ResponseStream: grpc.handleServerStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Unimplemented: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + +} + +export interface EchoTest2ServiceDefinition extends grpc.ServiceDefinition { + BidiStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + CheckClientInitialMetadata: MethodDefinition<_grpc_testing_SimpleRequest, _grpc_testing_SimpleResponse, _grpc_testing_SimpleRequest__Output, _grpc_testing_SimpleResponse__Output> + Echo: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Echo1: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Echo2: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + RequestStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + ResponseStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Unimplemented: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/EchoTestService.ts b/packages/grpc-js-xds/test/generated/grpc/testing/EchoTestService.ts new file mode 100644 index 000000000..d1fa2d075 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/EchoTestService.ts @@ -0,0 +1,150 @@ +// Original file: proto/grpc/testing/echo.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { EchoRequest as _grpc_testing_EchoRequest, EchoRequest__Output as _grpc_testing_EchoRequest__Output } from '../../grpc/testing/EchoRequest'; +import type { EchoResponse as _grpc_testing_EchoResponse, EchoResponse__Output as _grpc_testing_EchoResponse__Output } from '../../grpc/testing/EchoResponse'; +import type { SimpleRequest as _grpc_testing_SimpleRequest, SimpleRequest__Output as _grpc_testing_SimpleRequest__Output } from '../../grpc/testing/SimpleRequest'; +import type { SimpleResponse as _grpc_testing_SimpleResponse, SimpleResponse__Output as _grpc_testing_SimpleResponse__Output } from '../../grpc/testing/SimpleResponse'; +import type { StringValue as _grpc_testing_StringValue, StringValue__Output as _grpc_testing_StringValue__Output } from '../../grpc/testing/StringValue'; + +export interface EchoTestServiceClient extends grpc.Client { + BidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + BidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + bidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + bidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + CheckClientInitialMetadata(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + checkClientInitialMetadata(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_SimpleResponse__Output>): grpc.ClientUnaryCall; + + CheckDeadlineSet(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + CheckDeadlineSet(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + CheckDeadlineSet(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + CheckDeadlineSet(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineSet(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineSet(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineSet(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineSet(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + + CheckDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + CheckDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + CheckDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + CheckDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + checkDeadlineUpperBound(argument: _grpc_testing_SimpleRequest, callback: grpc.requestCallback<_grpc_testing_StringValue__Output>): grpc.ClientUnaryCall; + + Echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + Echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo1(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo1(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + Echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Echo2(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + echo2(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + RequestStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + RequestStream(callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + requestStream(callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientWritableStream<_grpc_testing_EchoRequest>; + + ResponseStream(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + ResponseStream(argument: _grpc_testing_EchoRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + responseStream(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + responseStream(argument: _grpc_testing_EchoRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_grpc_testing_EchoResponse__Output>; + + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + + UnimplementedBidi(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + UnimplementedBidi(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + unimplementedBidi(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + unimplementedBidi(options?: grpc.CallOptions): grpc.ClientDuplexStream<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse__Output>; + +} + +export interface EchoTestServiceHandlers extends grpc.UntypedServiceImplementation { + BidiStream: grpc.handleBidiStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + /** + * A service which checks that the initial metadata sent over contains some + * expected key value pair + */ + CheckClientInitialMetadata: grpc.handleUnaryCall<_grpc_testing_SimpleRequest__Output, _grpc_testing_SimpleResponse>; + + CheckDeadlineSet: grpc.handleUnaryCall<_grpc_testing_SimpleRequest__Output, _grpc_testing_StringValue>; + + CheckDeadlineUpperBound: grpc.handleUnaryCall<_grpc_testing_SimpleRequest__Output, _grpc_testing_StringValue>; + + Echo: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Echo1: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Echo2: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + RequestStream: grpc.handleClientStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + ResponseStream: grpc.handleServerStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + Unimplemented: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + + UnimplementedBidi: grpc.handleBidiStreamingCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + +} + +export interface EchoTestServiceDefinition extends grpc.ServiceDefinition { + BidiStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + CheckClientInitialMetadata: MethodDefinition<_grpc_testing_SimpleRequest, _grpc_testing_SimpleResponse, _grpc_testing_SimpleRequest__Output, _grpc_testing_SimpleResponse__Output> + CheckDeadlineSet: MethodDefinition<_grpc_testing_SimpleRequest, _grpc_testing_StringValue, _grpc_testing_SimpleRequest__Output, _grpc_testing_StringValue__Output> + CheckDeadlineUpperBound: MethodDefinition<_grpc_testing_SimpleRequest, _grpc_testing_StringValue, _grpc_testing_SimpleRequest__Output, _grpc_testing_StringValue__Output> + Echo: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Echo1: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Echo2: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + RequestStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + ResponseStream: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + Unimplemented: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> + UnimplementedBidi: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/ErrorStatus.ts b/packages/grpc-js-xds/test/generated/grpc/testing/ErrorStatus.ts new file mode 100644 index 000000000..42ff36d9a --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/ErrorStatus.ts @@ -0,0 +1,20 @@ +// Original file: proto/grpc/testing/echo_messages.proto + + +/** + * Error status client expects to see. + */ +export interface ErrorStatus { + 'code'?: (number); + 'error_message'?: (string); + 'binary_error_details'?: (string); +} + +/** + * Error status client expects to see. + */ +export interface ErrorStatus__Output { + 'code': (number); + 'error_message': (string); + 'binary_error_details': (string); +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/NoRpcService.ts b/packages/grpc-js-xds/test/generated/grpc/testing/NoRpcService.ts new file mode 100644 index 000000000..7427c8097 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/NoRpcService.ts @@ -0,0 +1,19 @@ +// Original file: proto/grpc/testing/echo.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' + +/** + * A service without any rpc defined to test coverage. + */ +export interface NoRpcServiceClient extends grpc.Client { +} + +/** + * A service without any rpc defined to test coverage. + */ +export interface NoRpcServiceHandlers extends grpc.UntypedServiceImplementation { +} + +export interface NoRpcServiceDefinition extends grpc.ServiceDefinition { +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/RequestParams.ts b/packages/grpc-js-xds/test/generated/grpc/testing/RequestParams.ts new file mode 100644 index 000000000..e8c5ef1d1 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/RequestParams.ts @@ -0,0 +1,75 @@ +// Original file: proto/grpc/testing/echo_messages.proto + +import type { DebugInfo as _grpc_testing_DebugInfo, DebugInfo__Output as _grpc_testing_DebugInfo__Output } from '../../grpc/testing/DebugInfo'; +import type { ErrorStatus as _grpc_testing_ErrorStatus, ErrorStatus__Output as _grpc_testing_ErrorStatus__Output } from '../../grpc/testing/ErrorStatus'; +import type { OrcaLoadReport as _xds_data_orca_v3_OrcaLoadReport, OrcaLoadReport__Output as _xds_data_orca_v3_OrcaLoadReport__Output } from '../../xds/data/orca/v3/OrcaLoadReport'; + +export interface RequestParams { + 'echo_deadline'?: (boolean); + 'client_cancel_after_us'?: (number); + 'server_cancel_after_us'?: (number); + 'echo_metadata'?: (boolean); + 'check_auth_context'?: (boolean); + 'response_message_length'?: (number); + 'echo_peer'?: (boolean); + /** + * will force check_auth_context. + */ + 'expected_client_identity'?: (string); + 'skip_cancelled_check'?: (boolean); + 'expected_transport_security_type'?: (string); + 'debug_info'?: (_grpc_testing_DebugInfo | null); + /** + * Server should not see a request with this set. + */ + 'server_die'?: (boolean); + 'binary_error_details'?: (string); + 'expected_error'?: (_grpc_testing_ErrorStatus | null); + /** + * sleep when invoking server for deadline tests + */ + 'server_sleep_us'?: (number); + /** + * which backend to send request to + */ + 'backend_channel_idx'?: (number); + 'echo_metadata_initially'?: (boolean); + 'server_notify_client_when_started'?: (boolean); + 'backend_metrics'?: (_xds_data_orca_v3_OrcaLoadReport | null); + 'echo_host_from_authority_header'?: (boolean); +} + +export interface RequestParams__Output { + 'echo_deadline': (boolean); + 'client_cancel_after_us': (number); + 'server_cancel_after_us': (number); + 'echo_metadata': (boolean); + 'check_auth_context': (boolean); + 'response_message_length': (number); + 'echo_peer': (boolean); + /** + * will force check_auth_context. + */ + 'expected_client_identity': (string); + 'skip_cancelled_check': (boolean); + 'expected_transport_security_type': (string); + 'debug_info': (_grpc_testing_DebugInfo__Output | null); + /** + * Server should not see a request with this set. + */ + 'server_die': (boolean); + 'binary_error_details': (string); + 'expected_error': (_grpc_testing_ErrorStatus__Output | null); + /** + * sleep when invoking server for deadline tests + */ + 'server_sleep_us': (number); + /** + * which backend to send request to + */ + 'backend_channel_idx': (number); + 'echo_metadata_initially': (boolean); + 'server_notify_client_when_started': (boolean); + 'backend_metrics': (_xds_data_orca_v3_OrcaLoadReport__Output | null); + 'echo_host_from_authority_header': (boolean); +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/ResponseParams.ts b/packages/grpc-js-xds/test/generated/grpc/testing/ResponseParams.ts new file mode 100644 index 000000000..588e463c2 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/ResponseParams.ts @@ -0,0 +1,15 @@ +// Original file: proto/grpc/testing/echo_messages.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface ResponseParams { + 'request_deadline'?: (number | string | Long); + 'host'?: (string); + 'peer'?: (string); +} + +export interface ResponseParams__Output { + 'request_deadline': (string); + 'host': (string); + 'peer': (string); +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/SimpleRequest.ts b/packages/grpc-js-xds/test/generated/grpc/testing/SimpleRequest.ts new file mode 100644 index 000000000..292a2020c --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/SimpleRequest.ts @@ -0,0 +1,8 @@ +// Original file: proto/grpc/testing/simple_messages.proto + + +export interface SimpleRequest { +} + +export interface SimpleRequest__Output { +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/SimpleResponse.ts b/packages/grpc-js-xds/test/generated/grpc/testing/SimpleResponse.ts new file mode 100644 index 000000000..3e8735e5e --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/SimpleResponse.ts @@ -0,0 +1,8 @@ +// Original file: proto/grpc/testing/simple_messages.proto + + +export interface SimpleResponse { +} + +export interface SimpleResponse__Output { +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/StringValue.ts b/packages/grpc-js-xds/test/generated/grpc/testing/StringValue.ts new file mode 100644 index 000000000..4a779ae2b --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/StringValue.ts @@ -0,0 +1,10 @@ +// Original file: proto/grpc/testing/simple_messages.proto + + +export interface StringValue { + 'message'?: (string); +} + +export interface StringValue__Output { + 'message': (string); +} diff --git a/packages/grpc-js-xds/test/generated/grpc/testing/UnimplementedEchoService.ts b/packages/grpc-js-xds/test/generated/grpc/testing/UnimplementedEchoService.ts new file mode 100644 index 000000000..48128976e --- /dev/null +++ b/packages/grpc-js-xds/test/generated/grpc/testing/UnimplementedEchoService.ts @@ -0,0 +1,27 @@ +// Original file: proto/grpc/testing/echo.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { EchoRequest as _grpc_testing_EchoRequest, EchoRequest__Output as _grpc_testing_EchoRequest__Output } from '../../grpc/testing/EchoRequest'; +import type { EchoResponse as _grpc_testing_EchoResponse, EchoResponse__Output as _grpc_testing_EchoResponse__Output } from '../../grpc/testing/EchoResponse'; + +export interface UnimplementedEchoServiceClient extends grpc.Client { + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + Unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + unimplemented(argument: _grpc_testing_EchoRequest, callback: grpc.requestCallback<_grpc_testing_EchoResponse__Output>): grpc.ClientUnaryCall; + +} + +export interface UnimplementedEchoServiceHandlers extends grpc.UntypedServiceImplementation { + Unimplemented: grpc.handleUnaryCall<_grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse>; + +} + +export interface UnimplementedEchoServiceDefinition extends grpc.ServiceDefinition { + Unimplemented: MethodDefinition<_grpc_testing_EchoRequest, _grpc_testing_EchoResponse, _grpc_testing_EchoRequest__Output, _grpc_testing_EchoResponse__Output> +} diff --git a/packages/grpc-js-xds/test/generated/xds/data/orca/v3/OrcaLoadReport.ts b/packages/grpc-js-xds/test/generated/xds/data/orca/v3/OrcaLoadReport.ts new file mode 100644 index 000000000..d66c42713 --- /dev/null +++ b/packages/grpc-js-xds/test/generated/xds/data/orca/v3/OrcaLoadReport.ts @@ -0,0 +1,59 @@ +// Original file: proto/grpc/testing/xds/v3/orca_load_report.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface OrcaLoadReport { + /** + * CPU utilization expressed as a fraction of available CPU resources. This + * should be derived from the latest sample or measurement. + */ + 'cpu_utilization'?: (number | string); + /** + * Memory utilization expressed as a fraction of available memory + * resources. This should be derived from the latest sample or measurement. + */ + 'mem_utilization'?: (number | string); + /** + * Total RPS being served by an endpoint. This should cover all services that an endpoint is + * responsible for. + */ + 'rps'?: (number | string | Long); + /** + * Application specific requests costs. Each value is an absolute cost (e.g. 3487 bytes of + * storage) associated with the request. + */ + 'request_cost'?: ({[key: string]: number | string}); + /** + * Resource utilization values. Each value is expressed as a fraction of total resources + * available, derived from the latest sample or measurement. + */ + 'utilization'?: ({[key: string]: number | string}); +} + +export interface OrcaLoadReport__Output { + /** + * CPU utilization expressed as a fraction of available CPU resources. This + * should be derived from the latest sample or measurement. + */ + 'cpu_utilization': (number | string); + /** + * Memory utilization expressed as a fraction of available memory + * resources. This should be derived from the latest sample or measurement. + */ + 'mem_utilization': (number | string); + /** + * Total RPS being served by an endpoint. This should cover all services that an endpoint is + * responsible for. + */ + 'rps': (string); + /** + * Application specific requests costs. Each value is an absolute cost (e.g. 3487 bytes of + * storage) associated with the request. + */ + 'request_cost': ({[key: string]: number | string}); + /** + * Resource utilization values. Each value is expressed as a fraction of total resources + * available, derived from the latest sample or measurement. + */ + 'utilization': ({[key: string]: number | string}); +} diff --git a/packages/grpc-js-xds/test/test-core.ts b/packages/grpc-js-xds/test/test-core.ts new file mode 100644 index 000000000..d0d1b6031 --- /dev/null +++ b/packages/grpc-js-xds/test/test-core.ts @@ -0,0 +1,63 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { Backend } from "./backend"; +import { XdsTestClient } from "./client"; +import { FakeCluster, FakeRouteGroup } from "./framework"; +import { XdsServer } from "./xds-server"; + +import { register } from "../src"; +import assert = require("assert"); + +register(); + +describe('core xDS functionality', () => { + let xdsServer: XdsServer; + let client: XdsTestClient; + beforeEach(done => { + xdsServer = new XdsServer(); + xdsServer.startServer(error => { + done(error); + }); + }); + afterEach(() => { + client?.close(); + xdsServer?.shutdownServer(); + }) + it('should route requests to the single backend', done => { + const cluster = new FakeCluster('cluster1', [{backends: [new Backend()], locality:{region: 'region1'}}]); + const routeGroup = new FakeRouteGroup('route1', [{cluster: cluster}]); + routeGroup.startAllBackends().then(() => { + xdsServer.setEdsResource(cluster.getEndpointConfig()); + xdsServer.setCdsResource(cluster.getClusterConfig()); + xdsServer.setRdsResource(routeGroup.getRouteConfiguration()); + xdsServer.setLdsResource(routeGroup.getListener()); + xdsServer.addResponseListener((typeUrl, responseState) => { + if (responseState.state === 'NACKED') { + client.stopCalls(); + assert.fail(`Client NACKED ${typeUrl} resource with message ${responseState.errorMessage}`); + } + }) + client = new XdsTestClient('route1', xdsServer); + client.startCalls(100); + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + client.stopCalls(); + done(); + }, reason => done(reason)); + }, reason => done(reason)); + }); +}); \ No newline at end of file diff --git a/packages/grpc-js-xds/test/test-nack.ts b/packages/grpc-js-xds/test/test-nack.ts new file mode 100644 index 000000000..9395628a6 --- /dev/null +++ b/packages/grpc-js-xds/test/test-nack.ts @@ -0,0 +1,160 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as assert from 'assert'; +import { register } from "../src"; +import { Backend } from "./backend"; +import { XdsTestClient } from "./client"; +import { FakeCluster, FakeRouteGroup } from "./framework"; +import { XdsServer } from "./xds-server"; + +register(); + +describe('Validation errors', () => { + let xdsServer: XdsServer; + let client: XdsTestClient; + beforeEach(done => { + xdsServer = new XdsServer(); + xdsServer.startServer(error => { + done(error); + }); + }); + afterEach(() => { + client?.close(); + xdsServer?.shutdownServer(); + }); + it('Should continue to use a valid resource after receiving an invalid EDS update', done => { + const cluster = new FakeCluster('cluster1', [{backends: [new Backend()], locality: {region: 'region1'}}]); + const routeGroup = new FakeRouteGroup('route1', [{cluster: cluster}]); + routeGroup.startAllBackends().then(() => { + xdsServer.setEdsResource(cluster.getEndpointConfig()); + xdsServer.setCdsResource(cluster.getClusterConfig()); + xdsServer.setRdsResource(routeGroup.getRouteConfiguration()); + xdsServer.setLdsResource(routeGroup.getListener()); + client = new XdsTestClient('route1', xdsServer); + client.startCalls(100); + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + // After backends receive calls, set invalid EDS resource + const invalidEdsResource = {cluster_name: cluster.getEndpointConfig().cluster_name, endpoints: [{}]}; + xdsServer.setEdsResource(invalidEdsResource); + let seenNack = false; + xdsServer.addResponseListener((typeUrl, responseState) => { + if (responseState.state === 'NACKED') { + if (seenNack) { + return; + } + seenNack = true; + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + client.stopCalls(); + done(); + }); + } + }); + }, reason => done(reason)); + }, reason => done(reason)); + }); + it('Should continue to use a valid resource after receiving an invalid CDS update', done => { + const cluster = new FakeCluster('cluster1', [{backends: [new Backend()], locality: {region: 'region1'}}]); + const routeGroup = new FakeRouteGroup('route1', [{cluster: cluster}]); + routeGroup.startAllBackends().then(() => { + xdsServer.setEdsResource(cluster.getEndpointConfig()); + xdsServer.setCdsResource(cluster.getClusterConfig()); + xdsServer.setRdsResource(routeGroup.getRouteConfiguration()); + xdsServer.setLdsResource(routeGroup.getListener()); + client = new XdsTestClient('route1', xdsServer); + client.startCalls(100); + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + // After backends receive calls, set invalid CDS resource + const invalidCdsResource = {name: cluster.getClusterConfig().name}; + xdsServer.setCdsResource(invalidCdsResource); + let seenNack = false; + xdsServer.addResponseListener((typeUrl, responseState) => { + if (responseState.state === 'NACKED') { + if (seenNack) { + return; + } + seenNack = true; + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + client.stopCalls(); + done(); + }); + } + }); + }, reason => done(reason)); + }, reason => done(reason)); + }); + it('Should continue to use a valid resource after receiving an invalid RDS update', done => { + const cluster = new FakeCluster('cluster1', [{backends: [new Backend()], locality: {region: 'region1'}}]); + const routeGroup = new FakeRouteGroup('route1', [{cluster: cluster}]); + routeGroup.startAllBackends().then(() => { + xdsServer.setEdsResource(cluster.getEndpointConfig()); + xdsServer.setCdsResource(cluster.getClusterConfig()); + xdsServer.setRdsResource(routeGroup.getRouteConfiguration()); + xdsServer.setLdsResource(routeGroup.getListener()); + client = new XdsTestClient('route1', xdsServer); + client.startCalls(100); + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + // After backends receive calls, set invalid RDS resource + const invalidRdsResource = {name: routeGroup.getRouteConfiguration().name, virtual_hosts: [{domains: ['**']}]}; + xdsServer.setRdsResource(invalidRdsResource); + let seenNack = false; + xdsServer.addResponseListener((typeUrl, responseState) => { + if (responseState.state === 'NACKED') { + if (seenNack) { + return; + } + seenNack = true; + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + client.stopCalls(); + done(); + }); + } + }); + }, reason => done(reason)); + }, reason => done(reason)); + }); + it('Should continue to use a valid resource after receiving an invalid LDS update', done => { + const cluster = new FakeCluster('cluster1', [{backends: [new Backend()], locality: {region: 'region1'}}]); + const routeGroup = new FakeRouteGroup('route1', [{cluster: cluster}]); + routeGroup.startAllBackends().then(() => { + xdsServer.setEdsResource(cluster.getEndpointConfig()); + xdsServer.setCdsResource(cluster.getClusterConfig()); + xdsServer.setRdsResource(routeGroup.getRouteConfiguration()); + xdsServer.setLdsResource(routeGroup.getListener()); + client = new XdsTestClient('route1', xdsServer); + client.startCalls(100); + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + // After backends receive calls, set invalid LDS resource + const invalidLdsResource = {name: routeGroup.getListener().name}; + xdsServer.setLdsResource(invalidLdsResource); + let seenNack = false; + xdsServer.addResponseListener((typeUrl, responseState) => { + if (responseState.state === 'NACKED') { + if (seenNack) { + return; + } + seenNack = true; + routeGroup.waitForAllBackendsToReceiveTraffic().then(() => { + client.stopCalls(); + done(); + }); + } + }); + }, reason => done(reason)); + }, reason => done(reason)); + }); +}); diff --git a/packages/grpc-js-xds/test/xds-server.ts b/packages/grpc-js-xds/test/xds-server.ts new file mode 100644 index 000000000..b82a3a673 --- /dev/null +++ b/packages/grpc-js-xds/test/xds-server.ts @@ -0,0 +1,342 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { ServerDuplexStream, Server, UntypedServiceImplementation, ServerCredentials, loadPackageDefinition } from "@grpc/grpc-js"; +import { AnyExtension, loadSync } from "@grpc/proto-loader"; +import { EventEmitter } from "stream"; +import { Cluster } from "../src/generated/envoy/config/cluster/v3/Cluster"; +import { ClusterLoadAssignment } from "../src/generated/envoy/config/endpoint/v3/ClusterLoadAssignment"; +import { Listener } from "../src/generated/envoy/config/listener/v3/Listener"; +import { RouteConfiguration } from "../src/generated/envoy/config/route/v3/RouteConfiguration"; +import { AggregatedDiscoveryServiceHandlers } from "../src/generated/envoy/service/discovery/v3/AggregatedDiscoveryService"; +import { DiscoveryRequest__Output } from "../src/generated/envoy/service/discovery/v3/DiscoveryRequest"; +import { DiscoveryResponse } from "../src/generated/envoy/service/discovery/v3/DiscoveryResponse"; +import { Any } from "../src/generated/google/protobuf/Any"; +import { LDS_TYPE_URL, RDS_TYPE_URL, CDS_TYPE_URL, EDS_TYPE_URL, LdsTypeUrl, RdsTypeUrl, CdsTypeUrl, EdsTypeUrl, AdsTypeUrl } from "../src/resources" +import * as adsTypes from '../src/generated/ads'; +import * as lrsTypes from '../src/generated/lrs'; +import { LoadStatsRequest__Output } from "../src/generated/envoy/service/load_stats/v3/LoadStatsRequest"; +import { LoadStatsResponse } from "../src/generated/envoy/service/load_stats/v3/LoadStatsResponse"; + +const loadedProtos = loadPackageDefinition(loadSync( + [ + 'envoy/service/discovery/v3/ads.proto', + 'envoy/service/load_stats/v3/lrs.proto', + 'envoy/config/listener/v3/listener.proto', + 'envoy/config/route/v3/route.proto', + 'envoy/config/cluster/v3/cluster.proto', + 'envoy/config/endpoint/v3/endpoint.proto', + 'envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto' + ], + { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + json: true, + includeDirs: [ + // Paths are relative to src/build + __dirname + '/../../deps/envoy-api/', + __dirname + '/../../deps/xds/', + __dirname + '/../../deps/googleapis/', + __dirname + '/../../deps/protoc-gen-validate/', + ], + })) as unknown as adsTypes.ProtoGrpcType & lrsTypes.ProtoGrpcType; + +type AdsInputType = T extends EdsTypeUrl + ? ClusterLoadAssignment + : T extends CdsTypeUrl + ? Cluster + : T extends RdsTypeUrl + ? RouteConfiguration + : Listener; + +const ADS_TYPE_URLS = new Set([LDS_TYPE_URL, RDS_TYPE_URL, CDS_TYPE_URL, EDS_TYPE_URL]); + +interface ResponseState { + state: 'ACKED' | 'NACKED'; + errorMessage?: string; +} + +interface ResponseListener { + (typeUrl: AdsTypeUrl, responseState: ResponseState): void; +} + +type ResourceAny = AdsInputType & {'@type': T}; + +interface ResourceState { + resource?: ResourceAny; + resourceTypeVersion: number; + subscriptions: Set; +} + +interface ResourceTypeState { + resourceTypeVersion: number; + /** + * Key type is type URL + */ + resourceNameMap: Map>; +} + +interface ResourceMap { + [EDS_TYPE_URL]: ResourceTypeState; + [CDS_TYPE_URL]: ResourceTypeState; + [RDS_TYPE_URL]: ResourceTypeState; + [LDS_TYPE_URL]: ResourceTypeState; +} + +function isAdsTypeUrl(value: string): value is AdsTypeUrl { + return ADS_TYPE_URLS.has(value); +} + +export class XdsServer { + private resourceMap: ResourceMap = { + [EDS_TYPE_URL]: { + resourceTypeVersion: 0, + resourceNameMap: new Map() + }, + [CDS_TYPE_URL]: { + resourceTypeVersion: 0, + resourceNameMap: new Map() + }, + [RDS_TYPE_URL]: { + resourceTypeVersion: 0, + resourceNameMap: new Map() + }, + [LDS_TYPE_URL]: { + resourceTypeVersion: 0, + resourceNameMap: new Map() + }, + }; + private responseListeners = new Set(); + private resourceTypesToIgnore = new Set(); + private clients = new Map>(); + private server: Server | null = null; + private port: number | null = null; + + addResponseListener(listener: ResponseListener) { + this.responseListeners.add(listener); + } + + removeResponseListener(listener: ResponseListener) { + this.responseListeners.delete(listener); + } + + setResource(resource: ResourceAny, name: string) { + const resourceTypeState = this.resourceMap[resource["@type"]] as ResourceTypeState; + resourceTypeState.resourceTypeVersion += 1; + let resourceState: ResourceState | undefined = resourceTypeState.resourceNameMap.get(name); + if (!resourceState) { + resourceState = { + resourceTypeVersion: 0, + subscriptions: new Set() + }; + resourceTypeState.resourceNameMap.set(name, resourceState); + } + resourceState.resourceTypeVersion = resourceTypeState.resourceTypeVersion; + resourceState.resource = resource; + this.sendResourceUpdates(resource['@type'], resourceState.subscriptions, new Set([name])); + } + + setLdsResource(resource: Listener) { + this.setResource({...resource, '@type': LDS_TYPE_URL}, resource.name!); + } + + setRdsResource(resource: RouteConfiguration) { + this.setResource({...resource, '@type': RDS_TYPE_URL}, resource.name!); + } + + setCdsResource(resource: Cluster) { + this.setResource({...resource, '@type': CDS_TYPE_URL}, resource.name!); + } + + setEdsResource(resource: ClusterLoadAssignment) { + this.setResource({...resource, '@type': EDS_TYPE_URL}, resource.cluster_name!); + } + + unsetResource(typeUrl: T, name: string) { + const resourceTypeState = this.resourceMap[typeUrl] as ResourceTypeState; + resourceTypeState.resourceTypeVersion += 1; + let resourceState: ResourceState | undefined = resourceTypeState.resourceNameMap.get(name); + if (resourceState) { + resourceState.resourceTypeVersion = resourceTypeState.resourceTypeVersion; + delete resourceState.resource; + this.sendResourceUpdates(typeUrl, resourceState.subscriptions, new Set([name])); + } + } + + ignoreResourceType(typeUrl: AdsTypeUrl) { + this.resourceTypesToIgnore.add(typeUrl); + } + + private sendResourceUpdates(typeUrl: T, clients: Set, includeResources: Set) { + const resourceTypeState = this.resourceMap[typeUrl] as ResourceTypeState; + const clientResources = new Map(); + for (const [resourceName, resourceState] of resourceTypeState.resourceNameMap) { + /* For RDS and EDS, only send updates for the listed updated resources. + * Otherwise include all resources. */ + if ((typeUrl === RDS_TYPE_URL || typeUrl === EDS_TYPE_URL) && !includeResources.has(resourceName)) { + continue; + } + if (!resourceState.resource) { + continue; + } + for (const clientName of clients) { + if (!resourceState.subscriptions.has(clientName)) { + continue; + } + let resourcesList = clientResources.get(clientName); + if (!resourcesList) { + resourcesList = []; + clientResources.set(clientName, resourcesList); + } + resourcesList.push(resourceState.resource); + } + } + for (const [clientName, resourceList] of clientResources) { + this.clients.get(clientName)?.write({ + resources: resourceList, + version_info: resourceTypeState.resourceTypeVersion.toString(), + nonce: resourceTypeState.resourceTypeVersion.toString(), + type_url: typeUrl + }); + } + } + + private updateResponseListeners(typeUrl: AdsTypeUrl, responseState: ResponseState) { + for (const listener of this.responseListeners) { + listener(typeUrl, responseState); + } + } + + private maybeSubscribe(typeUrl: T, client: string, resourceName: string): boolean { + const resourceTypeState = this.resourceMap[typeUrl] as ResourceTypeState; + let resourceState = resourceTypeState.resourceNameMap.get(resourceName); + if (!resourceState) { + resourceState = { + resourceTypeVersion: 0, + subscriptions: new Set() + }; + resourceTypeState.resourceNameMap.set(resourceName, resourceState); + } + const newlySubscribed = !resourceState.subscriptions.has(client); + resourceState.subscriptions.add(client); + return newlySubscribed; + } + + private handleUnsubscriptions(typeUrl: AdsTypeUrl, client: string, requestedResourceNames?: Set) { + const resourceTypeState = this.resourceMap[typeUrl]; + for (const [resourceName, resourceState] of resourceTypeState.resourceNameMap) { + if (!requestedResourceNames || !requestedResourceNames.has(resourceName)) { + resourceState.subscriptions.delete(client); + if (!resourceState.resource && resourceState.subscriptions.size === 0) { + resourceTypeState.resourceNameMap.delete(resourceName) + } + } + } + } + + private handleRequest(clientName: string, request: DiscoveryRequest__Output) { + if (!isAdsTypeUrl(request.type_url)) { + console.error(`Received ADS request with unsupported type_url ${request.type_url}`); + return; + } + const clientResourceVersion = request.version_info === '' ? 0 : Number.parseInt(request.version_info); + if (request.error_detail) { + this.updateResponseListeners(request.type_url, {state: 'NACKED', errorMessage: request.error_detail.message}); + } else { + this.updateResponseListeners(request.type_url, {state: 'ACKED'}); + } + const requestedResourceNames = new Set(request.resource_names); + const resourceTypeState = this.resourceMap[request.type_url]; + const updatedResources = new Set(); + for (const resourceName of requestedResourceNames) { + if (this.maybeSubscribe(request.type_url, clientName, resourceName) || resourceTypeState.resourceNameMap.get(resourceName)!.resourceTypeVersion > clientResourceVersion) { + updatedResources.add(resourceName); + } + } + this.handleUnsubscriptions(request.type_url, clientName, requestedResourceNames); + if (updatedResources.size > 0) { + this.sendResourceUpdates(request.type_url, new Set([clientName]), updatedResources); + } + } + + StreamAggregatedResources(call: ServerDuplexStream) { + const clientName = call.getPeer(); + this.clients.set(clientName, call); + call.on('data', (request: DiscoveryRequest__Output) => { + this.handleRequest(clientName, request); + }); + call.on('end', () => { + this.clients.delete(clientName); + for (const typeUrl of ADS_TYPE_URLS) { + this.handleUnsubscriptions(typeUrl as AdsTypeUrl, clientName); + } + call.end(); + }); + } + + StreamLoadStats(call: ServerDuplexStream) { + const statsResponse = {load_reporting_interval: {seconds: 30}}; + call.write(statsResponse); + call.on('data', (request: LoadStatsRequest__Output) => { + call.write(statsResponse); + }); + call.on('end', () => { + call.end(); + }); + } + + startServer(callback: (error: Error | null, port: number) => void) { + if (this.server) { + return; + } + const server = new Server(); + server.addService(loadedProtos.envoy.service.discovery.v3.AggregatedDiscoveryService.service, this as unknown as UntypedServiceImplementation); + server.addService(loadedProtos.envoy.service.load_stats.v3.LoadReportingService.service, this as unknown as UntypedServiceImplementation); + server.bindAsync('localhost:0', ServerCredentials.createInsecure(), (error, port) => { + if (!error) { + this.server = server; + this.port = port; + server.start(); + } + callback(error, port); + }); + } + + shutdownServer() { + this.server?.forceShutdown(); + } + + getBootstrapInfoString(): string { + if (this.port === null) { + throw new Error('Bootstrap info unavailable; server not started'); + } + const bootstrapInfo = { + xds_servers: [{ + server_uri: `localhost:${this.port}`, + channel_creds: [{type: 'insecure'}] + }], + node: { + id: 'test', + locality: {} + } + } + return JSON.stringify(bootstrapInfo); + } +} \ No newline at end of file diff --git a/packages/grpc-js/README.md b/packages/grpc-js/README.md index 4bb4da024..652ce5fef 100644 --- a/packages/grpc-js/README.md +++ b/packages/grpc-js/README.md @@ -25,6 +25,8 @@ Documentation specifically for the `@grpc/grpc-js` package is currently not avai - Connection Keepalives - HTTP Connect support (proxies) +If you need a feature from the `grpc` package that is not provided by the `@grpc/grpc-js`, please file a feature request with that information. + This library does not directly handle `.proto` files. To use `.proto` files with this library we recommend using the `@grpc/proto-loader` package. ## Migrating from [`grpc`](https://www.npmjs.com/package/grpc) @@ -34,6 +36,36 @@ This library does not directly handle `.proto` files. To use `.proto` files with - If you are currently loading `.proto` files using `grpc.load`, that function is not available in this library. You should instead load your `.proto` files using `@grpc/proto-loader` and load the resulting package definition objects into `@grpc/grpc-js` using `grpc.loadPackageDefinition`. - If you are currently loading packages generated by `grpc-tools`, you should instead generate your files using the `generate_package_definition` option in `grpc-tools`, then load the object exported by the generated file into `@grpc/grpc-js` using `grpc.loadPackageDefinition`. - If you have a server and you are using `Server#bind` to bind ports, you will need to use `Server#bindAsync` instead. +- If you are using any channel options supported in `grpc` but not supported in `@grpc/grpc-js`, you may need to adjust your code to handle the different behavior. Refer to [the list of supported options](#supported-channel-options) below. +- Refer to the [detailed package comparison](https://github.com/grpc/grpc-node/blob/master/PACKAGE-COMPARISON.md) for more details on the differences between `grpc` and `@grpc/grpc-js`. + +## Supported Channel Options +Many channel arguments supported in `grpc` are not supported in `@grpc/grpc-js`. The channel arguments supported by `@grpc/grpc-js` are: + - `grpc.ssl_target_name_override` + - `grpc.primary_user_agent` + - `grpc.secondary_user_agent` + - `grpc.default_authority` + - `grpc.keepalive_time_ms` + - `grpc.keepalive_timeout_ms` + - `grpc.keepalive_permit_without_calls` + - `grpc.service_config` + - `grpc.max_concurrent_streams` + - `grpc.initial_reconnect_backoff_ms` + - `grpc.max_reconnect_backoff_ms` + - `grpc.use_local_subchannel_pool` + - `grpc.max_send_message_length` + - `grpc.max_receive_message_length` + - `grpc.enable_http_proxy` + - `grpc.default_compression_algorithm` + - `grpc.enable_channelz` + - `grpc.dns_min_time_between_resolutions_ms` + - `grpc.enable_retries` + - `grpc.per_rpc_retry_buffer_size` + - `grpc.retry_buffer_size` + - `grpc.service_config_disable_resolution` + - `grpc-node.max_session_memory` + - `channelOverride` + - `channelFactoryOverride` ## Some Notes on API Guarantees diff --git a/packages/grpc-js/gulpfile.ts b/packages/grpc-js/gulpfile.ts index 6d8d20943..d85900364 100644 --- a/packages/grpc-js/gulpfile.ts +++ b/packages/grpc-js/gulpfile.ts @@ -67,6 +67,7 @@ const compile = checkTask(() => execNpmCommand('compile')); const copyTestFixtures = checkTask(() => ncpP(`${jsCoreDir}/test/fixtures`, `${outDir}/test/fixtures`)); const runTests = checkTask(() => { + process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION = 'true'; return gulp.src(`${outDir}/test/**/*.js`) .pipe(mocha({reporter: 'mocha-jenkins-reporter', require: ['ts-node/register']})); diff --git a/packages/grpc-js/package.json b/packages/grpc-js/package.json index f0e20ff10..d4b822600 100644 --- a/packages/grpc-js/package.json +++ b/packages/grpc-js/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/grpc-js", - "version": "1.3.7", + "version": "1.8.17", "description": "gRPC Library for Node - pure JS implementation", "homepage": "https://grpc.io/", "repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js", @@ -15,27 +15,27 @@ "types": "build/src/index.d.ts", "license": "Apache-2.0", "devDependencies": { - "@grpc/proto-loader": "^0.5.5", "@types/gulp": "^4.0.6", "@types/gulp-mocha": "0.0.32", - "@types/lodash": "^4.14.108", + "@types/lodash": "^4.14.186", "@types/mocha": "^5.2.6", "@types/ncp": "^2.0.1", "@types/pify": "^3.0.2", - "@types/yargs": "^15.0.5", + "@types/semver": "^7.3.9", "clang-format": "^1.0.55", "execa": "^2.0.3", - "gts": "^2.0.0", + "gts": "^3.1.1", "gulp": "^4.0.2", "gulp-mocha": "^6.0.0", "lodash": "^4.17.4", + "madge": "^5.0.1", "mocha-jenkins-reporter": "^0.4.1", "ncp": "^2.0.0", "pify": "^4.0.1", "rimraf": "^3.0.2", + "semver": "^7.3.5", "ts-node": "^8.3.0", - "typescript": "^3.7.2", - "yargs": "^15.4.1" + "typescript": "^4.8.4" }, "contributors": [ { @@ -44,23 +44,27 @@ ], "scripts": { "build": "npm run compile", - "clean": "node -e 'require(\"rimraf\")(\"./build\", () => {})'", + "clean": "rimraf ./build", "compile": "tsc -p .", "format": "clang-format -i -style=\"{Language: JavaScript, BasedOnStyle: Google, ColumnLimit: 80}\" src/*.ts test/*.ts", "lint": "npm run check", - "prepare": "npm run compile", + "prepare": "npm run generate-types && npm run compile", "test": "gulp test", "check": "gts check src/**/*.ts", "fix": "gts fix src/*.ts", - "pretest": "npm run compile", - "posttest": "npm run check" + "pretest": "npm run generate-types && npm run generate-test-types && npm run compile", + "posttest": "npm run check && madge -c ./build/src", + "generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --includeDirs proto/ --include-dirs test/fixtures/ -O src/generated/ --grpcLib ../index channelz.proto", + "generate-test-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --include-dirs test/fixtures/ -O test/generated/ --grpcLib ../../src/index test_service.proto" }, "dependencies": { + "@grpc/proto-loader": "^0.7.0", "@types/node": ">=12.12.47" }, "files": [ "src/**/*.ts", - "build/src/*.{js,d.ts,js.map}", + "build/src/**/*.{js,d.ts,js.map}", + "proto/*.proto", "LICENSE", "deps/envoy-api/envoy/api/v2/**/*.proto", "deps/envoy-api/envoy/config/**/*.proto", diff --git a/packages/grpc-js/proto/channelz.proto b/packages/grpc-js/proto/channelz.proto new file mode 100644 index 000000000..446e9794b --- /dev/null +++ b/packages/grpc-js/proto/channelz.proto @@ -0,0 +1,564 @@ +// Copyright 2018 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file defines an interface for exporting monitoring information +// out of gRPC servers. See the full design at +// https://github.com/grpc/proposal/blob/master/A14-channelz.md +// +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/channelz/v1/channelz.proto + +syntax = "proto3"; + +package grpc.channelz.v1; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option go_package = "google.golang.org/grpc/channelz/grpc_channelz_v1"; +option java_multiple_files = true; +option java_package = "io.grpc.channelz.v1"; +option java_outer_classname = "ChannelzProto"; + +// Channel is a logical grouping of channels, subchannels, and sockets. +message Channel { + // The identifier for this channel. This should bet set. + ChannelRef ref = 1; + // Data specific to this channel. + ChannelData data = 2; + // At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + + // There are no ordering guarantees on the order of channel refs. + // There may not be cycles in the ref graph. + // A channel ref may be present in more than one channel or subchannel. + repeated ChannelRef channel_ref = 3; + + // At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + // There are no ordering guarantees on the order of subchannel refs. + // There may not be cycles in the ref graph. + // A sub channel ref may be present in more than one channel or subchannel. + repeated SubchannelRef subchannel_ref = 4; + + // There are no ordering guarantees on the order of sockets. + repeated SocketRef socket_ref = 5; +} + +// Subchannel is a logical grouping of channels, subchannels, and sockets. +// A subchannel is load balanced over by it's ancestor +message Subchannel { + // The identifier for this channel. + SubchannelRef ref = 1; + // Data specific to this channel. + ChannelData data = 2; + // At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + + // There are no ordering guarantees on the order of channel refs. + // There may not be cycles in the ref graph. + // A channel ref may be present in more than one channel or subchannel. + repeated ChannelRef channel_ref = 3; + + // At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + // There are no ordering guarantees on the order of subchannel refs. + // There may not be cycles in the ref graph. + // A sub channel ref may be present in more than one channel or subchannel. + repeated SubchannelRef subchannel_ref = 4; + + // There are no ordering guarantees on the order of sockets. + repeated SocketRef socket_ref = 5; +} + +// These come from the specified states in this document: +// https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md +message ChannelConnectivityState { + enum State { + UNKNOWN = 0; + IDLE = 1; + CONNECTING = 2; + READY = 3; + TRANSIENT_FAILURE = 4; + SHUTDOWN = 5; + } + State state = 1; +} + +// Channel data is data related to a specific Channel or Subchannel. +message ChannelData { + // The connectivity state of the channel or subchannel. Implementations + // should always set this. + ChannelConnectivityState state = 1; + + // The target this channel originally tried to connect to. May be absent + string target = 2; + + // A trace of recent events on the channel. May be absent. + ChannelTrace trace = 3; + + // The number of calls started on the channel + int64 calls_started = 4; + // The number of calls that have completed with an OK status + int64 calls_succeeded = 5; + // The number of calls that have completed with a non-OK status + int64 calls_failed = 6; + + // The last time a call was started on the channel. + google.protobuf.Timestamp last_call_started_timestamp = 7; +} + +// A trace event is an interesting thing that happened to a channel or +// subchannel, such as creation, address resolution, subchannel creation, etc. +message ChannelTraceEvent { + // High level description of the event. + string description = 1; + // The supported severity levels of trace events. + enum Severity { + CT_UNKNOWN = 0; + CT_INFO = 1; + CT_WARNING = 2; + CT_ERROR = 3; + } + // the severity of the trace event + Severity severity = 2; + // When this event occurred. + google.protobuf.Timestamp timestamp = 3; + // ref of referenced channel or subchannel. + // Optional, only present if this event refers to a child object. For example, + // this field would be filled if this trace event was for a subchannel being + // created. + oneof child_ref { + ChannelRef channel_ref = 4; + SubchannelRef subchannel_ref = 5; + } +} + +// ChannelTrace represents the recent events that have occurred on the channel. +message ChannelTrace { + // Number of events ever logged in this tracing object. This can differ from + // events.size() because events can be overwritten or garbage collected by + // implementations. + int64 num_events_logged = 1; + // Time that this channel was created. + google.protobuf.Timestamp creation_timestamp = 2; + // List of events that have occurred on this channel. + repeated ChannelTraceEvent events = 3; +} + +// ChannelRef is a reference to a Channel. +message ChannelRef { + // The globally unique id for this channel. Must be a positive number. + int64 channel_id = 1; + // An optional name associated with the channel. + string name = 2; + // Intentionally don't use field numbers from other refs. + reserved 3, 4, 5, 6, 7, 8; +} + +// SubchannelRef is a reference to a Subchannel. +message SubchannelRef { + // The globally unique id for this subchannel. Must be a positive number. + int64 subchannel_id = 7; + // An optional name associated with the subchannel. + string name = 8; + // Intentionally don't use field numbers from other refs. + reserved 1, 2, 3, 4, 5, 6; +} + +// SocketRef is a reference to a Socket. +message SocketRef { + // The globally unique id for this socket. Must be a positive number. + int64 socket_id = 3; + // An optional name associated with the socket. + string name = 4; + // Intentionally don't use field numbers from other refs. + reserved 1, 2, 5, 6, 7, 8; +} + +// ServerRef is a reference to a Server. +message ServerRef { + // A globally unique identifier for this server. Must be a positive number. + int64 server_id = 5; + // An optional name associated with the server. + string name = 6; + // Intentionally don't use field numbers from other refs. + reserved 1, 2, 3, 4, 7, 8; +} + +// Server represents a single server. There may be multiple servers in a single +// program. +message Server { + // The identifier for a Server. This should be set. + ServerRef ref = 1; + // The associated data of the Server. + ServerData data = 2; + + // The sockets that the server is listening on. There are no ordering + // guarantees. This may be absent. + repeated SocketRef listen_socket = 3; +} + +// ServerData is data for a specific Server. +message ServerData { + // A trace of recent events on the server. May be absent. + ChannelTrace trace = 1; + + // The number of incoming calls started on the server + int64 calls_started = 2; + // The number of incoming calls that have completed with an OK status + int64 calls_succeeded = 3; + // The number of incoming calls that have a completed with a non-OK status + int64 calls_failed = 4; + + // The last time a call was started on the server. + google.protobuf.Timestamp last_call_started_timestamp = 5; +} + +// Information about an actual connection. Pronounced "sock-ay". +message Socket { + // The identifier for the Socket. + SocketRef ref = 1; + + // Data specific to this Socket. + SocketData data = 2; + // The locally bound address. + Address local = 3; + // The remote bound address. May be absent. + Address remote = 4; + // Security details for this socket. May be absent if not available, or + // there is no security on the socket. + Security security = 5; + + // Optional, represents the name of the remote endpoint, if different than + // the original target name. + string remote_name = 6; +} + +// SocketData is data associated for a specific Socket. The fields present +// are specific to the implementation, so there may be minor differences in +// the semantics. (e.g. flow control windows) +message SocketData { + // The number of streams that have been started. + int64 streams_started = 1; + // The number of streams that have ended successfully: + // On client side, received frame with eos bit set; + // On server side, sent frame with eos bit set. + int64 streams_succeeded = 2; + // The number of streams that have ended unsuccessfully: + // On client side, ended without receiving frame with eos bit set; + // On server side, ended without sending frame with eos bit set. + int64 streams_failed = 3; + // The number of grpc messages successfully sent on this socket. + int64 messages_sent = 4; + // The number of grpc messages received on this socket. + int64 messages_received = 5; + + // The number of keep alives sent. This is typically implemented with HTTP/2 + // ping messages. + int64 keep_alives_sent = 6; + + // The last time a stream was created by this endpoint. Usually unset for + // servers. + google.protobuf.Timestamp last_local_stream_created_timestamp = 7; + // The last time a stream was created by the remote endpoint. Usually unset + // for clients. + google.protobuf.Timestamp last_remote_stream_created_timestamp = 8; + + // The last time a message was sent by this endpoint. + google.protobuf.Timestamp last_message_sent_timestamp = 9; + // The last time a message was received by this endpoint. + google.protobuf.Timestamp last_message_received_timestamp = 10; + + // The amount of window, granted to the local endpoint by the remote endpoint. + // This may be slightly out of date due to network latency. This does NOT + // include stream level or TCP level flow control info. + google.protobuf.Int64Value local_flow_control_window = 11; + + // The amount of window, granted to the remote endpoint by the local endpoint. + // This may be slightly out of date due to network latency. This does NOT + // include stream level or TCP level flow control info. + google.protobuf.Int64Value remote_flow_control_window = 12; + + // Socket options set on this socket. May be absent if 'summary' is set + // on GetSocketRequest. + repeated SocketOption option = 13; +} + +// Address represents the address used to create the socket. +message Address { + message TcpIpAddress { + // Either the IPv4 or IPv6 address in bytes. Will be either 4 bytes or 16 + // bytes in length. + bytes ip_address = 1; + // 0-64k, or -1 if not appropriate. + int32 port = 2; + } + // A Unix Domain Socket address. + message UdsAddress { + string filename = 1; + } + // An address type not included above. + message OtherAddress { + // The human readable version of the value. This value should be set. + string name = 1; + // The actual address message. + google.protobuf.Any value = 2; + } + + oneof address { + TcpIpAddress tcpip_address = 1; + UdsAddress uds_address = 2; + OtherAddress other_address = 3; + } +} + +// Security represents details about how secure the socket is. +message Security { + message Tls { + oneof cipher_suite { + // The cipher suite name in the RFC 4346 format: + // https://tools.ietf.org/html/rfc4346#appendix-C + string standard_name = 1; + // Some other way to describe the cipher suite if + // the RFC 4346 name is not available. + string other_name = 2; + } + // the certificate used by this endpoint. + bytes local_certificate = 3; + // the certificate used by the remote endpoint. + bytes remote_certificate = 4; + } + message OtherSecurity { + // The human readable version of the value. + string name = 1; + // The actual security details message. + google.protobuf.Any value = 2; + } + oneof model { + Tls tls = 1; + OtherSecurity other = 2; + } +} + +// SocketOption represents socket options for a socket. Specifically, these +// are the options returned by getsockopt(). +message SocketOption { + // The full name of the socket option. Typically this will be the upper case + // name, such as "SO_REUSEPORT". + string name = 1; + // The human readable value of this socket option. At least one of value or + // additional will be set. + string value = 2; + // Additional data associated with the socket option. At least one of value + // or additional will be set. + google.protobuf.Any additional = 3; +} + +// For use with SocketOption's additional field. This is primarily used for +// SO_RCVTIMEO and SO_SNDTIMEO +message SocketOptionTimeout { + google.protobuf.Duration duration = 1; +} + +// For use with SocketOption's additional field. This is primarily used for +// SO_LINGER. +message SocketOptionLinger { + // active maps to `struct linger.l_onoff` + bool active = 1; + // duration maps to `struct linger.l_linger` + google.protobuf.Duration duration = 2; +} + +// For use with SocketOption's additional field. Tcp info for +// SOL_TCP and TCP_INFO. +message SocketOptionTcpInfo { + uint32 tcpi_state = 1; + + uint32 tcpi_ca_state = 2; + uint32 tcpi_retransmits = 3; + uint32 tcpi_probes = 4; + uint32 tcpi_backoff = 5; + uint32 tcpi_options = 6; + uint32 tcpi_snd_wscale = 7; + uint32 tcpi_rcv_wscale = 8; + + uint32 tcpi_rto = 9; + uint32 tcpi_ato = 10; + uint32 tcpi_snd_mss = 11; + uint32 tcpi_rcv_mss = 12; + + uint32 tcpi_unacked = 13; + uint32 tcpi_sacked = 14; + uint32 tcpi_lost = 15; + uint32 tcpi_retrans = 16; + uint32 tcpi_fackets = 17; + + uint32 tcpi_last_data_sent = 18; + uint32 tcpi_last_ack_sent = 19; + uint32 tcpi_last_data_recv = 20; + uint32 tcpi_last_ack_recv = 21; + + uint32 tcpi_pmtu = 22; + uint32 tcpi_rcv_ssthresh = 23; + uint32 tcpi_rtt = 24; + uint32 tcpi_rttvar = 25; + uint32 tcpi_snd_ssthresh = 26; + uint32 tcpi_snd_cwnd = 27; + uint32 tcpi_advmss = 28; + uint32 tcpi_reordering = 29; +} + +// Channelz is a service exposed by gRPC servers that provides detailed debug +// information. +service Channelz { + // Gets all root channels (i.e. channels the application has directly + // created). This does not include subchannels nor non-top level channels. + rpc GetTopChannels(GetTopChannelsRequest) returns (GetTopChannelsResponse); + // Gets all servers that exist in the process. + rpc GetServers(GetServersRequest) returns (GetServersResponse); + // Returns a single Server, or else a NOT_FOUND code. + rpc GetServer(GetServerRequest) returns (GetServerResponse); + // Gets all server sockets that exist in the process. + rpc GetServerSockets(GetServerSocketsRequest) returns (GetServerSocketsResponse); + // Returns a single Channel, or else a NOT_FOUND code. + rpc GetChannel(GetChannelRequest) returns (GetChannelResponse); + // Returns a single Subchannel, or else a NOT_FOUND code. + rpc GetSubchannel(GetSubchannelRequest) returns (GetSubchannelResponse); + // Returns a single Socket or else a NOT_FOUND code. + rpc GetSocket(GetSocketRequest) returns (GetSocketResponse); +} + +message GetTopChannelsRequest { + // start_channel_id indicates that only channels at or above this id should be + // included in the results. + // To request the first page, this should be set to 0. To request + // subsequent pages, the client generates this value by adding 1 to + // the highest seen result ID. + int64 start_channel_id = 1; + + // If non-zero, the server will return a page of results containing + // at most this many items. If zero, the server will choose a + // reasonable page size. Must never be negative. + int64 max_results = 2; +} + +message GetTopChannelsResponse { + // list of channels that the connection detail service knows about. Sorted in + // ascending channel_id order. + // Must contain at least 1 result, otherwise 'end' must be true. + repeated Channel channel = 1; + // If set, indicates that the list of channels is the final list. Requesting + // more channels can only return more if they are created after this RPC + // completes. + bool end = 2; +} + +message GetServersRequest { + // start_server_id indicates that only servers at or above this id should be + // included in the results. + // To request the first page, this must be set to 0. To request + // subsequent pages, the client generates this value by adding 1 to + // the highest seen result ID. + int64 start_server_id = 1; + + // If non-zero, the server will return a page of results containing + // at most this many items. If zero, the server will choose a + // reasonable page size. Must never be negative. + int64 max_results = 2; +} + +message GetServersResponse { + // list of servers that the connection detail service knows about. Sorted in + // ascending server_id order. + // Must contain at least 1 result, otherwise 'end' must be true. + repeated Server server = 1; + // If set, indicates that the list of servers is the final list. Requesting + // more servers will only return more if they are created after this RPC + // completes. + bool end = 2; +} + +message GetServerRequest { + // server_id is the identifier of the specific server to get. + int64 server_id = 1; +} + +message GetServerResponse { + // The Server that corresponds to the requested server_id. This field + // should be set. + Server server = 1; +} + +message GetServerSocketsRequest { + int64 server_id = 1; + // start_socket_id indicates that only sockets at or above this id should be + // included in the results. + // To request the first page, this must be set to 0. To request + // subsequent pages, the client generates this value by adding 1 to + // the highest seen result ID. + int64 start_socket_id = 2; + + // If non-zero, the server will return a page of results containing + // at most this many items. If zero, the server will choose a + // reasonable page size. Must never be negative. + int64 max_results = 3; +} + +message GetServerSocketsResponse { + // list of socket refs that the connection detail service knows about. Sorted in + // ascending socket_id order. + // Must contain at least 1 result, otherwise 'end' must be true. + repeated SocketRef socket_ref = 1; + // If set, indicates that the list of sockets is the final list. Requesting + // more sockets will only return more if they are created after this RPC + // completes. + bool end = 2; +} + +message GetChannelRequest { + // channel_id is the identifier of the specific channel to get. + int64 channel_id = 1; +} + +message GetChannelResponse { + // The Channel that corresponds to the requested channel_id. This field + // should be set. + Channel channel = 1; +} + +message GetSubchannelRequest { + // subchannel_id is the identifier of the specific subchannel to get. + int64 subchannel_id = 1; +} + +message GetSubchannelResponse { + // The Subchannel that corresponds to the requested subchannel_id. This + // field should be set. + Subchannel subchannel = 1; +} + +message GetSocketRequest { + // socket_id is the identifier of the specific socket to get. + int64 socket_id = 1; + + // If true, the response will contain only high level information + // that is inexpensive to obtain. Fields thay may be omitted are + // documented. + bool summary = 2; +} + +message GetSocketResponse { + // The Socket that corresponds to the requested socket_id. This field + // should be set. + Socket socket = 1; +} \ No newline at end of file diff --git a/packages/grpc-js/src/admin.ts b/packages/grpc-js/src/admin.ts new file mode 100644 index 000000000..7745d07d8 --- /dev/null +++ b/packages/grpc-js/src/admin.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { ServiceDefinition } from "./make-client"; +import { Server, UntypedServiceImplementation } from "./server"; + +interface GetServiceDefinition { + (): ServiceDefinition; +} + +interface GetHandlers { + (): UntypedServiceImplementation; +} + +const registeredAdminServices: {getServiceDefinition: GetServiceDefinition, getHandlers: GetHandlers}[] = []; + +export function registerAdminService(getServiceDefinition: GetServiceDefinition, getHandlers: GetHandlers) { + registeredAdminServices.push({getServiceDefinition, getHandlers}); +} + +export function addAdminServicesToServer(server: Server): void { + for (const {getServiceDefinition, getHandlers} of registeredAdminServices) { + server.addService(getServiceDefinition(), getHandlers()); + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/backoff-timeout.ts b/packages/grpc-js/src/backoff-timeout.ts index 7f2ab5ebf..f523e259a 100644 --- a/packages/grpc-js/src/backoff-timeout.ts +++ b/packages/grpc-js/src/backoff-timeout.ts @@ -37,14 +37,47 @@ export interface BackoffOptions { } export class BackoffTimeout { - private initialDelay: number = INITIAL_BACKOFF_MS; - private multiplier: number = BACKOFF_MULTIPLIER; - private maxDelay: number = MAX_BACKOFF_MS; - private jitter: number = BACKOFF_JITTER; + /** + * The delay time at the start, and after each reset. + */ + private readonly initialDelay: number = INITIAL_BACKOFF_MS; + /** + * The exponential backoff multiplier. + */ + private readonly multiplier: number = BACKOFF_MULTIPLIER; + /** + * The maximum delay time + */ + private readonly maxDelay: number = MAX_BACKOFF_MS; + /** + * The maximum fraction by which the delay time can randomly vary after + * applying the multiplier. + */ + private readonly jitter: number = BACKOFF_JITTER; + /** + * The delay time for the next time the timer runs. + */ private nextDelay: number; + /** + * The handle of the underlying timer. If running is false, this value refers + * to an object representing a timer that has ended, but it can still be + * interacted with without error. + */ private timerId: NodeJS.Timer; + /** + * Indicates whether the timer is currently running. + */ private running = false; + /** + * Indicates whether the timer should keep the Node process running if no + * other async operation is doing so. + */ private hasRef = true; + /** + * The time that the currently running timer was started. Only valid if + * running is true. + */ + private startTime: Date = new Date(); constructor(private callback: () => void, options?: BackoffOptions) { if (options) { @@ -66,18 +99,24 @@ export class BackoffTimeout { clearTimeout(this.timerId); } - /** - * Call the callback after the current amount of delay time - */ - runOnce() { - this.running = true; + private runTimer(delay: number) { + clearTimeout(this.timerId); this.timerId = setTimeout(() => { this.callback(); this.running = false; - }, this.nextDelay); + }, delay); if (!this.hasRef) { this.timerId.unref?.(); } + } + + /** + * Call the callback after the current amount of delay time + */ + runOnce() { + this.running = true; + this.startTime = new Date(); + this.runTimer(this.nextDelay); const nextBackoff = Math.min( this.nextDelay * this.multiplier, this.maxDelay @@ -97,21 +136,44 @@ export class BackoffTimeout { } /** - * Reset the delay time to its initial value. + * Reset the delay time to its initial value. If the timer is still running, + * retroactively apply that reset to the current timer. */ reset() { this.nextDelay = this.initialDelay; + if (this.running) { + const now = new Date(); + const newEndTime = this.startTime; + newEndTime.setMilliseconds(newEndTime.getMilliseconds() + this.nextDelay); + clearTimeout(this.timerId); + if (now < newEndTime) { + this.runTimer(newEndTime.getTime() - now.getTime()); + } else { + this.running = false; + } + } } + /** + * Check whether the timer is currently running. + */ isRunning() { return this.running; } + /** + * Set that while the timer is running, it should keep the Node process + * running. + */ ref() { this.hasRef = true; this.timerId.ref?.(); } + /** + * Set that while the timer is running, it should not keep the Node process + * running. + */ unref() { this.hasRef = false; this.timerId.unref?.(); diff --git a/packages/grpc-js/src/call-credentials-filter.ts b/packages/grpc-js/src/call-credentials-filter.ts deleted file mode 100644 index 53bdba2f1..000000000 --- a/packages/grpc-js/src/call-credentials-filter.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import { Call } from './call-stream'; -import { Channel } from './channel'; -import { BaseFilter, Filter, FilterFactory } from './filter'; -import { Metadata } from './metadata'; -import { Status } from './constants'; -import { splitHostPort } from './uri-parser'; -import { ServiceError } from './call'; - -export class CallCredentialsFilter extends BaseFilter implements Filter { - private serviceUrl: string; - constructor( - private readonly channel: Channel, - private readonly stream: Call - ) { - super(); - this.channel = channel; - this.stream = stream; - const splitPath: string[] = stream.getMethod().split('/'); - let serviceName = ''; - /* The standard path format is "/{serviceName}/{methodName}", so if we split - * by '/', the first item should be empty and the second should be the - * service name */ - if (splitPath.length >= 2) { - serviceName = splitPath[1]; - } - const hostname = splitHostPort(stream.getHost())?.host ?? 'localhost'; - /* Currently, call credentials are only allowed on HTTPS connections, so we - * can assume that the scheme is "https" */ - this.serviceUrl = `https://${hostname}/${serviceName}`; - } - - async sendMetadata(metadata: Promise): Promise { - const credentials = this.stream.getCredentials(); - const credsMetadata = credentials.generateMetadata({ - service_url: this.serviceUrl, - }); - const resultMetadata = await metadata; - try { - resultMetadata.merge(await credsMetadata); - } catch (error) { - this.stream.cancelWithStatus( - Status.UNAUTHENTICATED, - `Failed to retrieve auth metadata with error: ${error.message}` - ); - return Promise.reject('Failed to retrieve auth metadata'); - } - if (resultMetadata.get('authorization').length > 1) { - this.stream.cancelWithStatus( - Status.INTERNAL, - '"authorization" metadata cannot have multiple values' - ); - return Promise.reject('"authorization" metadata cannot have multiple values'); - } - return resultMetadata; - } -} - -export class CallCredentialsFilterFactory - implements FilterFactory { - constructor(private readonly channel: Channel) { - this.channel = channel; - } - - createFilter(callStream: Call): CallCredentialsFilter { - return new CallCredentialsFilter(this.channel, callStream); - } -} diff --git a/packages/grpc-js/src/call-credentials.ts b/packages/grpc-js/src/call-credentials.ts index bbc88a895..b98624ee2 100644 --- a/packages/grpc-js/src/call-credentials.ts +++ b/packages/grpc-js/src/call-credentials.ts @@ -115,6 +115,10 @@ export abstract class CallCredentials { reject(err); return; } + if (!headers) { + reject(new Error('Headers not set by metadata plugin')); + return; + } resolve(headers); } ); diff --git a/packages/grpc-js/src/call-interface.ts b/packages/grpc-js/src/call-interface.ts new file mode 100644 index 000000000..283cb9b54 --- /dev/null +++ b/packages/grpc-js/src/call-interface.ts @@ -0,0 +1,173 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { CallCredentials } from "./call-credentials"; +import { Status } from "./constants"; +import { Deadline } from "./deadline"; +import { Metadata } from "./metadata"; +import { ServerSurfaceCall } from "./server-call"; + +export interface CallStreamOptions { + deadline: Deadline; + flags: number; + host: string; + parentCall: ServerSurfaceCall | null; +} + +export type PartialCallStreamOptions = Partial; + +export interface StatusObject { + code: Status; + details: string; + metadata: Metadata; +} + +export type PartialStatusObject = Pick & { + metadata: Metadata | null; +} + +export const enum WriteFlags { + BufferHint = 1, + NoCompress = 2, + WriteThrough = 4, +} + +export interface WriteObject { + message: Buffer; + flags?: number; +} + +export interface MetadataListener { + (metadata: Metadata, next: (metadata: Metadata) => void): void; +} + +export interface MessageListener { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (message: any, next: (message: any) => void): void; +} + +export interface StatusListener { + (status: StatusObject, next: (status: StatusObject) => void): void; +} + +export interface FullListener { + onReceiveMetadata: MetadataListener; + onReceiveMessage: MessageListener; + onReceiveStatus: StatusListener; +} + +export type Listener = Partial; + +/** + * An object with methods for handling the responses to a call. + */ +export interface InterceptingListener { + onReceiveMetadata(metadata: Metadata): void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + onReceiveMessage(message: any): void; + onReceiveStatus(status: StatusObject): void; +} + +export function isInterceptingListener( + listener: Listener | InterceptingListener +): listener is InterceptingListener { + return ( + listener.onReceiveMetadata !== undefined && + listener.onReceiveMetadata.length === 1 + ); +} + +export class InterceptingListenerImpl implements InterceptingListener { + private processingMetadata = false; + private hasPendingMessage = false; + private pendingMessage: any; + private processingMessage = false; + private pendingStatus: StatusObject | null = null; + constructor( + private listener: FullListener, + private nextListener: InterceptingListener + ) {} + + private processPendingMessage() { + if (this.hasPendingMessage) { + this.nextListener.onReceiveMessage(this.pendingMessage); + this.pendingMessage = null; + this.hasPendingMessage = false; + } + } + + private processPendingStatus() { + if (this.pendingStatus) { + this.nextListener.onReceiveStatus(this.pendingStatus); + } + } + + onReceiveMetadata(metadata: Metadata): void { + this.processingMetadata = true; + this.listener.onReceiveMetadata(metadata, (metadata) => { + this.processingMetadata = false; + this.nextListener.onReceiveMetadata(metadata); + this.processPendingMessage(); + this.processPendingStatus(); + }); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + onReceiveMessage(message: any): void { + /* If this listener processes messages asynchronously, the last message may + * be reordered with respect to the status */ + this.processingMessage = true; + this.listener.onReceiveMessage(message, (msg) => { + this.processingMessage = false; + if (this.processingMetadata) { + this.pendingMessage = msg; + this.hasPendingMessage = true; + } else { + this.nextListener.onReceiveMessage(msg); + this.processPendingStatus(); + } + }); + } + onReceiveStatus(status: StatusObject): void { + this.listener.onReceiveStatus(status, (processedStatus) => { + if (this.processingMetadata || this.processingMessage) { + this.pendingStatus = processedStatus; + } else { + this.nextListener.onReceiveStatus(processedStatus); + } + }); + } +} + +export interface WriteCallback { + (error?: Error | null): void; +} + +export interface MessageContext { + callback?: WriteCallback; + flags?: number; +} + +export interface Call { + cancelWithStatus(status: Status, details: string): void; + getPeer(): string; + start(metadata: Metadata, listener: InterceptingListener): void; + sendMessageWithContext(context: MessageContext, message: Buffer): void; + startRead(): void; + halfClose(): void; + getCallNumber(): number; + setCredentials(credentials: CallCredentials): void; +} \ No newline at end of file diff --git a/packages/grpc-js/src/call-number.ts b/packages/grpc-js/src/call-number.ts new file mode 100644 index 000000000..48d34fac5 --- /dev/null +++ b/packages/grpc-js/src/call-number.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +let nextCallNumber = 0; + +export function getNextCallNumber() { + return nextCallNumber++; +} \ No newline at end of file diff --git a/packages/grpc-js/src/call-stream.ts b/packages/grpc-js/src/call-stream.ts deleted file mode 100644 index 8d72bb3ee..000000000 --- a/packages/grpc-js/src/call-stream.ts +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import * as http2 from 'http2'; -import * as os from 'os'; - -import { CallCredentials } from './call-credentials'; -import { Propagate, Status } from './constants'; -import { Filter, FilterFactory } from './filter'; -import { FilterStackFactory, FilterStack } from './filter-stack'; -import { Metadata } from './metadata'; -import { StreamDecoder } from './stream-decoder'; -import { ChannelImplementation } from './channel'; -import { Subchannel } from './subchannel'; -import * as logging from './logging'; -import { LogVerbosity } from './constants'; -import { ServerSurfaceCall } from './server-call'; - -const TRACER_NAME = 'call_stream'; - -const { - HTTP2_HEADER_STATUS, - HTTP2_HEADER_CONTENT_TYPE, - NGHTTP2_CANCEL, -} = http2.constants; - -/** - * https://nodejs.org/api/errors.html#errors_class_systemerror - */ -interface SystemError extends Error { - address?: string; - code: string; - dest?: string; - errno: number; - info?: object; - message: string; - path?: string; - port?: number; - syscall: string; -} - -/** - * Should do approximately the same thing as util.getSystemErrorName but the - * TypeScript types don't have that function for some reason so I just made my - * own. - * @param errno - */ -function getSystemErrorName(errno: number): string { - for (const [name, num] of Object.entries(os.constants.errno)) { - if (num === errno) { - return name; - } - } - return 'Unknown system error ' + errno; -} - -export type Deadline = Date | number; - -export interface CallStreamOptions { - deadline: Deadline; - flags: number; - host: string; - parentCall: ServerSurfaceCall | null; -} - -export type PartialCallStreamOptions = Partial; - -export interface StatusObject { - code: Status; - details: string; - metadata: Metadata; -} - -export const enum WriteFlags { - BufferHint = 1, - NoCompress = 2, - WriteThrough = 4, -} - -export interface WriteObject { - message: Buffer; - flags?: number; -} - -export interface MetadataListener { - (metadata: Metadata, next: (metadata: Metadata) => void): void; -} - -export interface MessageListener { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (message: any, next: (message: any) => void): void; -} - -export interface StatusListener { - (status: StatusObject, next: (status: StatusObject) => void): void; -} - -export interface FullListener { - onReceiveMetadata: MetadataListener; - onReceiveMessage: MessageListener; - onReceiveStatus: StatusListener; -} - -export type Listener = Partial; - -/** - * An object with methods for handling the responses to a call. - */ -export interface InterceptingListener { - onReceiveMetadata(metadata: Metadata): void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onReceiveMessage(message: any): void; - onReceiveStatus(status: StatusObject): void; -} - -export function isInterceptingListener( - listener: Listener | InterceptingListener -): listener is InterceptingListener { - return ( - listener.onReceiveMetadata !== undefined && - listener.onReceiveMetadata.length === 1 - ); -} - -export class InterceptingListenerImpl implements InterceptingListener { - private processingMessage = false; - private pendingStatus: StatusObject | null = null; - constructor( - private listener: FullListener, - private nextListener: InterceptingListener - ) {} - - onReceiveMetadata(metadata: Metadata): void { - this.listener.onReceiveMetadata(metadata, (metadata) => { - this.nextListener.onReceiveMetadata(metadata); - }); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onReceiveMessage(message: any): void { - /* If this listener processes messages asynchronously, the last message may - * be reordered with respect to the status */ - this.processingMessage = true; - this.listener.onReceiveMessage(message, (msg) => { - this.processingMessage = false; - this.nextListener.onReceiveMessage(msg); - if (this.pendingStatus) { - this.nextListener.onReceiveStatus(this.pendingStatus); - } - }); - } - onReceiveStatus(status: StatusObject): void { - this.listener.onReceiveStatus(status, (processedStatus) => { - if (this.processingMessage) { - this.pendingStatus = processedStatus; - } else { - this.nextListener.onReceiveStatus(processedStatus); - } - }); - } -} - -export interface WriteCallback { - (error?: Error | null): void; -} - -export interface MessageContext { - callback?: WriteCallback; - flags?: number; -} - -export interface Call { - cancelWithStatus(status: Status, details: string): void; - getPeer(): string; - start(metadata: Metadata, listener: InterceptingListener): void; - sendMessageWithContext(context: MessageContext, message: Buffer): void; - startRead(): void; - halfClose(): void; - - getDeadline(): Deadline; - getCredentials(): CallCredentials; - setCredentials(credentials: CallCredentials): void; - getMethod(): string; - getHost(): string; -} - -export class Http2CallStream implements Call { - credentials: CallCredentials; - filterStack: Filter; - private http2Stream: http2.ClientHttp2Stream | null = null; - private pendingRead = false; - private isWriteFilterPending = false; - private pendingWrite: Buffer | null = null; - private pendingWriteCallback: WriteCallback | null = null; - private writesClosed = false; - - private decoder = new StreamDecoder(); - - private isReadFilterPending = false; - private canPush = false; - /** - * Indicates that an 'end' event has come from the http2 stream, so there - * will be no more data events. - */ - private readsClosed = false; - - private statusOutput = false; - - private unpushedReadMessages: Buffer[] = []; - private unfilteredReadMessages: Buffer[] = []; - - // Status code mapped from :status. To be used if grpc-status is not received - private mappedStatusCode: Status = Status.UNKNOWN; - - // This is populated (non-null) if and only if the call has ended - private finalStatus: StatusObject | null = null; - - private subchannel: Subchannel | null = null; - private disconnectListener: () => void; - - private listener: InterceptingListener | null = null; - - private internalError: SystemError | null = null; - - constructor( - private readonly methodName: string, - private readonly channel: ChannelImplementation, - private readonly options: CallStreamOptions, - filterStackFactory: FilterStackFactory, - private readonly channelCallCredentials: CallCredentials, - private readonly callNumber: number - ) { - this.filterStack = filterStackFactory.createFilter(this); - this.credentials = channelCallCredentials; - this.disconnectListener = () => { - this.endCall({ - code: Status.UNAVAILABLE, - details: 'Connection dropped', - metadata: new Metadata(), - }); - }; - if (this.options.parentCall && this.options.flags & Propagate.CANCELLATION) { - this.options.parentCall.on('cancelled', () => { - this.cancelWithStatus(Status.CANCELLED, 'Cancelled by parent call'); - }); - } - } - - private outputStatus() { - /* Precondition: this.finalStatus !== null */ - if (!this.statusOutput) { - this.statusOutput = true; - const filteredStatus = this.filterStack.receiveTrailers( - this.finalStatus! - ); - /* We delay the actual action of bubbling up the status to insulate the - * cleanup code in this class from any errors that may be thrown in the - * upper layers as a result of bubbling up the status. In particular, - * if the status is not OK, the "error" event may be emitted - * synchronously at the top level, which will result in a thrown error if - * the user does not handle that event. */ - process.nextTick(() => { - this.listener?.onReceiveStatus(filteredStatus); - }); - if (this.subchannel) { - this.subchannel.callUnref(); - this.subchannel.removeDisconnectListener(this.disconnectListener); - } - } - } - - private trace(text: string): void { - logging.trace( - LogVerbosity.DEBUG, - TRACER_NAME, - '[' + this.callNumber + '] ' + text - ); - } - - /** - * On first call, emits a 'status' event with the given StatusObject. - * Subsequent calls are no-ops. - * @param status The status of the call. - */ - private endCall(status: StatusObject): void { - /* If the status is OK and a new status comes in (e.g. from a - * deserialization failure), that new status takes priority */ - if (this.finalStatus === null || this.finalStatus.code === Status.OK) { - this.trace( - 'ended with status: code=' + - status.code + - ' details="' + - status.details + - '"' - ); - this.finalStatus = status; - this.maybeOutputStatus(); - } - this.destroyHttp2Stream(); - } - - private maybeOutputStatus() { - if (this.finalStatus !== null) { - /* The combination check of readsClosed and that the two message buffer - * arrays are empty checks that there all incoming data has been fully - * processed */ - if ( - this.finalStatus.code !== Status.OK || - (this.readsClosed && - this.unpushedReadMessages.length === 0 && - this.unfilteredReadMessages.length === 0 && - !this.isReadFilterPending) - ) { - this.outputStatus(); - } - } - } - - private push(message: Buffer): void { - this.trace( - 'pushing to reader message of length ' + - (message instanceof Buffer ? message.length : null) - ); - this.canPush = false; - process.nextTick(() => { - /* If we have already output the status any later messages should be - * ignored, and can cause out-of-order operation errors higher up in the - * stack. Checking as late as possible here to avoid any race conditions. - */ - if (this.statusOutput) { - return; - } - this.listener?.onReceiveMessage(message); - this.maybeOutputStatus(); - }); - } - - private handleFilterError(error: Error) { - this.cancelWithStatus(Status.INTERNAL, error.message); - } - - private handleFilteredRead(message: Buffer) { - /* If we the call has already ended with an error, we don't want to do - * anything with this message. Dropping it on the floor is correct - * behavior */ - if (this.finalStatus !== null && this.finalStatus.code !== Status.OK) { - this.maybeOutputStatus(); - return; - } - this.isReadFilterPending = false; - if (this.canPush) { - this.http2Stream!.pause(); - this.push(message); - } else { - this.trace( - 'unpushedReadMessages.push message of length ' + message.length - ); - this.unpushedReadMessages.push(message); - } - if (this.unfilteredReadMessages.length > 0) { - /* nextMessage is guaranteed not to be undefined because - unfilteredReadMessages is non-empty */ - const nextMessage = this.unfilteredReadMessages.shift()!; - this.filterReceivedMessage(nextMessage); - } - } - - private filterReceivedMessage(framedMessage: Buffer) { - /* If we the call has already ended with an error, we don't want to do - * anything with this message. Dropping it on the floor is correct - * behavior */ - if (this.finalStatus !== null && this.finalStatus.code !== Status.OK) { - this.maybeOutputStatus(); - return; - } - this.trace('filterReceivedMessage of length ' + framedMessage.length); - this.isReadFilterPending = true; - this.filterStack - .receiveMessage(Promise.resolve(framedMessage)) - .then( - this.handleFilteredRead.bind(this), - this.handleFilterError.bind(this) - ); - } - - private tryPush(messageBytes: Buffer): void { - if (this.isReadFilterPending) { - this.trace( - 'unfilteredReadMessages.push message of length ' + - (messageBytes && messageBytes.length) - ); - this.unfilteredReadMessages.push(messageBytes); - } else { - this.filterReceivedMessage(messageBytes); - } - } - - private handleTrailers(headers: http2.IncomingHttpHeaders) { - let headersString = ''; - for (const header of Object.keys(headers)) { - headersString += '\t\t' + header + ': ' + headers[header] + '\n'; - } - this.trace('Received server trailers:\n' + headersString); - let metadata: Metadata; - try { - metadata = Metadata.fromHttp2Headers(headers); - } catch (e) { - metadata = new Metadata(); - } - const metadataMap = metadata.getMap(); - let code: Status = this.mappedStatusCode; - if ( - code === Status.UNKNOWN && - typeof metadataMap['grpc-status'] === 'string' - ) { - const receivedStatus = Number(metadataMap['grpc-status']); - if (receivedStatus in Status) { - code = receivedStatus; - this.trace('received status code ' + receivedStatus + ' from server'); - } - metadata.remove('grpc-status'); - } - let details = ''; - if (typeof metadataMap['grpc-message'] === 'string') { - details = decodeURI(metadataMap['grpc-message']); - metadata.remove('grpc-message'); - this.trace( - 'received status details string "' + details + '" from server' - ); - } - const status: StatusObject = { code, details, metadata }; - // This is a no-op if the call was already ended when handling headers. - this.endCall(status); - } - - attachHttp2Stream( - stream: http2.ClientHttp2Stream, - subchannel: Subchannel, - extraFilterFactory?: FilterFactory - ): void { - if (extraFilterFactory !== undefined) { - this.filterStack = new FilterStack([ - this.filterStack, - extraFilterFactory.createFilter(this), - ]); - } - if (this.finalStatus !== null) { - stream.close(NGHTTP2_CANCEL); - } else { - this.trace( - 'attachHttp2Stream from subchannel ' + subchannel.getAddress() - ); - this.http2Stream = stream; - this.subchannel = subchannel; - subchannel.addDisconnectListener(this.disconnectListener); - subchannel.callRef(); - stream.on('response', (headers, flags) => { - let headersString = ''; - for (const header of Object.keys(headers)) { - headersString += '\t\t' + header + ': ' + headers[header] + '\n'; - } - this.trace('Received server headers:\n' + headersString); - switch (headers[':status']) { - // TODO(murgatroid99): handle 100 and 101 - case 400: - this.mappedStatusCode = Status.INTERNAL; - break; - case 401: - this.mappedStatusCode = Status.UNAUTHENTICATED; - break; - case 403: - this.mappedStatusCode = Status.PERMISSION_DENIED; - break; - case 404: - this.mappedStatusCode = Status.UNIMPLEMENTED; - break; - case 429: - case 502: - case 503: - case 504: - this.mappedStatusCode = Status.UNAVAILABLE; - break; - default: - this.mappedStatusCode = Status.UNKNOWN; - } - - if (flags & http2.constants.NGHTTP2_FLAG_END_STREAM) { - this.handleTrailers(headers); - } else { - let metadata: Metadata; - try { - metadata = Metadata.fromHttp2Headers(headers); - } catch (error) { - this.endCall({ - code: Status.UNKNOWN, - details: error.message, - metadata: new Metadata(), - }); - return; - } - try { - const finalMetadata = this.filterStack.receiveMetadata(metadata); - this.listener?.onReceiveMetadata(finalMetadata); - } catch (error) { - this.endCall({ - code: Status.UNKNOWN, - details: error.message, - metadata: new Metadata(), - }); - } - } - }); - stream.on('trailers', this.handleTrailers.bind(this)); - stream.on('data', (data: Buffer) => { - this.trace('receive HTTP/2 data frame of length ' + data.length); - const messages = this.decoder.write(data); - - for (const message of messages) { - this.trace('parsed message of length ' + message.length); - this.tryPush(message); - } - }); - stream.on('end', () => { - this.readsClosed = true; - this.maybeOutputStatus(); - }); - stream.on('close', () => { - /* Use process.next tick to ensure that this code happens after any - * "error" event that may be emitted at about the same time, so that - * we can bubble up the error message from that event. */ - process.nextTick(() => { - this.trace('HTTP/2 stream closed with code ' + stream.rstCode); - /* If we have a final status with an OK status code, that means that - * we have received all of the messages and we have processed the - * trailers and the call completed successfully, so it doesn't matter - * how the stream ends after that */ - if (this.finalStatus?.code === Status.OK) { - return; - } - let code: Status; - let details = ''; - switch (stream.rstCode) { - case http2.constants.NGHTTP2_NO_ERROR: - /* If we get a NO_ERROR code and we already have a status, the - * stream completed properly and we just haven't fully processed - * it yet */ - if (this.finalStatus !== null) { - return; - } - code = Status.INTERNAL; - details = `Received RST_STREAM with code ${stream.rstCode}`; - break; - case http2.constants.NGHTTP2_REFUSED_STREAM: - code = Status.UNAVAILABLE; - details = 'Stream refused by server'; - break; - case http2.constants.NGHTTP2_CANCEL: - code = Status.CANCELLED; - details = 'Call cancelled'; - break; - case http2.constants.NGHTTP2_ENHANCE_YOUR_CALM: - code = Status.RESOURCE_EXHAUSTED; - details = 'Bandwidth exhausted'; - break; - case http2.constants.NGHTTP2_INADEQUATE_SECURITY: - code = Status.PERMISSION_DENIED; - details = 'Protocol not secure enough'; - break; - case http2.constants.NGHTTP2_INTERNAL_ERROR: - code = Status.INTERNAL; - if (this.internalError === null) { - /* This error code was previously handled in the default case, and - * there are several instances of it online, so I wanted to - * preserve the original error message so that people find existing - * information in searches, but also include the more recognizable - * "Internal server error" message. */ - details = `Received RST_STREAM with code ${stream.rstCode} (Internal server error)`; - } else { - if (this.internalError.code === 'ECONNRESET') { - code = Status.UNAVAILABLE; - details = this.internalError.message; - } else { - /* The "Received RST_STREAM with code ..." error is preserved - * here for continuity with errors reported online, but the - * error message at the end will probably be more relevant in - * most cases. */ - details = `Received RST_STREAM with code ${stream.rstCode} triggered by internal client error: ${this.internalError.message}`; - } - } - break; - default: - code = Status.INTERNAL; - details = `Received RST_STREAM with code ${stream.rstCode}`; - } - // This is a no-op if trailers were received at all. - // This is OK, because status codes emitted here correspond to more - // catastrophic issues that prevent us from receiving trailers in the - // first place. - this.endCall({ code, details, metadata: new Metadata() }); - }); - }); - stream.on('error', (err: SystemError) => { - /* We need an error handler here to stop "Uncaught Error" exceptions - * from bubbling up. However, errors here should all correspond to - * "close" events, where we will handle the error more granularly */ - /* Specifically looking for stream errors that were *not* constructed - * from a RST_STREAM response here: - * https://github.com/nodejs/node/blob/8b8620d580314050175983402dfddf2674e8e22a/lib/internal/http2/core.js#L2267 - */ - if (err.code !== 'ERR_HTTP2_STREAM_ERROR') { - this.trace('Node error event: message=' + err.message + ' code=' + err.code + ' errno=' + getSystemErrorName(err.errno) + ' syscall=' + err.syscall); - this.internalError = err; - } - }); - if (!this.pendingRead) { - stream.pause(); - } - if (this.pendingWrite) { - if (!this.pendingWriteCallback) { - throw new Error('Invalid state in write handling code'); - } - this.trace( - 'sending data chunk of length ' + - this.pendingWrite.length + - ' (deferred)' - ); - try { - stream.write(this.pendingWrite, this.pendingWriteCallback); - } catch (error) { - this.endCall({ - code: Status.UNAVAILABLE, - details: `Write failed with error ${error.message}`, - metadata: new Metadata() - }); - } - } - this.maybeCloseWrites(); - } - } - - start(metadata: Metadata, listener: InterceptingListener) { - this.trace('Sending metadata'); - this.listener = listener; - this.channel._startCallStream(this, metadata); - } - - private destroyHttp2Stream() { - // The http2 stream could already have been destroyed if cancelWithStatus - // is called in response to an internal http2 error. - if (this.http2Stream !== null && !this.http2Stream.destroyed) { - /* If the call has ended with an OK status, communicate that when closing - * the stream, partly to avoid a situation in which we detect an error - * RST_STREAM as a result after we have the status */ - let code: number; - if (this.finalStatus?.code === Status.OK) { - code = http2.constants.NGHTTP2_NO_ERROR; - } else { - code = http2.constants.NGHTTP2_CANCEL; - } - this.trace('close http2 stream with code ' + code); - this.http2Stream.close(code); - } - } - - cancelWithStatus(status: Status, details: string): void { - this.trace( - 'cancelWithStatus code: ' + status + ' details: "' + details + '"' - ); - this.endCall({ code: status, details, metadata: new Metadata() }); - } - - getDeadline(): Deadline { - if (this.options.parentCall && this.options.flags & Propagate.DEADLINE) { - const parentDeadline = this.options.parentCall.getDeadline(); - const selfDeadline = this.options.deadline; - const parentDeadlineMsecs = parentDeadline instanceof Date ? parentDeadline.getTime() : parentDeadline; - const selfDeadlineMsecs = selfDeadline instanceof Date ? selfDeadline.getTime() : selfDeadline; - return Math.min(parentDeadlineMsecs, selfDeadlineMsecs); - } else { - return this.options.deadline; - } - } - - getCredentials(): CallCredentials { - return this.credentials; - } - - setCredentials(credentials: CallCredentials): void { - this.credentials = this.channelCallCredentials.compose(credentials); - } - - getStatus(): StatusObject | null { - return this.finalStatus; - } - - getPeer(): string { - return this.subchannel?.getAddress() ?? this.channel.getTarget(); - } - - getMethod(): string { - return this.methodName; - } - - getHost(): string { - return this.options.host; - } - - startRead() { - /* If the stream has ended with an error, we should not emit any more - * messages and we should communicate that the stream has ended */ - if (this.finalStatus !== null && this.finalStatus.code !== Status.OK) { - this.readsClosed = true; - this.maybeOutputStatus(); - return; - } - this.canPush = true; - if (this.http2Stream === null) { - this.pendingRead = true; - } else { - if (this.unpushedReadMessages.length > 0) { - const nextMessage: Buffer = this.unpushedReadMessages.shift()!; - this.push(nextMessage); - return; - } - /* Only resume reading from the http2Stream if we don't have any pending - * messages to emit */ - this.http2Stream.resume(); - } - } - - private maybeCloseWrites() { - if ( - this.writesClosed && - !this.isWriteFilterPending && - this.http2Stream !== null - ) { - this.trace('calling end() on HTTP/2 stream'); - this.http2Stream.end(); - } - } - - sendMessageWithContext(context: MessageContext, message: Buffer) { - this.trace('write() called with message of length ' + message.length); - const writeObj: WriteObject = { - message, - flags: context.flags, - }; - const cb: WriteCallback = context.callback ?? (() => {}); - this.isWriteFilterPending = true; - this.filterStack.sendMessage(Promise.resolve(writeObj)).then((message) => { - this.isWriteFilterPending = false; - if (this.http2Stream === null) { - this.trace( - 'deferring writing data chunk of length ' + message.message.length - ); - this.pendingWrite = message.message; - this.pendingWriteCallback = cb; - } else { - this.trace('sending data chunk of length ' + message.message.length); - try { - this.http2Stream.write(message.message, cb); - } catch (error) { - this.endCall({ - code: Status.UNAVAILABLE, - details: `Write failed with error ${error.message}`, - metadata: new Metadata() - }); - } - this.maybeCloseWrites(); - } - }, this.handleFilterError.bind(this)); - } - - halfClose() { - this.trace('end() called'); - this.writesClosed = true; - this.maybeCloseWrites(); - } -} diff --git a/packages/grpc-js/src/call.ts b/packages/grpc-js/src/call.ts index cfe37ecfb..bb6d74ccf 100644 --- a/packages/grpc-js/src/call.ts +++ b/packages/grpc-js/src/call.ts @@ -18,7 +18,7 @@ import { EventEmitter } from 'events'; import { Duplex, Readable, Writable } from 'stream'; -import { StatusObject, MessageContext } from './call-stream'; +import { StatusObject, MessageContext } from './call-interface'; import { Status } from './constants'; import { EmitterAugmentation1 } from './events'; import { Metadata } from './metadata'; @@ -76,12 +76,15 @@ export type ClientDuplexStream< * error is not necessarily a problem in gRPC itself. * @param status */ -export function callErrorFromStatus(status: StatusObject): ServiceError { +export function callErrorFromStatus(status: StatusObject, callerStack: string): ServiceError { const message = `${status.code} ${Status[status.code]}: ${status.details}`; - return Object.assign(new Error(message), status); + const error = new Error(message); + const stack = `${error.stack}\nfor call at\n${callerStack}`; + return Object.assign(new Error(message), status, {stack}); } -export class ClientUnaryCallImpl extends EventEmitter +export class ClientUnaryCallImpl + extends EventEmitter implements ClientUnaryCall { public call?: InterceptingCallInterface; constructor() { @@ -97,7 +100,8 @@ export class ClientUnaryCallImpl extends EventEmitter } } -export class ClientReadableStreamImpl extends Readable +export class ClientReadableStreamImpl + extends Readable implements ClientReadableStream { public call?: InterceptingCallInterface; constructor(readonly deserialize: (chunk: Buffer) => ResponseType) { @@ -117,7 +121,8 @@ export class ClientReadableStreamImpl extends Readable } } -export class ClientWritableStreamImpl extends Writable +export class ClientWritableStreamImpl + extends Writable implements ClientWritableStream { public call?: InterceptingCallInterface; constructor(readonly serialize: (value: RequestType) => Buffer) { @@ -149,7 +154,8 @@ export class ClientWritableStreamImpl extends Writable } } -export class ClientDuplexStreamImpl extends Duplex +export class ClientDuplexStreamImpl + extends Duplex implements ClientDuplexStream { public call?: InterceptingCallInterface; constructor( diff --git a/packages/grpc-js/src/channel-credentials.ts b/packages/grpc-js/src/channel-credentials.ts index 675e91628..fd9d7b571 100644 --- a/packages/grpc-js/src/channel-credentials.ts +++ b/packages/grpc-js/src/channel-credentials.ts @@ -15,7 +15,7 @@ * */ -import { ConnectionOptions, createSecureContext, PeerCertificate } from 'tls'; +import { ConnectionOptions, createSecureContext, PeerCertificate, SecureContext } from 'tls'; import { CallCredentials } from './call-credentials'; import { CIPHER_SUITES, getDefaultRootsData } from './tls-helpers'; @@ -27,16 +27,6 @@ function verifyIsBufferOrNull(obj: any, friendlyName: string): void { } } -/** - * A certificate as received by the checkServerIdentity callback. - */ -export interface Certificate { - /** - * The raw certificate in DER form. - */ - raw: Buffer; -} - /** * A callback that will receive the expected hostname and presented peer * certificate as parameters. The callback should return an error to @@ -45,7 +35,7 @@ export interface Certificate { */ export type CheckServerIdentityCallback = ( hostname: string, - cert: Certificate + cert: PeerCertificate ) => Error | undefined; function bufferOrNullEqual(buf1: Buffer | null, buf2: Buffer | null) { @@ -120,6 +110,7 @@ export abstract class ChannelCredentials { * @param rootCerts The root certificate data. * @param privateKey The client certificate private key, if available. * @param certChain The client certificate key chain, if available. + * @param verifyOptions Additional options to modify certificate verification */ static createSsl( rootCerts?: Buffer | null, @@ -140,14 +131,35 @@ export abstract class ChannelCredentials { 'Certificate chain must be given with accompanying private key' ); } + const secureContext = createSecureContext({ + ca: rootCerts ?? getDefaultRootsData() ?? undefined, + key: privateKey ?? undefined, + cert: certChain ?? undefined, + ciphers: CIPHER_SUITES, + }); return new SecureChannelCredentialsImpl( - rootCerts || getDefaultRootsData(), - privateKey || null, - certChain || null, - verifyOptions || {} + secureContext, + verifyOptions ?? {} ); } + /** + * Return a new ChannelCredentials instance with credentials created using + * the provided secureContext. The resulting instances can be used to + * construct a Channel that communicates over TLS. gRPC will not override + * anything in the provided secureContext, so the environment variables + * GRPC_SSL_CIPHER_SUITES and GRPC_DEFAULT_SSL_ROOTS_FILE_PATH will + * not be applied. + * @param secureContext The return value of tls.createSecureContext() + * @param verifyOptions Additional options to modify certificate verification + */ + static createFromSecureContext(secureContext: SecureContext, verifyOptions?: VerifyOptions): ChannelCredentials { + return new SecureChannelCredentialsImpl( + secureContext, + verifyOptions ?? {} + ) + } + /** * Return a new ChannelCredentials instance with no credentials. */ @@ -161,7 +173,7 @@ class InsecureChannelCredentialsImpl extends ChannelCredentials { super(callCredentials); } - compose(callCredentials: CallCredentials): ChannelCredentials { + compose(callCredentials: CallCredentials): never { throw new Error('Cannot compose insecure credentials'); } @@ -180,26 +192,16 @@ class SecureChannelCredentialsImpl extends ChannelCredentials { connectionOptions: ConnectionOptions; constructor( - private rootCerts: Buffer | null, - private privateKey: Buffer | null, - private certChain: Buffer | null, + private secureContext: SecureContext, private verifyOptions: VerifyOptions ) { super(); - const secureContext = createSecureContext({ - ca: rootCerts || undefined, - key: privateKey || undefined, - cert: certChain || undefined, - ciphers: CIPHER_SUITES, - }); - this.connectionOptions = { secureContext }; - if (verifyOptions && verifyOptions.checkServerIdentity) { - this.connectionOptions.checkServerIdentity = ( - host: string, - cert: PeerCertificate - ) => { - return verifyOptions.checkServerIdentity!(host, { raw: cert.raw }); - }; + this.connectionOptions = { + secureContext + }; + // Node asserts that this option is a function, so we cannot pass undefined + if (verifyOptions?.checkServerIdentity) { + this.connectionOptions.checkServerIdentity = verifyOptions.checkServerIdentity; } } @@ -222,19 +224,10 @@ class SecureChannelCredentialsImpl extends ChannelCredentials { return true; } if (other instanceof SecureChannelCredentialsImpl) { - if (!bufferOrNullEqual(this.rootCerts, other.rootCerts)) { - return false; - } - if (!bufferOrNullEqual(this.privateKey, other.privateKey)) { - return false; - } - if (!bufferOrNullEqual(this.certChain, other.certChain)) { - return false; - } return ( - this.verifyOptions.checkServerIdentity === - other.verifyOptions.checkServerIdentity - ); + this.secureContext === other.secureContext && + this.verifyOptions.checkServerIdentity === other.verifyOptions.checkServerIdentity + ); } else { return false; } diff --git a/packages/grpc-js/src/channel-options.ts b/packages/grpc-js/src/channel-options.ts index ebb724b0e..a41b89e9b 100644 --- a/packages/grpc-js/src/channel-options.ts +++ b/packages/grpc-js/src/channel-options.ts @@ -15,6 +15,8 @@ * */ +import { CompressionAlgorithms } from './compression-algorithms'; + /** * An interface that contains options used when initializing a Channel instance. */ @@ -34,9 +36,27 @@ export interface ChannelOptions { 'grpc.max_send_message_length'?: number; 'grpc.max_receive_message_length'?: number; 'grpc.enable_http_proxy'?: number; + /* http_connect_target and http_connect_creds are used for passing data + * around internally, and should not be documented as public-facing options + */ 'grpc.http_connect_target'?: string; 'grpc.http_connect_creds'?: string; + 'grpc.default_compression_algorithm'?: CompressionAlgorithms; + 'grpc.enable_channelz'?: number; + 'grpc.dns_min_time_between_resolutions_ms'?: number; + 'grpc.enable_retries'?: number; + 'grpc.per_rpc_retry_buffer_size'?: number; + /* This option is pattered like a core option, but the core does not have + * this option. It is closely related to the option + * grpc.per_rpc_retry_buffer_size, which is in the core. The core will likely + * implement this functionality using the ResourceQuota mechanism, so there + * will probably not be any collision or other inconsistency. */ + 'grpc.retry_buffer_size'?: number; + 'grpc.max_connection_age_ms'?: number; + 'grpc.max_connection_age_grace_ms'?: number; 'grpc-node.max_session_memory'?: number; + 'grpc.service_config_disable_resolution'?: number; + // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; } @@ -60,7 +80,15 @@ export const recognizedOptions = { 'grpc.max_send_message_length': true, 'grpc.max_receive_message_length': true, 'grpc.enable_http_proxy': true, + 'grpc.enable_channelz': true, + 'grpc.dns_min_time_between_resolutions_ms': true, + 'grpc.enable_retries': true, + 'grpc.per_rpc_retry_buffer_size': true, + 'grpc.retry_buffer_size': true, + 'grpc.max_connection_age_ms': true, + 'grpc.max_connection_age_grace_ms': true, 'grpc-node.max_session_memory': true, + 'grpc.service_config_disable_resolution': true, }; export function channelOptionsEqual( diff --git a/packages/grpc-js/src/channel.ts b/packages/grpc-js/src/channel.ts index 41715c41e..aaf14bb22 100644 --- a/packages/grpc-js/src/channel.ts +++ b/packages/grpc-js/src/channel.ts @@ -15,56 +15,15 @@ * */ -import { - Deadline, - Call, - Http2CallStream, - CallStreamOptions, -} from './call-stream'; import { ChannelCredentials } from './channel-credentials'; import { ChannelOptions } from './channel-options'; -import { ResolvingLoadBalancer } from './resolving-load-balancer'; -import { SubchannelPool, getSubchannelPool } from './subchannel-pool'; -import { ChannelControlHelper } from './load-balancer'; -import { UnavailablePicker, Picker, PickResultType } from './picker'; -import { Metadata } from './metadata'; -import { Status, LogVerbosity, Propagate } from './constants'; -import { FilterStackFactory } from './filter-stack'; -import { CallCredentialsFilterFactory } from './call-credentials-filter'; -import { DeadlineFilterFactory } from './deadline-filter'; -import { CompressionFilterFactory } from './compression-filter'; -import { CallConfig, ConfigSelector, getDefaultAuthority, mapUriDefaultScheme } from './resolver'; -import { trace, log } from './logging'; -import { SubchannelAddress } from './subchannel'; -import { MaxMessageSizeFilterFactory } from './max-message-size-filter'; -import { mapProxyName } from './http_proxy'; -import { GrpcUri, parseUri, uriToString } from './uri-parser'; import { ServerSurfaceCall } from './server-call'; -import { SurfaceCall } from './call'; -export enum ConnectivityState { - IDLE, - CONNECTING, - READY, - TRANSIENT_FAILURE, - SHUTDOWN, -} - -/** - * See https://nodejs.org/api/timers.html#timers_setinterval_callback_delay_args - */ -const MAX_TIMEOUT_TIME = 2147483647; - -let nextCallNumber = 0; - -function getNewCallNumber(): number { - const callNumber = nextCallNumber; - nextCallNumber += 1; - if (nextCallNumber >= Number.MAX_SAFE_INTEGER) { - nextCallNumber = 0; - } - return callNumber; -} +import { ConnectivityState } from './connectivity-state'; +import { ChannelRef } from './channelz'; +import { Call } from './call-interface'; +import { InternalChannel } from './internal-channel'; +import { Deadline } from './deadline'; /** * An interface that represents a communication channel to a server specified @@ -104,6 +63,12 @@ export interface Channel { deadline: Date | number, callback: (error?: Error) => void ): void; + /** + * Get the channelz reference object for this channel. A request to the + * channelz service for the id in this object will provide information + * about this channel. + */ + getChannelzRef(): ChannelRef; /** * Create a call object. Call is an opaque type that is used by the Client * class. This function is called by the gRPC library when starting a @@ -125,47 +90,14 @@ export interface Channel { ): Call; } -interface ConnectivityStateWatcher { - currentState: ConnectivityState; - timer: NodeJS.Timeout | null; - callback: (error?: Error) => void; -} - export class ChannelImplementation implements Channel { - private resolvingLoadBalancer: ResolvingLoadBalancer; - private subchannelPool: SubchannelPool; - private connectivityState: ConnectivityState = ConnectivityState.IDLE; - private currentPicker: Picker = new UnavailablePicker(); - /** - * Calls queued up to get a call config. Should only be populated before the - * first time the resolver returns a result, which includes the ConfigSelector. - */ - private configSelectionQueue: Array<{ - callStream: Http2CallStream; - callMetadata: Metadata; - }> = []; - private pickQueue: Array<{ - callStream: Http2CallStream; - callMetadata: Metadata; - callConfig: CallConfig; - }> = []; - private connectivityStateWatchers: ConnectivityStateWatcher[] = []; - private defaultAuthority: string; - private filterStackFactory: FilterStackFactory; - private target: GrpcUri; - /** - * This timer does not do anything on its own. Its purpose is to hold the - * event loop open while there are any pending calls for the channel that - * have not yet been assigned to specific subchannels. In other words, - * the invariant is that callRefTimer is reffed if and only if pickQueue - * is non-empty. - */ - private callRefTimer: NodeJS.Timer; - private configSelector: ConfigSelector | null = null; + + private internalChannel: InternalChannel; + constructor( target: string, - private readonly credentials: ChannelCredentials, - private readonly options: ChannelOptions + credentials: ChannelCredentials, + options: ChannelOptions ) { if (typeof target !== 'string') { throw new TypeError('Channel target must be a string'); @@ -176,382 +108,24 @@ export class ChannelImplementation implements Channel { ); } if (options) { - if ( - typeof options !== 'object' || - !Object.values(options).every( - (value) => - typeof value === 'string' || - typeof value === 'number' || - typeof value === 'undefined' - ) - ) { - throw new TypeError( - 'Channel options must be an object with string or number values' - ); - } - } - const originalTargetUri = parseUri(target); - if (originalTargetUri === null) { - throw new Error(`Could not parse target name "${target}"`); - } - /* This ensures that the target has a scheme that is registered with the - * resolver */ - const defaultSchemeMapResult = mapUriDefaultScheme(originalTargetUri); - if (defaultSchemeMapResult === null) { - throw new Error( - `Could not find a default scheme for target name "${target}"` - ); - } - - this.callRefTimer = setInterval(() => {}, MAX_TIMEOUT_TIME); - this.callRefTimer.unref?.(); - - if (this.options['grpc.default_authority']) { - this.defaultAuthority = this.options['grpc.default_authority'] as string; - } else { - this.defaultAuthority = getDefaultAuthority(defaultSchemeMapResult); - } - const proxyMapResult = mapProxyName(defaultSchemeMapResult, options); - this.target = proxyMapResult.target; - this.options = Object.assign({}, this.options, proxyMapResult.extraOptions); - - /* The global boolean parameter to getSubchannelPool has the inverse meaning to what - * the grpc.use_local_subchannel_pool channel option means. */ - this.subchannelPool = getSubchannelPool( - (options['grpc.use_local_subchannel_pool'] ?? 0) === 0 - ); - const channelControlHelper: ChannelControlHelper = { - createSubchannel: ( - subchannelAddress: SubchannelAddress, - subchannelArgs: ChannelOptions - ) => { - return this.subchannelPool.getOrCreateSubchannel( - this.target, - subchannelAddress, - Object.assign({}, this.options, subchannelArgs), - this.credentials - ); - }, - updateState: (connectivityState: ConnectivityState, picker: Picker) => { - this.currentPicker = picker; - const queueCopy = this.pickQueue.slice(); - this.pickQueue = []; - this.callRefTimerUnref(); - for (const { callStream, callMetadata, callConfig } of queueCopy) { - this.tryPick(callStream, callMetadata, callConfig); - } - this.updateState(connectivityState); - }, - requestReresolution: () => { - // This should never be called. - throw new Error( - 'Resolving load balancer should never call requestReresolution' - ); - }, - }; - this.resolvingLoadBalancer = new ResolvingLoadBalancer( - this.target, - channelControlHelper, - options, - (configSelector) => { - this.configSelector = configSelector; - /* We process the queue asynchronously to ensure that the corresponding - * load balancer update has completed. */ - process.nextTick(() => { - const localQueue = this.configSelectionQueue; - this.configSelectionQueue = []; - this.callRefTimerUnref() - for (const {callStream, callMetadata} of localQueue) { - this.tryGetConfig(callStream, callMetadata); - } - this.configSelectionQueue = []; - }); - }, - (status) => { - if (this.configSelectionQueue.length > 0) { - trace(LogVerbosity.DEBUG, 'channel', 'Name resolution failed for target ' + uriToString(this.target) + ' with calls queued for config selection'); - } - const localQueue = this.configSelectionQueue; - this.configSelectionQueue = []; - this.callRefTimerUnref(); - for (const {callStream, callMetadata} of localQueue) { - if (callMetadata.getOptions().waitForReady) { - this.callRefTimerRef(); - this.configSelectionQueue.push({callStream, callMetadata}); - } else { - callStream.cancelWithStatus(status.code, status.details); - } - } - } - ); - this.filterStackFactory = new FilterStackFactory([ - new CallCredentialsFilterFactory(this), - new DeadlineFilterFactory(this), - new MaxMessageSizeFilterFactory(this.options), - new CompressionFilterFactory(this), - ]); - } - - private callRefTimerRef() { - // If the hasRef function does not exist, always run the code - if (!this.callRefTimer.hasRef?.()) { - trace(LogVerbosity.DEBUG, 'channel', 'callRefTimer.ref | configSelectionQueue.length=' + this.configSelectionQueue.length + ' pickQueue.length=' + this.pickQueue.length); - this.callRefTimer.ref?.(); - } - } - - private callRefTimerUnref() { - // If the hasRef function does not exist, always run the code - if ((!this.callRefTimer.hasRef) || (this.callRefTimer.hasRef())) { - trace(LogVerbosity.DEBUG, 'channel', 'callRefTimer.unref | configSelectionQueue.length=' + this.configSelectionQueue.length + ' pickQueue.length=' + this.pickQueue.length); - this.callRefTimer.unref?.(); - } - } - - private pushPick(callStream: Http2CallStream, callMetadata: Metadata, callConfig: CallConfig) { - this.pickQueue.push({ callStream, callMetadata, callConfig }); - this.callRefTimerRef(); - } - - /** - * Check the picker output for the given call and corresponding metadata, - * and take any relevant actions. Should not be called while iterating - * over pickQueue. - * @param callStream - * @param callMetadata - */ - private tryPick(callStream: Http2CallStream, callMetadata: Metadata, callConfig: CallConfig) { - const pickResult = this.currentPicker.pick({ metadata: callMetadata, extraPickInfo: callConfig.pickInformation }); - trace( - LogVerbosity.DEBUG, - 'channel', - 'Pick result: ' + - PickResultType[pickResult.pickResultType] + - ' subchannel: ' + - pickResult.subchannel?.getAddress() + - ' status: ' + - pickResult.status?.code + - ' ' + - pickResult.status?.details - ); - switch (pickResult.pickResultType) { - case PickResultType.COMPLETE: - if (pickResult.subchannel === null) { - callStream.cancelWithStatus( - Status.UNAVAILABLE, - 'Request dropped by load balancing policy' - ); - // End the call with an error - } else { - /* If the subchannel is not in the READY state, that indicates a bug - * somewhere in the load balancer or picker. So, we log an error and - * queue the pick to be tried again later. */ - if ( - pickResult.subchannel!.getConnectivityState() !== - ConnectivityState.READY - ) { - log( - LogVerbosity.ERROR, - 'Error: COMPLETE pick result subchannel ' + - pickResult.subchannel!.getAddress() + - ' has state ' + - ConnectivityState[pickResult.subchannel!.getConnectivityState()] - ); - this.pushPick(callStream, callMetadata, callConfig); - break; - } - /* We need to clone the callMetadata here because the transparent - * retry code in the promise resolution handler use the same - * callMetadata object, so it needs to stay unmodified */ - callStream.filterStack - .sendMetadata(Promise.resolve(callMetadata.clone())) - .then( - (finalMetadata) => { - const subchannelState: ConnectivityState = pickResult.subchannel!.getConnectivityState(); - if (subchannelState === ConnectivityState.READY) { - try { - pickResult.subchannel!.startCallStream( - finalMetadata, - callStream, - pickResult.extraFilterFactory ?? undefined - ); - /* If we reach this point, the call stream has started - * successfully */ - callConfig.onCommitted?.(); - pickResult.onCallStarted?.(); - } catch (error) { - if ( - (error as NodeJS.ErrnoException).code === - 'ERR_HTTP2_GOAWAY_SESSION' - ) { - /* An error here indicates that something went wrong with - * the picked subchannel's http2 stream right before we - * tried to start the stream. We are handling a promise - * result here, so this is asynchronous with respect to the - * original tryPick call, so calling it again is not - * recursive. We call tryPick immediately instead of - * queueing this pick again because handling the queue is - * triggered by state changes, and we want to immediately - * check if the state has already changed since the - * previous tryPick call. We do this instead of cancelling - * the stream because the correct behavior may be - * re-queueing instead, based on the logic in the rest of - * tryPick */ - trace( - LogVerbosity.INFO, - 'channel', - 'Failed to start call on picked subchannel ' + - pickResult.subchannel!.getAddress() + - ' with error ' + - (error as Error).message + - '. Retrying pick' - ); - this.tryPick(callStream, callMetadata, callConfig); - } else { - trace( - LogVerbosity.INFO, - 'channel', - 'Failed to start call on picked subchanel ' + - pickResult.subchannel!.getAddress() + - ' with error ' + - (error as Error).message + - '. Ending call' - ); - callStream.cancelWithStatus( - Status.INTERNAL, - `Failed to start HTTP/2 stream with error: ${(error as Error).message}` - ); - } - } - } else { - /* The logic for doing this here is the same as in the catch - * block above */ - trace( - LogVerbosity.INFO, - 'channel', - 'Picked subchannel ' + - pickResult.subchannel!.getAddress() + - ' has state ' + - ConnectivityState[subchannelState] + - ' after metadata filters. Retrying pick' - ); - this.tryPick(callStream, callMetadata, callConfig); - } - }, - (error: Error & { code: number }) => { - // We assume the error code isn't 0 (Status.OK) - callStream.cancelWithStatus( - (typeof error.code === 'number') ? error.code : Status.UNKNOWN, - `Getting metadata from plugin failed with error: ${error.message}` - ); - } - ); - } - break; - case PickResultType.QUEUE: - this.pushPick(callStream, callMetadata, callConfig); - break; - case PickResultType.TRANSIENT_FAILURE: - if (callMetadata.getOptions().waitForReady) { - this.pushPick(callStream, callMetadata, callConfig); - } else { - callStream.cancelWithStatus( - pickResult.status!.code, - pickResult.status!.details - ); - } - break; - case PickResultType.DROP: - callStream.cancelWithStatus( - pickResult.status!.code, - pickResult.status!.details - ); - break; - default: - throw new Error( - `Invalid state: unknown pickResultType ${pickResult.pickResultType}` - ); - } - } - - private removeConnectivityStateWatcher( - watcherObject: ConnectivityStateWatcher - ) { - const watcherIndex = this.connectivityStateWatchers.findIndex( - (value) => value === watcherObject - ); - if (watcherIndex >= 0) { - this.connectivityStateWatchers.splice(watcherIndex, 1); - } - } - - private updateState(newState: ConnectivityState): void { - trace( - LogVerbosity.DEBUG, - 'connectivity_state', - uriToString(this.target) + - ' ' + - ConnectivityState[this.connectivityState] + - ' -> ' + - ConnectivityState[newState] - ); - this.connectivityState = newState; - const watchersCopy = this.connectivityStateWatchers.slice(); - for (const watcherObject of watchersCopy) { - if (newState !== watcherObject.currentState) { - if(watcherObject.timer) { - clearTimeout(watcherObject.timer); - } - this.removeConnectivityStateWatcher(watcherObject); - watcherObject.callback(); + if (typeof options !== 'object') { + throw new TypeError('Channel options must be an object'); } } - } - - private tryGetConfig(stream: Http2CallStream, metadata: Metadata) { - if (this.configSelector === null) { - /* This branch will only be taken at the beginning of the channel's life, - * before the resolver ever returns a result. So, the - * ResolvingLoadBalancer may be idle and if so it needs to be kicked - * because it now has a pending request. */ - this.resolvingLoadBalancer.exitIdle(); - this.configSelectionQueue.push({ - callStream: stream, - callMetadata: metadata - }); - this.callRefTimerRef(); - } else { - const callConfig = this.configSelector(stream.getMethod(), metadata); - if (callConfig.status === Status.OK) { - this.tryPick(stream, metadata, callConfig); - } else { - stream.cancelWithStatus(callConfig.status, "Failed to route call to method " + stream.getMethod()); - } - } - } - _startCallStream(stream: Http2CallStream, metadata: Metadata) { - this.tryGetConfig(stream, metadata.clone()); + this.internalChannel = new InternalChannel(target, credentials, options); } close() { - this.resolvingLoadBalancer.destroy(); - this.updateState(ConnectivityState.SHUTDOWN); - clearInterval(this.callRefTimer); - - this.subchannelPool.unrefUnusedSubchannels(); + this.internalChannel.close(); } getTarget() { - return uriToString(this.target); + return this.internalChannel.getTarget(); } getConnectivityState(tryToConnect: boolean) { - const connectivityState = this.connectivityState; - if (tryToConnect) { - this.resolvingLoadBalancer.exitIdle(); - } - return connectivityState; + return this.internalChannel.getConnectivityState(tryToConnect); } watchConnectivityState( @@ -559,34 +133,16 @@ export class ChannelImplementation implements Channel { deadline: Date | number, callback: (error?: Error) => void ): void { - if (this.connectivityState === ConnectivityState.SHUTDOWN) { - throw new Error('Channel has been shut down'); - } - let timer = null; - if(deadline !== Infinity) { - const deadlineDate: Date = - deadline instanceof Date ? deadline : new Date(deadline); - const now = new Date(); - if (deadline === -Infinity || deadlineDate <= now) { - process.nextTick( - callback, - new Error('Deadline passed without connectivity state change') - ); - return; - } - timer = setTimeout(() => { - this.removeConnectivityStateWatcher(watcherObject); - callback( - new Error('Deadline passed without connectivity state change') - ); - }, deadlineDate.getTime() - now.getTime()) - } - const watcherObject = { - currentState, - callback, - timer - }; - this.connectivityStateWatchers.push(watcherObject); + this.internalChannel.watchConnectivityState(currentState, deadline, callback); + } + + /** + * Get the channelz reference object for this channel. The returned value is + * garbage if channelz is disabled for this channel. + * @returns + */ + getChannelzRef() { + return this.internalChannel.getChannelzRef(); } createCall( @@ -604,35 +160,6 @@ export class ChannelImplementation implements Channel { 'Channel#createCall: deadline must be a number or Date' ); } - if (this.connectivityState === ConnectivityState.SHUTDOWN) { - throw new Error('Channel has been shut down'); - } - const callNumber = getNewCallNumber(); - trace( - LogVerbosity.DEBUG, - 'channel', - uriToString(this.target) + - ' createCall [' + - callNumber + - '] method="' + - method + - '", deadline=' + - deadline - ); - const finalOptions: CallStreamOptions = { - deadline: deadline, - flags: propagateFlags ?? Propagate.DEFAULTS, - host: host ?? this.defaultAuthority, - parentCall: parentCall, - }; - const stream: Http2CallStream = new Http2CallStream( - method, - this, - finalOptions, - this.filterStackFactory, - this.credentials._getCallCredentials(), - callNumber - ); - return stream; + return this.internalChannel.createCall(method, deadline, host, parentCall, propagateFlags); } } diff --git a/packages/grpc-js/src/channelz.ts b/packages/grpc-js/src/channelz.ts new file mode 100644 index 000000000..5a7a54760 --- /dev/null +++ b/packages/grpc-js/src/channelz.ts @@ -0,0 +1,758 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { isIPv4, isIPv6 } from "net"; +import { ConnectivityState } from "./connectivity-state"; +import { Status } from "./constants"; +import { Timestamp } from "./generated/google/protobuf/Timestamp"; +import { Channel as ChannelMessage } from "./generated/grpc/channelz/v1/Channel"; +import { ChannelConnectivityState__Output } from "./generated/grpc/channelz/v1/ChannelConnectivityState"; +import { ChannelRef as ChannelRefMessage } from "./generated/grpc/channelz/v1/ChannelRef"; +import { ChannelTrace } from "./generated/grpc/channelz/v1/ChannelTrace"; +import { GetChannelRequest__Output } from "./generated/grpc/channelz/v1/GetChannelRequest"; +import { GetChannelResponse } from "./generated/grpc/channelz/v1/GetChannelResponse"; +import { sendUnaryData, ServerUnaryCall } from "./server-call"; +import { ServerRef as ServerRefMessage } from "./generated/grpc/channelz/v1/ServerRef"; +import { SocketRef as SocketRefMessage } from "./generated/grpc/channelz/v1/SocketRef"; +import { isTcpSubchannelAddress, SubchannelAddress } from "./subchannel-address"; +import { SubchannelRef as SubchannelRefMessage } from "./generated/grpc/channelz/v1/SubchannelRef"; +import { GetServerRequest__Output } from "./generated/grpc/channelz/v1/GetServerRequest"; +import { GetServerResponse } from "./generated/grpc/channelz/v1/GetServerResponse"; +import { Server as ServerMessage } from "./generated/grpc/channelz/v1/Server"; +import { GetServersRequest__Output } from "./generated/grpc/channelz/v1/GetServersRequest"; +import { GetServersResponse } from "./generated/grpc/channelz/v1/GetServersResponse"; +import { GetTopChannelsRequest__Output } from "./generated/grpc/channelz/v1/GetTopChannelsRequest"; +import { GetTopChannelsResponse } from "./generated/grpc/channelz/v1/GetTopChannelsResponse"; +import { GetSubchannelRequest__Output } from "./generated/grpc/channelz/v1/GetSubchannelRequest"; +import { GetSubchannelResponse } from "./generated/grpc/channelz/v1/GetSubchannelResponse"; +import { Subchannel as SubchannelMessage } from "./generated/grpc/channelz/v1/Subchannel"; +import { GetSocketRequest__Output } from "./generated/grpc/channelz/v1/GetSocketRequest"; +import { GetSocketResponse } from "./generated/grpc/channelz/v1/GetSocketResponse"; +import { Socket as SocketMessage } from "./generated/grpc/channelz/v1/Socket"; +import { Address } from "./generated/grpc/channelz/v1/Address"; +import { Security } from "./generated/grpc/channelz/v1/Security"; +import { GetServerSocketsRequest__Output } from "./generated/grpc/channelz/v1/GetServerSocketsRequest"; +import { GetServerSocketsResponse } from "./generated/grpc/channelz/v1/GetServerSocketsResponse"; +import { ChannelzDefinition, ChannelzHandlers } from "./generated/grpc/channelz/v1/Channelz"; +import { ProtoGrpcType as ChannelzProtoGrpcType } from "./generated/channelz"; +import type { loadSync } from '@grpc/proto-loader'; +import { registerAdminService } from "./admin"; +import { loadPackageDefinition } from "./make-client"; + +export type TraceSeverity = 'CT_UNKNOWN' | 'CT_INFO' | 'CT_WARNING' | 'CT_ERROR'; + +export interface ChannelRef { + kind: 'channel'; + id: number; + name: string; +} + +export interface SubchannelRef { + kind: 'subchannel'; + id: number; + name: string; +} + +export interface ServerRef { + kind: 'server'; + id: number; +} + +export interface SocketRef { + kind: 'socket'; + id: number; + name: string; +} + +function channelRefToMessage(ref: ChannelRef): ChannelRefMessage { + return { + channel_id: ref.id, + name: ref.name + }; +} + +function subchannelRefToMessage(ref: SubchannelRef): SubchannelRefMessage { + return { + subchannel_id: ref.id, + name: ref.name + } +} + +function serverRefToMessage(ref: ServerRef): ServerRefMessage { + return { + server_id: ref.id + } +} + +function socketRefToMessage(ref: SocketRef): SocketRefMessage { + return { + socket_id: ref.id, + name: ref.name + } +} + +interface TraceEvent { + description: string; + severity: TraceSeverity; + timestamp: Date; + childChannel?: ChannelRef; + childSubchannel?: SubchannelRef; +} + +/** + * The loose upper bound on the number of events that should be retained in a + * trace. This may be exceeded by up to a factor of 2. Arbitrarily chosen as a + * number that should be large enough to contain the recent relevant + * information, but small enough to not use excessive memory. + */ +const TARGET_RETAINED_TRACES = 32; + +export class ChannelzTrace { + events: TraceEvent[] = []; + creationTimestamp: Date; + eventsLogged: number = 0; + + constructor() { + this.creationTimestamp = new Date(); + } + + addTrace(severity: TraceSeverity, description: string, child?: ChannelRef | SubchannelRef) { + const timestamp = new Date(); + this.events.push({ + description: description, + severity: severity, + timestamp: timestamp, + childChannel: child?.kind === 'channel' ? child : undefined, + childSubchannel: child?.kind === 'subchannel' ? child : undefined + }); + // Whenever the trace array gets too large, discard the first half + if (this.events.length >= TARGET_RETAINED_TRACES * 2) { + this.events = this.events.slice(TARGET_RETAINED_TRACES); + } + this.eventsLogged += 1; + } + + getTraceMessage(): ChannelTrace { + return { + creation_timestamp: dateToProtoTimestamp(this.creationTimestamp), + num_events_logged: this.eventsLogged, + events: this.events.map(event => { + return { + description: event.description, + severity: event.severity, + timestamp: dateToProtoTimestamp(event.timestamp), + channel_ref: event.childChannel ? channelRefToMessage(event.childChannel) : null, + subchannel_ref: event.childSubchannel ? subchannelRefToMessage(event.childSubchannel) : null + } + }) + }; + } +} + +export class ChannelzChildrenTracker { + private channelChildren: Map = new Map(); + private subchannelChildren: Map = new Map(); + private socketChildren: Map = new Map(); + + refChild(child: ChannelRef | SubchannelRef | SocketRef) { + switch (child.kind) { + case 'channel': { + let trackedChild = this.channelChildren.get(child.id) ?? {ref: child, count: 0}; + trackedChild.count += 1; + this.channelChildren.set(child.id, trackedChild); + break; + } + case 'subchannel':{ + let trackedChild = this.subchannelChildren.get(child.id) ?? {ref: child, count: 0}; + trackedChild.count += 1; + this.subchannelChildren.set(child.id, trackedChild); + break; + } + case 'socket':{ + let trackedChild = this.socketChildren.get(child.id) ?? {ref: child, count: 0}; + trackedChild.count += 1; + this.socketChildren.set(child.id, trackedChild); + break; + } + } + } + + unrefChild(child: ChannelRef | SubchannelRef | SocketRef) { + switch (child.kind) { + case 'channel': { + let trackedChild = this.channelChildren.get(child.id); + if (trackedChild !== undefined) { + trackedChild.count -= 1; + if (trackedChild.count === 0) { + this.channelChildren.delete(child.id); + } else { + this.channelChildren.set(child.id, trackedChild); + } + } + break; + } + case 'subchannel': { + let trackedChild = this.subchannelChildren.get(child.id); + if (trackedChild !== undefined) { + trackedChild.count -= 1; + if (trackedChild.count === 0) { + this.subchannelChildren.delete(child.id); + } else { + this.subchannelChildren.set(child.id, trackedChild); + } + } + break; + } + case 'socket': { + let trackedChild = this.socketChildren.get(child.id); + if (trackedChild !== undefined) { + trackedChild.count -= 1; + if (trackedChild.count === 0) { + this.socketChildren.delete(child.id); + } else { + this.socketChildren.set(child.id, trackedChild); + } + } + break; + } + } + } + + getChildLists(): ChannelzChildren { + const channels: ChannelRef[] = []; + for (const {ref} of this.channelChildren.values()) { + channels.push(ref); + } + const subchannels: SubchannelRef[] = []; + for (const {ref} of this.subchannelChildren.values()) { + subchannels.push(ref); + } + const sockets: SocketRef[] = []; + for (const {ref} of this.socketChildren.values()) { + sockets.push(ref); + } + return {channels, subchannels, sockets}; + } +} + +export class ChannelzCallTracker { + callsStarted: number = 0; + callsSucceeded: number = 0; + callsFailed: number = 0; + lastCallStartedTimestamp: Date | null = null; + + addCallStarted() { + this.callsStarted += 1; + this.lastCallStartedTimestamp = new Date(); + } + addCallSucceeded() { + this.callsSucceeded += 1; + } + addCallFailed() { + this.callsFailed += 1; + } +} + +export interface ChannelzChildren { + channels: ChannelRef[]; + subchannels: SubchannelRef[]; + sockets: SocketRef[]; +} + +export interface ChannelInfo { + target: string; + state: ConnectivityState; + trace: ChannelzTrace; + callTracker: ChannelzCallTracker; + children: ChannelzChildren; +} + +export interface SubchannelInfo extends ChannelInfo {} + +export interface ServerInfo { + trace: ChannelzTrace; + callTracker: ChannelzCallTracker; + listenerChildren: ChannelzChildren; + sessionChildren: ChannelzChildren; +} + +export interface TlsInfo { + cipherSuiteStandardName: string | null; + cipherSuiteOtherName: string | null; + localCertificate: Buffer | null; + remoteCertificate: Buffer | null; +} + +export interface SocketInfo { + localAddress: SubchannelAddress | null; + remoteAddress: SubchannelAddress | null; + security: TlsInfo | null; + remoteName: string | null; + streamsStarted: number; + streamsSucceeded: number; + streamsFailed: number; + messagesSent: number; + messagesReceived: number; + keepAlivesSent: number; + lastLocalStreamCreatedTimestamp: Date | null; + lastRemoteStreamCreatedTimestamp: Date | null; + lastMessageSentTimestamp: Date | null; + lastMessageReceivedTimestamp: Date | null; + localFlowControlWindow: number | null; + remoteFlowControlWindow: number | null; +} + +interface ChannelEntry { + ref: ChannelRef; + getInfo(): ChannelInfo; +} + +interface SubchannelEntry { + ref: SubchannelRef; + getInfo(): SubchannelInfo; +} + +interface ServerEntry { + ref: ServerRef; + getInfo(): ServerInfo; +} + +interface SocketEntry { + ref: SocketRef; + getInfo(): SocketInfo; +} + +let nextId = 1; + +function getNextId(): number { + return nextId++; +} + +const channels: (ChannelEntry | undefined)[] = []; +const subchannels: (SubchannelEntry | undefined)[] = []; +const servers: (ServerEntry | undefined)[] = []; +const sockets: (SocketEntry | undefined)[] = []; + +export function registerChannelzChannel(name: string, getInfo: () => ChannelInfo, channelzEnabled: boolean): ChannelRef { + const id = getNextId(); + const ref: ChannelRef = {id, name, kind: 'channel'}; + if (channelzEnabled) { + channels[id] = { ref, getInfo }; + } + return ref; +} + +export function registerChannelzSubchannel(name: string, getInfo:() => SubchannelInfo, channelzEnabled: boolean): SubchannelRef { + const id = getNextId(); + const ref: SubchannelRef = {id, name, kind: 'subchannel'}; + if (channelzEnabled) { + subchannels[id] = { ref, getInfo }; + } + return ref; +} + +export function registerChannelzServer(getInfo: () => ServerInfo, channelzEnabled: boolean): ServerRef { + const id = getNextId(); + const ref: ServerRef = {id, kind: 'server'}; + if (channelzEnabled) { + servers[id] = { ref, getInfo }; + } + return ref; +} + +export function registerChannelzSocket(name: string, getInfo: () => SocketInfo, channelzEnabled: boolean): SocketRef { + const id = getNextId(); + const ref: SocketRef = {id, name, kind: 'socket'}; + if (channelzEnabled) { + sockets[id] = { ref, getInfo}; + } + return ref; +} + +export function unregisterChannelzRef(ref: ChannelRef | SubchannelRef | ServerRef | SocketRef) { + switch (ref.kind) { + case 'channel': + delete channels[ref.id]; + return; + case 'subchannel': + delete subchannels[ref.id]; + return; + case 'server': + delete servers[ref.id]; + return; + case 'socket': + delete sockets[ref.id]; + return; + } +} + +/** + * Parse a single section of an IPv6 address as two bytes + * @param addressSection A hexadecimal string of length up to 4 + * @returns The pair of bytes representing this address section + */ +function parseIPv6Section(addressSection: string): [number, number] { + const numberValue = Number.parseInt(addressSection, 16); + return [numberValue / 256 | 0, numberValue % 256]; +} + +/** + * Parse a chunk of an IPv6 address string to some number of bytes + * @param addressChunk Some number of segments of up to 4 hexadecimal + * characters each, joined by colons. + * @returns The list of bytes representing this address chunk + */ +function parseIPv6Chunk(addressChunk: string): number[] { + if (addressChunk === '') { + return []; + } + const bytePairs = addressChunk.split(':').map(section => parseIPv6Section(section)); + const result: number[] = []; + return result.concat(...bytePairs); +} + +/** + * Converts an IPv4 or IPv6 address from string representation to binary + * representation + * @param ipAddress an IP address in standard IPv4 or IPv6 text format + * @returns + */ +function ipAddressStringToBuffer(ipAddress: string): Buffer | null { + if (isIPv4(ipAddress)) { + return Buffer.from(Uint8Array.from(ipAddress.split('.').map(segment => Number.parseInt(segment)))); + } else if (isIPv6(ipAddress)) { + let leftSection: string; + let rightSection: string; + const doubleColonIndex = ipAddress.indexOf('::'); + if (doubleColonIndex === -1) { + leftSection = ipAddress; + rightSection = ''; + } else { + leftSection = ipAddress.substring(0, doubleColonIndex); + rightSection = ipAddress.substring(doubleColonIndex + 2); + } + const leftBuffer = Buffer.from(parseIPv6Chunk(leftSection)); + const rightBuffer = Buffer.from(parseIPv6Chunk(rightSection)); + const middleBuffer = Buffer.alloc(16 - leftBuffer.length - rightBuffer.length, 0); + return Buffer.concat([leftBuffer, middleBuffer, rightBuffer]); + } else { + return null; + } +} + +function connectivityStateToMessage(state: ConnectivityState): ChannelConnectivityState__Output { + switch (state) { + case ConnectivityState.CONNECTING: + return { + state: 'CONNECTING' + }; + case ConnectivityState.IDLE: + return { + state: 'IDLE' + }; + case ConnectivityState.READY: + return { + state: 'READY' + }; + case ConnectivityState.SHUTDOWN: + return { + state: 'SHUTDOWN' + }; + case ConnectivityState.TRANSIENT_FAILURE: + return { + state: 'TRANSIENT_FAILURE' + }; + default: + return { + state: 'UNKNOWN' + }; + } +} + +function dateToProtoTimestamp(date?: Date | null): Timestamp | null { + if (!date) { + return null; + } + const millisSinceEpoch = date.getTime(); + return { + seconds: (millisSinceEpoch / 1000) | 0, + nanos: (millisSinceEpoch % 1000) * 1_000_000 + } +} + +function getChannelMessage(channelEntry: ChannelEntry): ChannelMessage { + const resolvedInfo = channelEntry.getInfo(); + return { + ref: channelRefToMessage(channelEntry.ref), + data: { + target: resolvedInfo.target, + state: connectivityStateToMessage(resolvedInfo.state), + calls_started: resolvedInfo.callTracker.callsStarted, + calls_succeeded: resolvedInfo.callTracker.callsSucceeded, + calls_failed: resolvedInfo.callTracker.callsFailed, + last_call_started_timestamp: dateToProtoTimestamp(resolvedInfo.callTracker.lastCallStartedTimestamp), + trace: resolvedInfo.trace.getTraceMessage() + }, + channel_ref: resolvedInfo.children.channels.map(ref => channelRefToMessage(ref)), + subchannel_ref: resolvedInfo.children.subchannels.map(ref => subchannelRefToMessage(ref)) + }; +} + +function GetChannel(call: ServerUnaryCall, callback: sendUnaryData): void { + const channelId = Number.parseInt(call.request.channel_id); + const channelEntry = channels[channelId]; + if (channelEntry === undefined) { + callback({ + 'code': Status.NOT_FOUND, + 'details': 'No channel data found for id ' + channelId + }); + return; + } + callback(null, {channel: getChannelMessage(channelEntry)}); +} + +function GetTopChannels(call: ServerUnaryCall, callback: sendUnaryData): void { + const maxResults = Number.parseInt(call.request.max_results); + const resultList: ChannelMessage[] = []; + let i = Number.parseInt(call.request.start_channel_id); + for (; i < channels.length; i++) { + const channelEntry = channels[i]; + if (channelEntry === undefined) { + continue; + } + resultList.push(getChannelMessage(channelEntry)); + if (resultList.length >= maxResults) { + break; + } + } + callback(null, { + channel: resultList, + end: i >= servers.length + }); +} + +function getServerMessage(serverEntry: ServerEntry): ServerMessage { + const resolvedInfo = serverEntry.getInfo(); + return { + ref: serverRefToMessage(serverEntry.ref), + data: { + calls_started: resolvedInfo.callTracker.callsStarted, + calls_succeeded: resolvedInfo.callTracker.callsSucceeded, + calls_failed: resolvedInfo.callTracker.callsFailed, + last_call_started_timestamp: dateToProtoTimestamp(resolvedInfo.callTracker.lastCallStartedTimestamp), + trace: resolvedInfo.trace.getTraceMessage() + }, + listen_socket: resolvedInfo.listenerChildren.sockets.map(ref => socketRefToMessage(ref)) + }; +} + +function GetServer(call: ServerUnaryCall, callback: sendUnaryData): void { + const serverId = Number.parseInt(call.request.server_id); + const serverEntry = servers[serverId]; + if (serverEntry === undefined) { + callback({ + 'code': Status.NOT_FOUND, + 'details': 'No server data found for id ' + serverId + }); + return; + } + callback(null, {server: getServerMessage(serverEntry)}); +} + +function GetServers(call: ServerUnaryCall, callback: sendUnaryData): void { + const maxResults = Number.parseInt(call.request.max_results); + const resultList: ServerMessage[] = []; + let i = Number.parseInt(call.request.start_server_id); + for (; i < servers.length; i++) { + const serverEntry = servers[i]; + if (serverEntry === undefined) { + continue; + } + resultList.push(getServerMessage(serverEntry)); + if (resultList.length >= maxResults) { + break; + } + } + callback(null, { + server: resultList, + end: i >= servers.length + }); +} + +function GetSubchannel(call: ServerUnaryCall, callback: sendUnaryData): void { + const subchannelId = Number.parseInt(call.request.subchannel_id); + const subchannelEntry = subchannels[subchannelId]; + if (subchannelEntry === undefined) { + callback({ + 'code': Status.NOT_FOUND, + 'details': 'No subchannel data found for id ' + subchannelId + }); + return; + } + const resolvedInfo = subchannelEntry.getInfo(); + const subchannelMessage: SubchannelMessage = { + ref: subchannelRefToMessage(subchannelEntry.ref), + data: { + target: resolvedInfo.target, + state: connectivityStateToMessage(resolvedInfo.state), + calls_started: resolvedInfo.callTracker.callsStarted, + calls_succeeded: resolvedInfo.callTracker.callsSucceeded, + calls_failed: resolvedInfo.callTracker.callsFailed, + last_call_started_timestamp: dateToProtoTimestamp(resolvedInfo.callTracker.lastCallStartedTimestamp), + trace: resolvedInfo.trace.getTraceMessage() + }, + socket_ref: resolvedInfo.children.sockets.map(ref => socketRefToMessage(ref)) + }; + callback(null, {subchannel: subchannelMessage}); +} + +function subchannelAddressToAddressMessage(subchannelAddress: SubchannelAddress): Address { + if (isTcpSubchannelAddress(subchannelAddress)) { + return { + address: 'tcpip_address', + tcpip_address: { + ip_address: ipAddressStringToBuffer(subchannelAddress.host) ?? undefined, + port: subchannelAddress.port + } + }; + } else { + return { + address: 'uds_address', + uds_address: { + filename: subchannelAddress.path + } + }; + } +} + +function GetSocket(call: ServerUnaryCall, callback: sendUnaryData): void { + const socketId = Number.parseInt(call.request.socket_id); + const socketEntry = sockets[socketId]; + if (socketEntry === undefined) { + callback({ + 'code': Status.NOT_FOUND, + 'details': 'No socket data found for id ' + socketId + }); + return; + } + const resolvedInfo = socketEntry.getInfo(); + const securityMessage: Security | null = resolvedInfo.security ? { + model: 'tls', + tls: { + cipher_suite: resolvedInfo.security.cipherSuiteStandardName ? 'standard_name' : 'other_name', + standard_name: resolvedInfo.security.cipherSuiteStandardName ?? undefined, + other_name: resolvedInfo.security.cipherSuiteOtherName ?? undefined, + local_certificate: resolvedInfo.security.localCertificate ?? undefined, + remote_certificate: resolvedInfo.security.remoteCertificate ?? undefined + } + } : null; + const socketMessage: SocketMessage = { + ref: socketRefToMessage(socketEntry.ref), + local: resolvedInfo.localAddress ? subchannelAddressToAddressMessage(resolvedInfo.localAddress) : null, + remote: resolvedInfo.remoteAddress ? subchannelAddressToAddressMessage(resolvedInfo.remoteAddress) : null, + remote_name: resolvedInfo.remoteName ?? undefined, + security: securityMessage, + data: { + keep_alives_sent: resolvedInfo.keepAlivesSent, + streams_started: resolvedInfo.streamsStarted, + streams_succeeded: resolvedInfo.streamsSucceeded, + streams_failed: resolvedInfo.streamsFailed, + last_local_stream_created_timestamp: dateToProtoTimestamp(resolvedInfo.lastLocalStreamCreatedTimestamp), + last_remote_stream_created_timestamp: dateToProtoTimestamp(resolvedInfo.lastRemoteStreamCreatedTimestamp), + messages_received: resolvedInfo.messagesReceived, + messages_sent: resolvedInfo.messagesSent, + last_message_received_timestamp: dateToProtoTimestamp(resolvedInfo.lastMessageReceivedTimestamp), + last_message_sent_timestamp: dateToProtoTimestamp(resolvedInfo.lastMessageSentTimestamp), + local_flow_control_window: resolvedInfo.localFlowControlWindow ? { value: resolvedInfo.localFlowControlWindow } : null, + remote_flow_control_window: resolvedInfo.remoteFlowControlWindow ? { value: resolvedInfo.remoteFlowControlWindow } : null, + } + }; + callback(null, {socket: socketMessage}); +} + +function GetServerSockets(call: ServerUnaryCall, callback: sendUnaryData): void { + const serverId = Number.parseInt(call.request.server_id); + const serverEntry = servers[serverId]; + if (serverEntry === undefined) { + callback({ + 'code': Status.NOT_FOUND, + 'details': 'No server data found for id ' + serverId + }); + return; + } + const startId = Number.parseInt(call.request.start_socket_id); + const maxResults = Number.parseInt(call.request.max_results); + const resolvedInfo = serverEntry.getInfo(); + // If we wanted to include listener sockets in the result, this line would + // instead say + // const allSockets = resolvedInfo.listenerChildren.sockets.concat(resolvedInfo.sessionChildren.sockets).sort((ref1, ref2) => ref1.id - ref2.id); + const allSockets = resolvedInfo.sessionChildren.sockets.sort((ref1, ref2) => ref1.id - ref2.id); + const resultList: SocketRefMessage[] = []; + let i = 0; + for (; i < allSockets.length; i++) { + if (allSockets[i].id >= startId) { + resultList.push(socketRefToMessage(allSockets[i])); + if (resultList.length >= maxResults) { + break; + } + } + } + callback(null, { + socket_ref: resultList, + end: i >= allSockets.length + }); +} + +export function getChannelzHandlers(): ChannelzHandlers { + return { + GetChannel, + GetTopChannels, + GetServer, + GetServers, + GetSubchannel, + GetSocket, + GetServerSockets + }; +} + +let loadedChannelzDefinition: ChannelzDefinition | null = null; + +export function getChannelzServiceDefinition(): ChannelzDefinition { + if (loadedChannelzDefinition) { + return loadedChannelzDefinition; + } + /* The purpose of this complexity is to avoid loading @grpc/proto-loader at + * runtime for users who will not use/enable channelz. */ + const loaderLoadSync = require('@grpc/proto-loader').loadSync as typeof loadSync; + const loadedProto = loaderLoadSync('channelz.proto', { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + includeDirs: [ + `${__dirname}/../../proto` + ] + }); + const channelzGrpcObject = loadPackageDefinition(loadedProto) as unknown as ChannelzProtoGrpcType; + loadedChannelzDefinition = channelzGrpcObject.grpc.channelz.v1.Channelz.service; + return loadedChannelzDefinition; +} + +export function setup() { + registerAdminService(getChannelzServiceDefinition, getChannelzHandlers); +} \ No newline at end of file diff --git a/packages/grpc-js/src/client-interceptors.ts b/packages/grpc-js/src/client-interceptors.ts index a7cc2f878..d95828550 100644 --- a/packages/grpc-js/src/client-interceptors.ts +++ b/packages/grpc-js/src/client-interceptors.ts @@ -28,12 +28,13 @@ import { isInterceptingListener, MessageContext, Call, -} from './call-stream'; +} from './call-interface'; import { Status } from './constants'; import { Channel } from './channel'; import { CallOptions } from './client'; import { CallCredentials } from './call-credentials'; import { ClientMethodDefinition } from './make-client'; +import { getErrorMessage } from './error'; /** * Error class associated with passing both interceptors and interceptor @@ -198,8 +199,6 @@ export interface InterceptingCallInterface { sendMessage(message: any): void; startRead(): void; halfClose(): void; - - setCredentials(credentials: CallCredentials): void; } export class InterceptingCall implements InterceptingCallInterface { @@ -208,8 +207,18 @@ export class InterceptingCall implements InterceptingCallInterface { */ private requester: FullRequester; /** - * Indicates that a message has been passed to the listener's onReceiveMessage - * method it has not been passed to the corresponding next callback + * Indicates that metadata has been passed to the requester's start + * method but it has not been passed to the corresponding next callback + */ + private processingMetadata = false; + /** + * Message context for a pending message that is waiting for + */ + private pendingMessageContext: MessageContext | null = null; + private pendingMessage: any; + /** + * Indicates that a message has been passed to the requester's sendMessage + * method but it has not been passed to the corresponding next callback */ private processingMessage = false; /** @@ -242,6 +251,21 @@ export class InterceptingCall implements InterceptingCallInterface { getPeer() { return this.nextCall.getPeer(); } + + private processPendingMessage() { + if (this.pendingMessageContext) { + this.nextCall.sendMessageWithContext(this.pendingMessageContext, this.pendingMessage); + this.pendingMessageContext = null; + this.pendingMessage = null; + } + } + + private processPendingHalfClose() { + if (this.pendingHalfClose) { + this.nextCall.halfClose(); + } + } + start( metadata: Metadata, interceptingListener?: Partial @@ -257,7 +281,9 @@ export class InterceptingCall implements InterceptingCallInterface { interceptingListener?.onReceiveStatus?.bind(interceptingListener) ?? ((status) => {}), }; + this.processingMetadata = true; this.requester.start(metadata, fullInterceptingListener, (md, listener) => { + this.processingMetadata = false; let finalInterceptingListener: InterceptingListener; if (isInterceptingListener(listener)) { finalInterceptingListener = listener; @@ -276,6 +302,8 @@ export class InterceptingCall implements InterceptingCallInterface { ); } this.nextCall.start(md, finalInterceptingListener); + this.processPendingMessage(); + this.processPendingHalfClose(); }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -283,9 +311,12 @@ export class InterceptingCall implements InterceptingCallInterface { this.processingMessage = true; this.requester.sendMessage(message, (finalMessage) => { this.processingMessage = false; - this.nextCall.sendMessageWithContext(context, finalMessage); - if (this.pendingHalfClose) { - this.nextCall.halfClose(); + if (this.processingMetadata) { + this.pendingMessageContext = context; + this.pendingMessage = message; + } else { + this.nextCall.sendMessageWithContext(context, finalMessage); + this.processPendingHalfClose(); } }); } @@ -298,16 +329,13 @@ export class InterceptingCall implements InterceptingCallInterface { } halfClose(): void { this.requester.halfClose(() => { - if (this.processingMessage) { + if (this.processingMetadata || this.processingMessage) { this.pendingHalfClose = true; } else { this.nextCall.halfClose(); } }); } - setCredentials(credentials: CallCredentials): void { - this.nextCall.setCredentials(credentials); - } } function getCall(channel: Channel, path: string, options: CallOptions): Call { @@ -339,16 +367,16 @@ class BaseInterceptingCall implements InterceptingCallInterface { getPeer(): string { return this.call.getPeer(); } - setCredentials(credentials: CallCredentials): void { - this.call.setCredentials(credentials); - } // eslint-disable-next-line @typescript-eslint/no-explicit-any sendMessageWithContext(context: MessageContext, message: any): void { let serialized: Buffer; try { serialized = this.methodDefinition.requestSerialize(message); } catch (e) { - this.call.cancelWithStatus(Status.INTERNAL, `Request message serialization failure: ${e.message}`); + this.call.cancelWithStatus( + Status.INTERNAL, + `Request message serialization failure: ${getErrorMessage(e)}` + ); return; } this.call.sendMessageWithContext(context, serialized); @@ -374,7 +402,7 @@ class BaseInterceptingCall implements InterceptingCallInterface { } catch (e) { readError = { code: Status.INTERNAL, - details: `Response message parsing error: ${e.message}`, + details: `Response message parsing error: ${getErrorMessage(e)}`, metadata: new Metadata(), }; this.call.cancelWithStatus(readError.code, readError.details); @@ -403,7 +431,8 @@ class BaseInterceptingCall implements InterceptingCallInterface { * BaseInterceptingCall with special-cased behavior for methods with unary * responses. */ -class BaseUnaryInterceptingCall extends BaseInterceptingCall +class BaseUnaryInterceptingCall + extends BaseInterceptingCall implements InterceptingCallInterface { // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor(call: Call, methodDefinition: ClientMethodDefinition) { @@ -435,7 +464,8 @@ class BaseUnaryInterceptingCall extends BaseInterceptingCall * BaseInterceptingCall with special-cased behavior for methods with streaming * responses. */ -class BaseStreamingInterceptingCall extends BaseInterceptingCall +class BaseStreamingInterceptingCall + extends BaseInterceptingCall implements InterceptingCallInterface {} function getBottomInterceptingCall( diff --git a/packages/grpc-js/src/client.ts b/packages/grpc-js/src/client.ts index 204be9017..bdbdc6e97 100644 --- a/packages/grpc-js/src/client.ts +++ b/packages/grpc-js/src/client.ts @@ -29,8 +29,9 @@ import { SurfaceCall, } from './call'; import { CallCredentials } from './call-credentials'; -import { Deadline, StatusObject } from './call-stream'; -import { Channel, ConnectivityState, ChannelImplementation } from './channel'; +import { StatusObject } from './call-interface'; +import { Channel, ChannelImplementation } from './channel'; +import { ConnectivityState } from './connectivity-state'; import { ChannelCredentials } from './channel-credentials'; import { ChannelOptions } from './channel-options'; import { Status } from './constants'; @@ -49,13 +50,16 @@ import { ServerWritableStream, ServerDuplexStream, } from './server-call'; +import { Deadline } from './deadline'; const CHANNEL_SYMBOL = Symbol(); const INTERCEPTOR_SYMBOL = Symbol(); const INTERCEPTOR_PROVIDER_SYMBOL = Symbol(); const CALL_INVOCATION_TRANSFORMER_SYMBOL = Symbol(); -function isFunction(arg: Metadata | CallOptions | UnaryCallback | undefined): arg is UnaryCallback{ +function isFunction( + arg: Metadata | CallOptions | UnaryCallback | undefined +): arg is UnaryCallback { return typeof arg === 'function'; } @@ -105,6 +109,10 @@ export type ClientOptions = Partial & { callInvocationTransformer?: CallInvocationTransformer; }; +function getErrorStackString(error: Error): string { + return error.stack!.split('\n').slice(1).join('\n'); +} + /** * A generic gRPC client. Primarily useful as a base class for all generated * clients. @@ -265,9 +273,11 @@ export class Client { options?: CallOptions | UnaryCallback, callback?: UnaryCallback ): ClientUnaryCall { - const checkedArguments = this.checkOptionalUnaryResponseArguments< - ResponseType - >(metadata, options, callback); + const checkedArguments = this.checkOptionalUnaryResponseArguments( + metadata, + options, + callback + ); const methodDefinition: ClientMethodDefinition< RequestType, ResponseType @@ -311,11 +321,9 @@ export class Client { * before calling the CallInvocationTransformer, and we need to create the * call after that. */ emitter.call = call; - if (callProperties.callOptions.credentials) { - call.setCredentials(callProperties.callOptions.credentials); - } let responseMessage: ResponseType | null = null; let receivedStatus = false; + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata: (metadata) => { emitter.emit('metadata', metadata); @@ -333,10 +341,23 @@ export class Client { } receivedStatus = true; if (status.code === Status.OK) { - callProperties.callback!(null, responseMessage!); + if (responseMessage === null) { + const callerStack = getErrorStackString(callerStackError!); + callProperties.callback!(callErrorFromStatus({ + code: Status.INTERNAL, + details: 'No message received', + metadata: status.metadata + }, /*callerStack*/'')); + } else { + callProperties.callback!(null, responseMessage); + } } else { - callProperties.callback!(callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError!); + callProperties.callback!(callErrorFromStatus(status, /*callerStack*/'')); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; emitter.emit('status', status); }, }); @@ -381,9 +402,11 @@ export class Client { options?: CallOptions | UnaryCallback, callback?: UnaryCallback ): ClientWritableStream { - const checkedArguments = this.checkOptionalUnaryResponseArguments< - ResponseType - >(metadata, options, callback); + const checkedArguments = this.checkOptionalUnaryResponseArguments( + metadata, + options, + callback + ); const methodDefinition: ClientMethodDefinition< RequestType, ResponseType @@ -407,9 +430,7 @@ export class Client { callProperties ) as CallProperties; } - const emitter: ClientWritableStream = callProperties.call as ClientWritableStream< - RequestType - >; + const emitter: ClientWritableStream = callProperties.call as ClientWritableStream; const interceptorArgs: InterceptorArguments = { clientInterceptors: this[INTERCEPTOR_SYMBOL], clientInterceptorProviders: this[INTERCEPTOR_PROVIDER_SYMBOL], @@ -428,11 +449,9 @@ export class Client { * before calling the CallInvocationTransformer, and we need to create the * call after that. */ emitter.call = call; - if (callProperties.callOptions.credentials) { - call.setCredentials(callProperties.callOptions.credentials); - } let responseMessage: ResponseType | null = null; let receivedStatus = false; + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata: (metadata) => { emitter.emit('metadata', metadata); @@ -450,10 +469,23 @@ export class Client { } receivedStatus = true; if (status.code === Status.OK) { - callProperties.callback!(null, responseMessage!); + if (responseMessage === null) { + const callerStack = getErrorStackString(callerStackError!); + callProperties.callback!(callErrorFromStatus({ + code: Status.INTERNAL, + details: 'No message received', + metadata: status.metadata + }, callerStack)); + } else { + callProperties.callback!(null, responseMessage); + } } else { - callProperties.callback!(callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError!); + callProperties.callback!(callErrorFromStatus(status, callerStack)); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; emitter.emit('status', status); }, }); @@ -531,9 +563,7 @@ export class Client { callProperties ) as CallProperties; } - const stream: ClientReadableStream = callProperties.call as ClientReadableStream< - ResponseType - >; + const stream: ClientReadableStream = callProperties.call as ClientReadableStream; const interceptorArgs: InterceptorArguments = { clientInterceptors: this[INTERCEPTOR_SYMBOL], clientInterceptorProviders: this[INTERCEPTOR_PROVIDER_SYMBOL], @@ -552,10 +582,8 @@ export class Client { * before calling the CallInvocationTransformer, and we need to create the * call after that. */ stream.call = call; - if (callProperties.callOptions.credentials) { - call.setCredentials(callProperties.callOptions.credentials); - } let receivedStatus = false; + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata(metadata: Metadata) { stream.emit('metadata', metadata); @@ -571,8 +599,12 @@ export class Client { receivedStatus = true; stream.push(null); if (status.code !== Status.OK) { - stream.emit('error', callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError!); + stream.emit('error', callErrorFromStatus(status, callerStack)); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; stream.emit('status', status); }, }); @@ -649,16 +681,14 @@ export class Client { * before calling the CallInvocationTransformer, and we need to create the * call after that. */ stream.call = call; - if (callProperties.callOptions.credentials) { - call.setCredentials(callProperties.callOptions.credentials); - } let receivedStatus = false; + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata(metadata: Metadata) { stream.emit('metadata', metadata); }, onReceiveMessage(message: Buffer) { - stream.push(message) + stream.push(message); }, onReceiveStatus(status: StatusObject) { if (receivedStatus) { @@ -667,12 +697,15 @@ export class Client { receivedStatus = true; stream.push(null); if (status.code !== Status.OK) { - stream.emit('error', callErrorFromStatus(status)); + const callerStack = getErrorStackString(callerStackError!); + stream.emit('error', callErrorFromStatus(status, callerStack)); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; stream.emit('status', status); }, }); return stream; } } - diff --git a/packages/grpc-js/src/compression-algorithms.ts b/packages/grpc-js/src/compression-algorithms.ts new file mode 100644 index 000000000..ca2c7a624 --- /dev/null +++ b/packages/grpc-js/src/compression-algorithms.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export enum CompressionAlgorithms { + identity = 0, + deflate = 1, + gzip = 2 +}; diff --git a/packages/grpc-js/src/compression-filter.ts b/packages/grpc-js/src/compression-filter.ts index 330eb675a..f87614114 100644 --- a/packages/grpc-js/src/compression-filter.ts +++ b/packages/grpc-js/src/compression-filter.ts @@ -17,11 +17,25 @@ import * as zlib from 'zlib'; -import { Call, WriteFlags, WriteObject } from './call-stream'; +import { WriteObject, WriteFlags } from './call-interface'; import { Channel } from './channel'; +import { ChannelOptions } from './channel-options'; +import { CompressionAlgorithms } from './compression-algorithms'; +import { LogVerbosity } from './constants'; import { BaseFilter, Filter, FilterFactory } from './filter'; +import * as logging from './logging'; import { Metadata, MetadataValue } from './metadata'; +const isCompressionAlgorithmKey = (key: number): key is CompressionAlgorithms => { + return typeof key === 'number' && typeof CompressionAlgorithms[key] === 'string'; +} + +type CompressionAlgorithm = keyof typeof CompressionAlgorithms; + +type SharedCompressionFilterConfig = { + serverSupportedEncodingHeader?: string; +}; + abstract class CompressionHandler { protected abstract compressMessage(message: Buffer): Promise; protected abstract decompressMessage(data: Buffer): Promise; @@ -167,10 +181,45 @@ function getCompressionHandler(compressionName: string): CompressionHandler { export class CompressionFilter extends BaseFilter implements Filter { private sendCompression: CompressionHandler = new IdentityHandler(); private receiveCompression: CompressionHandler = new IdentityHandler(); + private currentCompressionAlgorithm: CompressionAlgorithm = 'identity'; + + constructor(channelOptions: ChannelOptions, private sharedFilterConfig: SharedCompressionFilterConfig) { + super(); + + const compressionAlgorithmKey = channelOptions['grpc.default_compression_algorithm']; + if (compressionAlgorithmKey !== undefined) { + if (isCompressionAlgorithmKey(compressionAlgorithmKey)) { + const clientSelectedEncoding = CompressionAlgorithms[compressionAlgorithmKey] as CompressionAlgorithm; + const serverSupportedEncodings = sharedFilterConfig.serverSupportedEncodingHeader?.split(','); + /** + * There are two possible situations here: + * 1) We don't have any info yet from the server about what compression it supports + * In that case we should just use what the client tells us to use + * 2) We've previously received a response from the server including a grpc-accept-encoding header + * In that case we only want to use the encoding chosen by the client if the server supports it + */ + if (!serverSupportedEncodings || serverSupportedEncodings.includes(clientSelectedEncoding)) { + this.currentCompressionAlgorithm = clientSelectedEncoding; + this.sendCompression = getCompressionHandler(this.currentCompressionAlgorithm); + } + } else { + logging.log(LogVerbosity.ERROR, `Invalid value provided for grpc.default_compression_algorithm option: ${compressionAlgorithmKey}`); + } + } + } + async sendMetadata(metadata: Promise): Promise { const headers: Metadata = await metadata; headers.set('grpc-accept-encoding', 'identity,deflate,gzip'); headers.set('accept-encoding', 'identity'); + + // No need to send the header if it's "identity" - behavior is identical; save the bandwidth + if (this.currentCompressionAlgorithm === 'identity') { + headers.remove('grpc-encoding'); + } else { + headers.set('grpc-encoding', this.currentCompressionAlgorithm); + } + return headers; } @@ -183,6 +232,19 @@ export class CompressionFilter extends BaseFilter implements Filter { } } metadata.remove('grpc-encoding'); + + /* Check to see if the compression we're using to send messages is supported by the server + * If not, reset the sendCompression filter and have it use the default IdentityHandler */ + const serverSupportedEncodingsHeader = metadata.get('grpc-accept-encoding')[0] as string | undefined; + if (serverSupportedEncodingsHeader) { + this.sharedFilterConfig.serverSupportedEncodingHeader = serverSupportedEncodingsHeader; + const serverSupportedEncodings = serverSupportedEncodingsHeader.split(','); + + if (!serverSupportedEncodings.includes(this.currentCompressionAlgorithm)) { + this.sendCompression = new IdentityHandler(); + this.currentCompressionAlgorithm = 'identity'; + } + } metadata.remove('grpc-accept-encoding'); return metadata; } @@ -192,10 +254,13 @@ export class CompressionFilter extends BaseFilter implements Filter { * and the output is a framed and possibly compressed message. For this * reason, this filter should be at the bottom of the filter stack */ const resolvedMessage: WriteObject = await message; - const compress = - resolvedMessage.flags === undefined - ? false - : (resolvedMessage.flags & WriteFlags.NoCompress) === 0; + let compress: boolean; + if (this.sendCompression instanceof IdentityHandler) { + compress = false; + } else { + compress = ((resolvedMessage.flags ?? 0) & WriteFlags.NoCompress) === 0; + } + return { message: await this.sendCompression.writeMessage( resolvedMessage.message, @@ -216,8 +281,9 @@ export class CompressionFilter extends BaseFilter implements Filter { export class CompressionFilterFactory implements FilterFactory { - constructor(private readonly channel: Channel) {} - createFilter(callStream: Call): CompressionFilter { - return new CompressionFilter(); + private sharedFilterConfig: SharedCompressionFilterConfig = {}; + constructor(private readonly channel: Channel, private readonly options: ChannelOptions) {} + createFilter(): CompressionFilter { + return new CompressionFilter(this.options, this.sharedFilterConfig); } } diff --git a/packages/grpc-js/src/connectivity-state.ts b/packages/grpc-js/src/connectivity-state.ts new file mode 100644 index 000000000..560ab9c39 --- /dev/null +++ b/packages/grpc-js/src/connectivity-state.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export enum ConnectivityState { + IDLE, + CONNECTING, + READY, + TRANSIENT_FAILURE, + SHUTDOWN, +} diff --git a/packages/grpc-js/src/constants.ts b/packages/grpc-js/src/constants.ts index 94763cfe1..865b24c94 100644 --- a/packages/grpc-js/src/constants.ts +++ b/packages/grpc-js/src/constants.ts @@ -52,7 +52,11 @@ export enum Propagate { CENSUS_TRACING_CONTEXT = 4, CANCELLATION = 8, // https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/propagation_bits.h#L43 - DEFAULTS = 0xffff | Propagate.DEADLINE | Propagate.CENSUS_STATS_CONTEXT | Propagate.CENSUS_TRACING_CONTEXT | Propagate.CANCELLATION, + DEFAULTS = 0xffff | + Propagate.DEADLINE | + Propagate.CENSUS_STATS_CONTEXT | + Propagate.CENSUS_TRACING_CONTEXT | + Propagate.CANCELLATION, } // -1 means unlimited diff --git a/packages/grpc-js/src/control-plane-status.ts b/packages/grpc-js/src/control-plane-status.ts new file mode 100644 index 000000000..808d695b2 --- /dev/null +++ b/packages/grpc-js/src/control-plane-status.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { Status } from './constants'; + +const INAPPROPRIATE_CONTROL_PLANE_CODES: Status[] = [ + Status.OK, + Status.INVALID_ARGUMENT, + Status.NOT_FOUND, + Status.ALREADY_EXISTS, + Status.FAILED_PRECONDITION, + Status.ABORTED, + Status.OUT_OF_RANGE, + Status.DATA_LOSS +] + +export function restrictControlPlaneStatusCode(code: Status, details: string): {code: Status, details: string} { + if (INAPPROPRIATE_CONTROL_PLANE_CODES.includes(code)) { + return { + code: Status.INTERNAL, + details: `Invalid status from control plane: ${code} ${Status[code]} ${details}` + } + } else { + return {code, details}; + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/deadline-filter.ts b/packages/grpc-js/src/deadline-filter.ts deleted file mode 100644 index 99bfa2bec..000000000 --- a/packages/grpc-js/src/deadline-filter.ts +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import { Call, StatusObject } from './call-stream'; -import { Channel } from './channel'; -import { Status } from './constants'; -import { BaseFilter, Filter, FilterFactory } from './filter'; -import { Metadata } from './metadata'; - -const units: Array<[string, number]> = [ - ['m', 1], - ['S', 1000], - ['M', 60 * 1000], - ['H', 60 * 60 * 1000], -]; - -function getDeadline(deadline: number) { - const now = new Date().getTime(); - const timeoutMs = Math.max(deadline - now, 0); - for (const [unit, factor] of units) { - const amount = timeoutMs / factor; - if (amount < 1e8) { - return String(Math.ceil(amount)) + unit; - } - } - throw new Error('Deadline is too far in the future'); -} - -export class DeadlineFilter extends BaseFilter implements Filter { - private timer: NodeJS.Timer | null = null; - private deadline: number; - constructor( - private readonly channel: Channel, - private readonly callStream: Call - ) { - super(); - const callDeadline = callStream.getDeadline(); - if (callDeadline instanceof Date) { - this.deadline = callDeadline.getTime(); - } else { - this.deadline = callDeadline; - } - const now: number = new Date().getTime(); - let timeout = this.deadline - now; - if (timeout <= 0) { - process.nextTick(() => { - callStream.cancelWithStatus( - Status.DEADLINE_EXCEEDED, - 'Deadline exceeded' - ); - }); - } else if (this.deadline !== Infinity) { - this.timer = setTimeout(() => { - callStream.cancelWithStatus( - Status.DEADLINE_EXCEEDED, - 'Deadline exceeded' - ); - }, timeout); - this.timer.unref?.(); - } - } - - async sendMetadata(metadata: Promise) { - if (this.deadline === Infinity) { - return metadata; - } - /* The input metadata promise depends on the original channel.connect() - * promise, so when it is complete that implies that the channel is - * connected */ - const finalMetadata = await metadata; - const timeoutString = getDeadline(this.deadline); - finalMetadata.set('grpc-timeout', timeoutString); - return finalMetadata; - } - - receiveTrailers(status: StatusObject) { - if (this.timer) { - clearTimeout(this.timer); - } - return status; - } -} - -export class DeadlineFilterFactory implements FilterFactory { - constructor(private readonly channel: Channel) {} - - createFilter(callStream: Call): DeadlineFilter { - return new DeadlineFilter(this.channel, callStream); - } -} diff --git a/packages/grpc-js/src/deadline.ts b/packages/grpc-js/src/deadline.ts new file mode 100644 index 000000000..be1f3c3b0 --- /dev/null +++ b/packages/grpc-js/src/deadline.ts @@ -0,0 +1,95 @@ +/* + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export type Deadline = Date | number; + +export function minDeadline(...deadlineList: Deadline[]): Deadline { + let minValue = Infinity; + for (const deadline of deadlineList) { + const deadlineMsecs = + deadline instanceof Date ? deadline.getTime() : deadline; + if (deadlineMsecs < minValue) { + minValue = deadlineMsecs; + } + } + return minValue; +} + +const units: Array<[string, number]> = [ + ['m', 1], + ['S', 1000], + ['M', 60 * 1000], + ['H', 60 * 60 * 1000], +]; + +export function getDeadlineTimeoutString(deadline: Deadline) { + const now = new Date().getTime(); + if (deadline instanceof Date) { + deadline = deadline.getTime(); + } + const timeoutMs = Math.max(deadline - now, 0); + for (const [unit, factor] of units) { + const amount = timeoutMs / factor; + if (amount < 1e8) { + return String(Math.ceil(amount)) + unit; + } + } + throw new Error('Deadline is too far in the future') +} + +/** + * See https://nodejs.org/api/timers.html#settimeoutcallback-delay-args + * In particular, "When delay is larger than 2147483647 or less than 1, the + * delay will be set to 1. Non-integer delays are truncated to an integer." + * This number of milliseconds is almost 25 days. + */ +const MAX_TIMEOUT_TIME = 2147483647; + +/** + * Get the timeout value that should be passed to setTimeout now for the timer + * to end at the deadline. For any deadline before now, the timer should end + * immediately, represented by a value of 0. For any deadline more than + * MAX_TIMEOUT_TIME milliseconds in the future, a timer cannot be set that will + * end at that time, so it is treated as infinitely far in the future. + * @param deadline + * @returns + */ +export function getRelativeTimeout(deadline: Deadline) { + const deadlineMs = deadline instanceof Date ? deadline.getTime() : deadline; + const now = new Date().getTime(); + const timeout = deadlineMs - now; + if (timeout < 0) { + return 0; + } else if (timeout > MAX_TIMEOUT_TIME) { + return Infinity + } else { + return timeout; + } +} + +export function deadlineToString(deadline: Deadline): string { + if (deadline instanceof Date) { + return deadline.toISOString(); + } else { + const dateDeadline = new Date(deadline); + if (Number.isNaN(dateDeadline.getTime())) { + return '' + deadline; + } else { + return dateDeadline.toISOString(); + } + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/duration.ts b/packages/grpc-js/src/duration.ts new file mode 100644 index 000000000..278c9ae54 --- /dev/null +++ b/packages/grpc-js/src/duration.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export interface Duration { + seconds: number; + nanos: number; +} + +export function msToDuration(millis: number): Duration { + return { + seconds: (millis / 1000) | 0, + nanos: (millis % 1000) * 1_000_000 | 0 + }; +} + +export function durationToMs(duration: Duration): number { + return (duration.seconds * 1000 + duration.nanos / 1_000_000) | 0; +} + +export function isDuration(value: any): value is Duration { + return (typeof value.seconds === 'number') && (typeof value.nanos === 'number'); +} \ No newline at end of file diff --git a/packages/grpc-js/src/error.ts b/packages/grpc-js/src/error.ts new file mode 100644 index 000000000..b973128a7 --- /dev/null +++ b/packages/grpc-js/src/error.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export function getErrorMessage(error: unknown): string { + if (error instanceof Error) { + return error.message; + } else { + return String(error); + } +} + +export function getErrorCode(error: unknown): number | null { + if ( + typeof error === 'object' && + error !== null && + 'code' in error && + typeof (error as Record).code === 'number' + ) { + return (error as Record).code; + } else { + return null; + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/experimental.ts b/packages/grpc-js/src/experimental.ts index f62838c12..a7c28219b 100644 --- a/packages/grpc-js/src/experimental.ts +++ b/packages/grpc-js/src/experimental.ts @@ -1,12 +1,39 @@ -export { trace } from './logging'; -export { Resolver, ResolverListener, registerResolver, ConfigSelector } from './resolver'; -export { GrpcUri, uriToString } from './uri-parser'; -export { ServiceConfig } from './service-config'; -export { BackoffTimeout } from './backoff-timeout'; -export { LoadBalancer, LoadBalancingConfig, ChannelControlHelper, registerLoadBalancerType, getFirstUsableConfig, validateLoadBalancingConfig } from './load-balancer'; -export { SubchannelAddress, subchannelAddressToString } from './subchannel'; -export { ChildLoadBalancerHandler } from './load-balancer-child-handler'; -export { Picker, UnavailablePicker, QueuePicker, PickResult, PickArgs, PickResultType } from './picker'; -export { Call as CallStream } from './call-stream'; -export { Filter, BaseFilter, FilterFactory } from './filter'; -export { FilterStackFactory } from './filter-stack'; \ No newline at end of file +export { trace, log } from './logging'; +export { + Resolver, + ResolverListener, + registerResolver, + ConfigSelector, +} from './resolver'; +export { GrpcUri, uriToString } from './uri-parser'; +export { Duration, durationToMs } from './duration'; +export { ServiceConfig, MethodConfig, RetryPolicy } from './service-config'; +export { BackoffTimeout } from './backoff-timeout'; +export { + LoadBalancer, + LoadBalancingConfig, + ChannelControlHelper, + createChildChannelControlHelper, + registerLoadBalancerType, + getFirstUsableConfig, + validateLoadBalancingConfig, +} from './load-balancer'; +export { + SubchannelAddress, + subchannelAddressToString, +} from './subchannel-address'; +export { ChildLoadBalancerHandler } from './load-balancer-child-handler'; +export { + Picker, + UnavailablePicker, + QueuePicker, + PickResult, + PickArgs, + PickResultType, +} from './picker'; +export { Call as CallStream } from './call-interface'; +export { Filter, BaseFilter, FilterFactory } from './filter'; +export { FilterStackFactory } from './filter-stack'; +export { registerAdminService } from './admin'; +export { SubchannelInterface, BaseSubchannelWrapper, ConnectivityStateListener } from './subchannel-interface'; +export { OutlierDetectionLoadBalancingConfig, SuccessRateEjectionConfig, FailurePercentageEjectionConfig } from './load-balancer-outlier-detection'; diff --git a/packages/grpc-js/src/filter-stack.ts b/packages/grpc-js/src/filter-stack.ts index a656a4099..4733c8218 100644 --- a/packages/grpc-js/src/filter-stack.ts +++ b/packages/grpc-js/src/filter-stack.ts @@ -15,14 +15,14 @@ * */ -import { Call, StatusObject, WriteObject } from './call-stream'; +import { StatusObject, WriteObject } from './call-interface'; import { Filter, FilterFactory } from './filter'; import { Metadata } from './metadata'; export class FilterStack implements Filter { constructor(private readonly filters: Filter[]) {} - sendMetadata(metadata: Promise) { + sendMetadata(metadata: Promise): Promise { let result: Promise = metadata; for (let i = 0; i < this.filters.length; i++) { @@ -71,14 +71,30 @@ export class FilterStack implements Filter { return result; } + + push(filters: Filter[]) { + this.filters.unshift(...filters); + } + + getFilters(): Filter[] { + return this.filters; + } } export class FilterStackFactory implements FilterFactory { constructor(private readonly factories: Array>) {} - createFilter(callStream: Call): FilterStack { + push(filterFactories: FilterFactory[]) { + this.factories.unshift(...filterFactories); + } + + clone(): FilterStackFactory { + return new FilterStackFactory([...this.factories]); + } + + createFilter(): FilterStack { return new FilterStack( - this.factories.map((factory) => factory.createFilter(callStream)) + this.factories.map((factory) => factory.createFilter()) ); } } diff --git a/packages/grpc-js/src/filter.ts b/packages/grpc-js/src/filter.ts index c1e412ae5..5313f91a8 100644 --- a/packages/grpc-js/src/filter.ts +++ b/packages/grpc-js/src/filter.ts @@ -15,12 +15,14 @@ * */ -import { Call, StatusObject, WriteObject } from './call-stream'; +import { StatusObject, WriteObject } from './call-interface'; import { Metadata } from './metadata'; /** * Filter classes represent related per-call logic and state that is primarily - * used to modify incoming and outgoing data + * used to modify incoming and outgoing data. All async filters can be + * rejected. The rejection error must be a StatusObject, and a rejection will + * cause the call to end with that status. */ export interface Filter { sendMetadata(metadata: Promise): Promise; @@ -57,5 +59,5 @@ export abstract class BaseFilter implements Filter { } export interface FilterFactory { - createFilter(callStream: Call): T; + createFilter(): T; } diff --git a/packages/grpc-js/src/generated/channelz.ts b/packages/grpc-js/src/generated/channelz.ts new file mode 100644 index 000000000..367cf27f6 --- /dev/null +++ b/packages/grpc-js/src/generated/channelz.ts @@ -0,0 +1,73 @@ +import type * as grpc from '../index'; +import type { MessageTypeDefinition } from '@grpc/proto-loader'; + +import type { ChannelzClient as _grpc_channelz_v1_ChannelzClient, ChannelzDefinition as _grpc_channelz_v1_ChannelzDefinition } from './grpc/channelz/v1/Channelz'; + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + google: { + protobuf: { + Any: MessageTypeDefinition + BoolValue: MessageTypeDefinition + BytesValue: MessageTypeDefinition + DoubleValue: MessageTypeDefinition + Duration: MessageTypeDefinition + FloatValue: MessageTypeDefinition + Int32Value: MessageTypeDefinition + Int64Value: MessageTypeDefinition + StringValue: MessageTypeDefinition + Timestamp: MessageTypeDefinition + UInt32Value: MessageTypeDefinition + UInt64Value: MessageTypeDefinition + } + } + grpc: { + channelz: { + v1: { + Address: MessageTypeDefinition + Channel: MessageTypeDefinition + ChannelConnectivityState: MessageTypeDefinition + ChannelData: MessageTypeDefinition + ChannelRef: MessageTypeDefinition + ChannelTrace: MessageTypeDefinition + ChannelTraceEvent: MessageTypeDefinition + /** + * Channelz is a service exposed by gRPC servers that provides detailed debug + * information. + */ + Channelz: SubtypeConstructor & { service: _grpc_channelz_v1_ChannelzDefinition } + GetChannelRequest: MessageTypeDefinition + GetChannelResponse: MessageTypeDefinition + GetServerRequest: MessageTypeDefinition + GetServerResponse: MessageTypeDefinition + GetServerSocketsRequest: MessageTypeDefinition + GetServerSocketsResponse: MessageTypeDefinition + GetServersRequest: MessageTypeDefinition + GetServersResponse: MessageTypeDefinition + GetSocketRequest: MessageTypeDefinition + GetSocketResponse: MessageTypeDefinition + GetSubchannelRequest: MessageTypeDefinition + GetSubchannelResponse: MessageTypeDefinition + GetTopChannelsRequest: MessageTypeDefinition + GetTopChannelsResponse: MessageTypeDefinition + Security: MessageTypeDefinition + Server: MessageTypeDefinition + ServerData: MessageTypeDefinition + ServerRef: MessageTypeDefinition + Socket: MessageTypeDefinition + SocketData: MessageTypeDefinition + SocketOption: MessageTypeDefinition + SocketOptionLinger: MessageTypeDefinition + SocketOptionTcpInfo: MessageTypeDefinition + SocketOptionTimeout: MessageTypeDefinition + SocketRef: MessageTypeDefinition + Subchannel: MessageTypeDefinition + SubchannelRef: MessageTypeDefinition + } + } + } +} + diff --git a/packages/grpc-js/src/generated/google/protobuf/Any.ts b/packages/grpc-js/src/generated/google/protobuf/Any.ts new file mode 100644 index 000000000..fcaa6724e --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/Any.ts @@ -0,0 +1,13 @@ +// Original file: null + +import type { AnyExtension } from '@grpc/proto-loader'; + +export type Any = AnyExtension | { + type_url: string; + value: Buffer | Uint8Array | string; +} + +export interface Any__Output { + 'type_url': (string); + 'value': (Buffer); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/BoolValue.ts b/packages/grpc-js/src/generated/google/protobuf/BoolValue.ts new file mode 100644 index 000000000..86507eaf1 --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/BoolValue.ts @@ -0,0 +1,10 @@ +// Original file: null + + +export interface BoolValue { + 'value'?: (boolean); +} + +export interface BoolValue__Output { + 'value': (boolean); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/BytesValue.ts b/packages/grpc-js/src/generated/google/protobuf/BytesValue.ts new file mode 100644 index 000000000..9cec76f71 --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/BytesValue.ts @@ -0,0 +1,10 @@ +// Original file: null + + +export interface BytesValue { + 'value'?: (Buffer | Uint8Array | string); +} + +export interface BytesValue__Output { + 'value': (Buffer); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/DoubleValue.ts b/packages/grpc-js/src/generated/google/protobuf/DoubleValue.ts new file mode 100644 index 000000000..d70b303c2 --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/DoubleValue.ts @@ -0,0 +1,10 @@ +// Original file: null + + +export interface DoubleValue { + 'value'?: (number | string); +} + +export interface DoubleValue__Output { + 'value': (number); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/Duration.ts b/packages/grpc-js/src/generated/google/protobuf/Duration.ts new file mode 100644 index 000000000..8595377a0 --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/Duration.ts @@ -0,0 +1,13 @@ +// Original file: null + +import type { Long } from '@grpc/proto-loader'; + +export interface Duration { + 'seconds'?: (number | string | Long); + 'nanos'?: (number); +} + +export interface Duration__Output { + 'seconds': (string); + 'nanos': (number); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/FloatValue.ts b/packages/grpc-js/src/generated/google/protobuf/FloatValue.ts new file mode 100644 index 000000000..54a655fbb --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/FloatValue.ts @@ -0,0 +1,10 @@ +// Original file: null + + +export interface FloatValue { + 'value'?: (number | string); +} + +export interface FloatValue__Output { + 'value': (number); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/Int32Value.ts b/packages/grpc-js/src/generated/google/protobuf/Int32Value.ts new file mode 100644 index 000000000..ec4eeb7ec --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/Int32Value.ts @@ -0,0 +1,10 @@ +// Original file: null + + +export interface Int32Value { + 'value'?: (number); +} + +export interface Int32Value__Output { + 'value': (number); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/Int64Value.ts b/packages/grpc-js/src/generated/google/protobuf/Int64Value.ts new file mode 100644 index 000000000..f7375196d --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/Int64Value.ts @@ -0,0 +1,11 @@ +// Original file: null + +import type { Long } from '@grpc/proto-loader'; + +export interface Int64Value { + 'value'?: (number | string | Long); +} + +export interface Int64Value__Output { + 'value': (string); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/StringValue.ts b/packages/grpc-js/src/generated/google/protobuf/StringValue.ts new file mode 100644 index 000000000..673090e3f --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/StringValue.ts @@ -0,0 +1,10 @@ +// Original file: null + + +export interface StringValue { + 'value'?: (string); +} + +export interface StringValue__Output { + 'value': (string); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/Timestamp.ts b/packages/grpc-js/src/generated/google/protobuf/Timestamp.ts new file mode 100644 index 000000000..ceaa32b5f --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/Timestamp.ts @@ -0,0 +1,13 @@ +// Original file: null + +import type { Long } from '@grpc/proto-loader'; + +export interface Timestamp { + 'seconds'?: (number | string | Long); + 'nanos'?: (number); +} + +export interface Timestamp__Output { + 'seconds': (string); + 'nanos': (number); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/UInt32Value.ts b/packages/grpc-js/src/generated/google/protobuf/UInt32Value.ts new file mode 100644 index 000000000..973ab34a5 --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/UInt32Value.ts @@ -0,0 +1,10 @@ +// Original file: null + + +export interface UInt32Value { + 'value'?: (number); +} + +export interface UInt32Value__Output { + 'value': (number); +} diff --git a/packages/grpc-js/src/generated/google/protobuf/UInt64Value.ts b/packages/grpc-js/src/generated/google/protobuf/UInt64Value.ts new file mode 100644 index 000000000..7a85c39ce --- /dev/null +++ b/packages/grpc-js/src/generated/google/protobuf/UInt64Value.ts @@ -0,0 +1,11 @@ +// Original file: null + +import type { Long } from '@grpc/proto-loader'; + +export interface UInt64Value { + 'value'?: (number | string | Long); +} + +export interface UInt64Value__Output { + 'value': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/Address.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/Address.ts new file mode 100644 index 000000000..259cfeabe --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/Address.ts @@ -0,0 +1,89 @@ +// Original file: proto/channelz.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; + +/** + * An address type not included above. + */ +export interface _grpc_channelz_v1_Address_OtherAddress { + /** + * The human readable version of the value. This value should be set. + */ + 'name'?: (string); + /** + * The actual address message. + */ + 'value'?: (_google_protobuf_Any | null); +} + +/** + * An address type not included above. + */ +export interface _grpc_channelz_v1_Address_OtherAddress__Output { + /** + * The human readable version of the value. This value should be set. + */ + 'name': (string); + /** + * The actual address message. + */ + 'value': (_google_protobuf_Any__Output | null); +} + +export interface _grpc_channelz_v1_Address_TcpIpAddress { + /** + * Either the IPv4 or IPv6 address in bytes. Will be either 4 bytes or 16 + * bytes in length. + */ + 'ip_address'?: (Buffer | Uint8Array | string); + /** + * 0-64k, or -1 if not appropriate. + */ + 'port'?: (number); +} + +export interface _grpc_channelz_v1_Address_TcpIpAddress__Output { + /** + * Either the IPv4 or IPv6 address in bytes. Will be either 4 bytes or 16 + * bytes in length. + */ + 'ip_address': (Buffer); + /** + * 0-64k, or -1 if not appropriate. + */ + 'port': (number); +} + +/** + * A Unix Domain Socket address. + */ +export interface _grpc_channelz_v1_Address_UdsAddress { + 'filename'?: (string); +} + +/** + * A Unix Domain Socket address. + */ +export interface _grpc_channelz_v1_Address_UdsAddress__Output { + 'filename': (string); +} + +/** + * Address represents the address used to create the socket. + */ +export interface Address { + 'tcpip_address'?: (_grpc_channelz_v1_Address_TcpIpAddress | null); + 'uds_address'?: (_grpc_channelz_v1_Address_UdsAddress | null); + 'other_address'?: (_grpc_channelz_v1_Address_OtherAddress | null); + 'address'?: "tcpip_address"|"uds_address"|"other_address"; +} + +/** + * Address represents the address used to create the socket. + */ +export interface Address__Output { + 'tcpip_address'?: (_grpc_channelz_v1_Address_TcpIpAddress__Output | null); + 'uds_address'?: (_grpc_channelz_v1_Address_UdsAddress__Output | null); + 'other_address'?: (_grpc_channelz_v1_Address_OtherAddress__Output | null); + 'address': "tcpip_address"|"uds_address"|"other_address"; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/Channel.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/Channel.ts new file mode 100644 index 000000000..93b4a261d --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/Channel.ts @@ -0,0 +1,68 @@ +// Original file: proto/channelz.proto + +import type { ChannelRef as _grpc_channelz_v1_ChannelRef, ChannelRef__Output as _grpc_channelz_v1_ChannelRef__Output } from '../../../grpc/channelz/v1/ChannelRef'; +import type { ChannelData as _grpc_channelz_v1_ChannelData, ChannelData__Output as _grpc_channelz_v1_ChannelData__Output } from '../../../grpc/channelz/v1/ChannelData'; +import type { SubchannelRef as _grpc_channelz_v1_SubchannelRef, SubchannelRef__Output as _grpc_channelz_v1_SubchannelRef__Output } from '../../../grpc/channelz/v1/SubchannelRef'; +import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef'; + +/** + * Channel is a logical grouping of channels, subchannels, and sockets. + */ +export interface Channel { + /** + * The identifier for this channel. This should bet set. + */ + 'ref'?: (_grpc_channelz_v1_ChannelRef | null); + /** + * Data specific to this channel. + */ + 'data'?: (_grpc_channelz_v1_ChannelData | null); + /** + * There are no ordering guarantees on the order of channel refs. + * There may not be cycles in the ref graph. + * A channel ref may be present in more than one channel or subchannel. + */ + 'channel_ref'?: (_grpc_channelz_v1_ChannelRef)[]; + /** + * At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + * There are no ordering guarantees on the order of subchannel refs. + * There may not be cycles in the ref graph. + * A sub channel ref may be present in more than one channel or subchannel. + */ + 'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef)[]; + /** + * There are no ordering guarantees on the order of sockets. + */ + 'socket_ref'?: (_grpc_channelz_v1_SocketRef)[]; +} + +/** + * Channel is a logical grouping of channels, subchannels, and sockets. + */ +export interface Channel__Output { + /** + * The identifier for this channel. This should bet set. + */ + 'ref': (_grpc_channelz_v1_ChannelRef__Output | null); + /** + * Data specific to this channel. + */ + 'data': (_grpc_channelz_v1_ChannelData__Output | null); + /** + * There are no ordering guarantees on the order of channel refs. + * There may not be cycles in the ref graph. + * A channel ref may be present in more than one channel or subchannel. + */ + 'channel_ref': (_grpc_channelz_v1_ChannelRef__Output)[]; + /** + * At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + * There are no ordering guarantees on the order of subchannel refs. + * There may not be cycles in the ref graph. + * A sub channel ref may be present in more than one channel or subchannel. + */ + 'subchannel_ref': (_grpc_channelz_v1_SubchannelRef__Output)[]; + /** + * There are no ordering guarantees on the order of sockets. + */ + 'socket_ref': (_grpc_channelz_v1_SocketRef__Output)[]; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts new file mode 100644 index 000000000..be34ab98d --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts @@ -0,0 +1,29 @@ +// Original file: proto/channelz.proto + + +// Original file: proto/channelz.proto + +export enum _grpc_channelz_v1_ChannelConnectivityState_State { + UNKNOWN = 0, + IDLE = 1, + CONNECTING = 2, + READY = 3, + TRANSIENT_FAILURE = 4, + SHUTDOWN = 5, +} + +/** + * These come from the specified states in this document: + * https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md + */ +export interface ChannelConnectivityState { + 'state'?: (_grpc_channelz_v1_ChannelConnectivityState_State | keyof typeof _grpc_channelz_v1_ChannelConnectivityState_State); +} + +/** + * These come from the specified states in this document: + * https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md + */ +export interface ChannelConnectivityState__Output { + 'state': (keyof typeof _grpc_channelz_v1_ChannelConnectivityState_State); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelData.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelData.ts new file mode 100644 index 000000000..6d6824af4 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelData.ts @@ -0,0 +1,76 @@ +// Original file: proto/channelz.proto + +import type { ChannelConnectivityState as _grpc_channelz_v1_ChannelConnectivityState, ChannelConnectivityState__Output as _grpc_channelz_v1_ChannelConnectivityState__Output } from '../../../grpc/channelz/v1/ChannelConnectivityState'; +import type { ChannelTrace as _grpc_channelz_v1_ChannelTrace, ChannelTrace__Output as _grpc_channelz_v1_ChannelTrace__Output } from '../../../grpc/channelz/v1/ChannelTrace'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { Long } from '@grpc/proto-loader'; + +/** + * Channel data is data related to a specific Channel or Subchannel. + */ +export interface ChannelData { + /** + * The connectivity state of the channel or subchannel. Implementations + * should always set this. + */ + 'state'?: (_grpc_channelz_v1_ChannelConnectivityState | null); + /** + * The target this channel originally tried to connect to. May be absent + */ + 'target'?: (string); + /** + * A trace of recent events on the channel. May be absent. + */ + 'trace'?: (_grpc_channelz_v1_ChannelTrace | null); + /** + * The number of calls started on the channel + */ + 'calls_started'?: (number | string | Long); + /** + * The number of calls that have completed with an OK status + */ + 'calls_succeeded'?: (number | string | Long); + /** + * The number of calls that have completed with a non-OK status + */ + 'calls_failed'?: (number | string | Long); + /** + * The last time a call was started on the channel. + */ + 'last_call_started_timestamp'?: (_google_protobuf_Timestamp | null); +} + +/** + * Channel data is data related to a specific Channel or Subchannel. + */ +export interface ChannelData__Output { + /** + * The connectivity state of the channel or subchannel. Implementations + * should always set this. + */ + 'state': (_grpc_channelz_v1_ChannelConnectivityState__Output | null); + /** + * The target this channel originally tried to connect to. May be absent + */ + 'target': (string); + /** + * A trace of recent events on the channel. May be absent. + */ + 'trace': (_grpc_channelz_v1_ChannelTrace__Output | null); + /** + * The number of calls started on the channel + */ + 'calls_started': (string); + /** + * The number of calls that have completed with an OK status + */ + 'calls_succeeded': (string); + /** + * The number of calls that have completed with a non-OK status + */ + 'calls_failed': (string); + /** + * The last time a call was started on the channel. + */ + 'last_call_started_timestamp': (_google_protobuf_Timestamp__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelRef.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelRef.ts new file mode 100644 index 000000000..231d00876 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelRef.ts @@ -0,0 +1,31 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +/** + * ChannelRef is a reference to a Channel. + */ +export interface ChannelRef { + /** + * The globally unique id for this channel. Must be a positive number. + */ + 'channel_id'?: (number | string | Long); + /** + * An optional name associated with the channel. + */ + 'name'?: (string); +} + +/** + * ChannelRef is a reference to a Channel. + */ +export interface ChannelRef__Output { + /** + * The globally unique id for this channel. Must be a positive number. + */ + 'channel_id': (string); + /** + * An optional name associated with the channel. + */ + 'name': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTrace.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTrace.ts new file mode 100644 index 000000000..7dbc8d924 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTrace.ts @@ -0,0 +1,45 @@ +// Original file: proto/channelz.proto + +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { ChannelTraceEvent as _grpc_channelz_v1_ChannelTraceEvent, ChannelTraceEvent__Output as _grpc_channelz_v1_ChannelTraceEvent__Output } from '../../../grpc/channelz/v1/ChannelTraceEvent'; +import type { Long } from '@grpc/proto-loader'; + +/** + * ChannelTrace represents the recent events that have occurred on the channel. + */ +export interface ChannelTrace { + /** + * Number of events ever logged in this tracing object. This can differ from + * events.size() because events can be overwritten or garbage collected by + * implementations. + */ + 'num_events_logged'?: (number | string | Long); + /** + * Time that this channel was created. + */ + 'creation_timestamp'?: (_google_protobuf_Timestamp | null); + /** + * List of events that have occurred on this channel. + */ + 'events'?: (_grpc_channelz_v1_ChannelTraceEvent)[]; +} + +/** + * ChannelTrace represents the recent events that have occurred on the channel. + */ +export interface ChannelTrace__Output { + /** + * Number of events ever logged in this tracing object. This can differ from + * events.size() because events can be overwritten or garbage collected by + * implementations. + */ + 'num_events_logged': (string); + /** + * Time that this channel was created. + */ + 'creation_timestamp': (_google_protobuf_Timestamp__Output | null); + /** + * List of events that have occurred on this channel. + */ + 'events': (_grpc_channelz_v1_ChannelTraceEvent__Output)[]; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts new file mode 100644 index 000000000..24b97fbcd --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts @@ -0,0 +1,73 @@ +// Original file: proto/channelz.proto + +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { ChannelRef as _grpc_channelz_v1_ChannelRef, ChannelRef__Output as _grpc_channelz_v1_ChannelRef__Output } from '../../../grpc/channelz/v1/ChannelRef'; +import type { SubchannelRef as _grpc_channelz_v1_SubchannelRef, SubchannelRef__Output as _grpc_channelz_v1_SubchannelRef__Output } from '../../../grpc/channelz/v1/SubchannelRef'; + +// Original file: proto/channelz.proto + +/** + * The supported severity levels of trace events. + */ +export enum _grpc_channelz_v1_ChannelTraceEvent_Severity { + CT_UNKNOWN = 0, + CT_INFO = 1, + CT_WARNING = 2, + CT_ERROR = 3, +} + +/** + * A trace event is an interesting thing that happened to a channel or + * subchannel, such as creation, address resolution, subchannel creation, etc. + */ +export interface ChannelTraceEvent { + /** + * High level description of the event. + */ + 'description'?: (string); + /** + * the severity of the trace event + */ + 'severity'?: (_grpc_channelz_v1_ChannelTraceEvent_Severity | keyof typeof _grpc_channelz_v1_ChannelTraceEvent_Severity); + /** + * When this event occurred. + */ + 'timestamp'?: (_google_protobuf_Timestamp | null); + 'channel_ref'?: (_grpc_channelz_v1_ChannelRef | null); + 'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef | null); + /** + * ref of referenced channel or subchannel. + * Optional, only present if this event refers to a child object. For example, + * this field would be filled if this trace event was for a subchannel being + * created. + */ + 'child_ref'?: "channel_ref"|"subchannel_ref"; +} + +/** + * A trace event is an interesting thing that happened to a channel or + * subchannel, such as creation, address resolution, subchannel creation, etc. + */ +export interface ChannelTraceEvent__Output { + /** + * High level description of the event. + */ + 'description': (string); + /** + * the severity of the trace event + */ + 'severity': (keyof typeof _grpc_channelz_v1_ChannelTraceEvent_Severity); + /** + * When this event occurred. + */ + 'timestamp': (_google_protobuf_Timestamp__Output | null); + 'channel_ref'?: (_grpc_channelz_v1_ChannelRef__Output | null); + 'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef__Output | null); + /** + * ref of referenced channel or subchannel. + * Optional, only present if this event refers to a child object. For example, + * this field would be filled if this trace event was for a subchannel being + * created. + */ + 'child_ref': "channel_ref"|"subchannel_ref"; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/Channelz.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/Channelz.ts new file mode 100644 index 000000000..4c8c18aa7 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/Channelz.ts @@ -0,0 +1,178 @@ +// Original file: proto/channelz.proto + +import type * as grpc from '../../../../index' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { GetChannelRequest as _grpc_channelz_v1_GetChannelRequest, GetChannelRequest__Output as _grpc_channelz_v1_GetChannelRequest__Output } from '../../../grpc/channelz/v1/GetChannelRequest'; +import type { GetChannelResponse as _grpc_channelz_v1_GetChannelResponse, GetChannelResponse__Output as _grpc_channelz_v1_GetChannelResponse__Output } from '../../../grpc/channelz/v1/GetChannelResponse'; +import type { GetServerRequest as _grpc_channelz_v1_GetServerRequest, GetServerRequest__Output as _grpc_channelz_v1_GetServerRequest__Output } from '../../../grpc/channelz/v1/GetServerRequest'; +import type { GetServerResponse as _grpc_channelz_v1_GetServerResponse, GetServerResponse__Output as _grpc_channelz_v1_GetServerResponse__Output } from '../../../grpc/channelz/v1/GetServerResponse'; +import type { GetServerSocketsRequest as _grpc_channelz_v1_GetServerSocketsRequest, GetServerSocketsRequest__Output as _grpc_channelz_v1_GetServerSocketsRequest__Output } from '../../../grpc/channelz/v1/GetServerSocketsRequest'; +import type { GetServerSocketsResponse as _grpc_channelz_v1_GetServerSocketsResponse, GetServerSocketsResponse__Output as _grpc_channelz_v1_GetServerSocketsResponse__Output } from '../../../grpc/channelz/v1/GetServerSocketsResponse'; +import type { GetServersRequest as _grpc_channelz_v1_GetServersRequest, GetServersRequest__Output as _grpc_channelz_v1_GetServersRequest__Output } from '../../../grpc/channelz/v1/GetServersRequest'; +import type { GetServersResponse as _grpc_channelz_v1_GetServersResponse, GetServersResponse__Output as _grpc_channelz_v1_GetServersResponse__Output } from '../../../grpc/channelz/v1/GetServersResponse'; +import type { GetSocketRequest as _grpc_channelz_v1_GetSocketRequest, GetSocketRequest__Output as _grpc_channelz_v1_GetSocketRequest__Output } from '../../../grpc/channelz/v1/GetSocketRequest'; +import type { GetSocketResponse as _grpc_channelz_v1_GetSocketResponse, GetSocketResponse__Output as _grpc_channelz_v1_GetSocketResponse__Output } from '../../../grpc/channelz/v1/GetSocketResponse'; +import type { GetSubchannelRequest as _grpc_channelz_v1_GetSubchannelRequest, GetSubchannelRequest__Output as _grpc_channelz_v1_GetSubchannelRequest__Output } from '../../../grpc/channelz/v1/GetSubchannelRequest'; +import type { GetSubchannelResponse as _grpc_channelz_v1_GetSubchannelResponse, GetSubchannelResponse__Output as _grpc_channelz_v1_GetSubchannelResponse__Output } from '../../../grpc/channelz/v1/GetSubchannelResponse'; +import type { GetTopChannelsRequest as _grpc_channelz_v1_GetTopChannelsRequest, GetTopChannelsRequest__Output as _grpc_channelz_v1_GetTopChannelsRequest__Output } from '../../../grpc/channelz/v1/GetTopChannelsRequest'; +import type { GetTopChannelsResponse as _grpc_channelz_v1_GetTopChannelsResponse, GetTopChannelsResponse__Output as _grpc_channelz_v1_GetTopChannelsResponse__Output } from '../../../grpc/channelz/v1/GetTopChannelsResponse'; + +/** + * Channelz is a service exposed by gRPC servers that provides detailed debug + * information. + */ +export interface ChannelzClient extends grpc.Client { + /** + * Returns a single Channel, or else a NOT_FOUND code. + */ + GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetChannelResponse__Output>): grpc.ClientUnaryCall; + GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetChannelResponse__Output>): grpc.ClientUnaryCall; + GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetChannelResponse__Output>): grpc.ClientUnaryCall; + GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetChannelResponse__Output>): grpc.ClientUnaryCall; + + /** + * Returns a single Server, or else a NOT_FOUND code. + */ + GetServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + GetServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + GetServer(argument: _grpc_channelz_v1_GetServerRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + GetServer(argument: _grpc_channelz_v1_GetServerRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + /** + * Returns a single Server, or else a NOT_FOUND code. + */ + getServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + getServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + getServer(argument: _grpc_channelz_v1_GetServerRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + getServer(argument: _grpc_channelz_v1_GetServerRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerResponse__Output>): grpc.ClientUnaryCall; + + /** + * Gets all server sockets that exist in the process. + */ + GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + /** + * Gets all server sockets that exist in the process. + */ + getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetServerSocketsResponse__Output>): grpc.ClientUnaryCall; + + /** + * Gets all servers that exist in the process. + */ + GetServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + GetServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + GetServers(argument: _grpc_channelz_v1_GetServersRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + GetServers(argument: _grpc_channelz_v1_GetServersRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + /** + * Gets all servers that exist in the process. + */ + getServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + getServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + getServers(argument: _grpc_channelz_v1_GetServersRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + getServers(argument: _grpc_channelz_v1_GetServersRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetServersResponse__Output>): grpc.ClientUnaryCall; + + /** + * Returns a single Socket or else a NOT_FOUND code. + */ + GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + /** + * Returns a single Socket or else a NOT_FOUND code. + */ + getSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + getSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + getSocket(argument: _grpc_channelz_v1_GetSocketRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + getSocket(argument: _grpc_channelz_v1_GetSocketRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetSocketResponse__Output>): grpc.ClientUnaryCall; + + /** + * Returns a single Subchannel, or else a NOT_FOUND code. + */ + GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + /** + * Returns a single Subchannel, or else a NOT_FOUND code. + */ + getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetSubchannelResponse__Output>): grpc.ClientUnaryCall; + + /** + * Gets all root channels (i.e. channels the application has directly + * created). This does not include subchannels nor non-top level channels. + */ + GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + /** + * Gets all root channels (i.e. channels the application has directly + * created). This does not include subchannels nor non-top level channels. + */ + getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, callback: grpc.requestCallback<_grpc_channelz_v1_GetTopChannelsResponse__Output>): grpc.ClientUnaryCall; + +} + +/** + * Channelz is a service exposed by gRPC servers that provides detailed debug + * information. + */ +export interface ChannelzHandlers extends grpc.UntypedServiceImplementation { + /** + * Returns a single Channel, or else a NOT_FOUND code. + */ + GetChannel: grpc.handleUnaryCall<_grpc_channelz_v1_GetChannelRequest__Output, _grpc_channelz_v1_GetChannelResponse>; + + /** + * Returns a single Server, or else a NOT_FOUND code. + */ + GetServer: grpc.handleUnaryCall<_grpc_channelz_v1_GetServerRequest__Output, _grpc_channelz_v1_GetServerResponse>; + + /** + * Gets all server sockets that exist in the process. + */ + GetServerSockets: grpc.handleUnaryCall<_grpc_channelz_v1_GetServerSocketsRequest__Output, _grpc_channelz_v1_GetServerSocketsResponse>; + + /** + * Gets all servers that exist in the process. + */ + GetServers: grpc.handleUnaryCall<_grpc_channelz_v1_GetServersRequest__Output, _grpc_channelz_v1_GetServersResponse>; + + /** + * Returns a single Socket or else a NOT_FOUND code. + */ + GetSocket: grpc.handleUnaryCall<_grpc_channelz_v1_GetSocketRequest__Output, _grpc_channelz_v1_GetSocketResponse>; + + /** + * Returns a single Subchannel, or else a NOT_FOUND code. + */ + GetSubchannel: grpc.handleUnaryCall<_grpc_channelz_v1_GetSubchannelRequest__Output, _grpc_channelz_v1_GetSubchannelResponse>; + + /** + * Gets all root channels (i.e. channels the application has directly + * created). This does not include subchannels nor non-top level channels. + */ + GetTopChannels: grpc.handleUnaryCall<_grpc_channelz_v1_GetTopChannelsRequest__Output, _grpc_channelz_v1_GetTopChannelsResponse>; + +} + +export interface ChannelzDefinition extends grpc.ServiceDefinition { + GetChannel: MethodDefinition<_grpc_channelz_v1_GetChannelRequest, _grpc_channelz_v1_GetChannelResponse, _grpc_channelz_v1_GetChannelRequest__Output, _grpc_channelz_v1_GetChannelResponse__Output> + GetServer: MethodDefinition<_grpc_channelz_v1_GetServerRequest, _grpc_channelz_v1_GetServerResponse, _grpc_channelz_v1_GetServerRequest__Output, _grpc_channelz_v1_GetServerResponse__Output> + GetServerSockets: MethodDefinition<_grpc_channelz_v1_GetServerSocketsRequest, _grpc_channelz_v1_GetServerSocketsResponse, _grpc_channelz_v1_GetServerSocketsRequest__Output, _grpc_channelz_v1_GetServerSocketsResponse__Output> + GetServers: MethodDefinition<_grpc_channelz_v1_GetServersRequest, _grpc_channelz_v1_GetServersResponse, _grpc_channelz_v1_GetServersRequest__Output, _grpc_channelz_v1_GetServersResponse__Output> + GetSocket: MethodDefinition<_grpc_channelz_v1_GetSocketRequest, _grpc_channelz_v1_GetSocketResponse, _grpc_channelz_v1_GetSocketRequest__Output, _grpc_channelz_v1_GetSocketResponse__Output> + GetSubchannel: MethodDefinition<_grpc_channelz_v1_GetSubchannelRequest, _grpc_channelz_v1_GetSubchannelResponse, _grpc_channelz_v1_GetSubchannelRequest__Output, _grpc_channelz_v1_GetSubchannelResponse__Output> + GetTopChannels: MethodDefinition<_grpc_channelz_v1_GetTopChannelsRequest, _grpc_channelz_v1_GetTopChannelsResponse, _grpc_channelz_v1_GetTopChannelsRequest__Output, _grpc_channelz_v1_GetTopChannelsResponse__Output> +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetChannelRequest.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetChannelRequest.ts new file mode 100644 index 000000000..437e2d60a --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetChannelRequest.ts @@ -0,0 +1,17 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface GetChannelRequest { + /** + * channel_id is the identifier of the specific channel to get. + */ + 'channel_id'?: (number | string | Long); +} + +export interface GetChannelRequest__Output { + /** + * channel_id is the identifier of the specific channel to get. + */ + 'channel_id': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetChannelResponse.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetChannelResponse.ts new file mode 100644 index 000000000..2e967a458 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetChannelResponse.ts @@ -0,0 +1,19 @@ +// Original file: proto/channelz.proto + +import type { Channel as _grpc_channelz_v1_Channel, Channel__Output as _grpc_channelz_v1_Channel__Output } from '../../../grpc/channelz/v1/Channel'; + +export interface GetChannelResponse { + /** + * The Channel that corresponds to the requested channel_id. This field + * should be set. + */ + 'channel'?: (_grpc_channelz_v1_Channel | null); +} + +export interface GetChannelResponse__Output { + /** + * The Channel that corresponds to the requested channel_id. This field + * should be set. + */ + 'channel': (_grpc_channelz_v1_Channel__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerRequest.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerRequest.ts new file mode 100644 index 000000000..f5d4a298f --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerRequest.ts @@ -0,0 +1,17 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface GetServerRequest { + /** + * server_id is the identifier of the specific server to get. + */ + 'server_id'?: (number | string | Long); +} + +export interface GetServerRequest__Output { + /** + * server_id is the identifier of the specific server to get. + */ + 'server_id': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerResponse.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerResponse.ts new file mode 100644 index 000000000..fe0078209 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerResponse.ts @@ -0,0 +1,19 @@ +// Original file: proto/channelz.proto + +import type { Server as _grpc_channelz_v1_Server, Server__Output as _grpc_channelz_v1_Server__Output } from '../../../grpc/channelz/v1/Server'; + +export interface GetServerResponse { + /** + * The Server that corresponds to the requested server_id. This field + * should be set. + */ + 'server'?: (_grpc_channelz_v1_Server | null); +} + +export interface GetServerResponse__Output { + /** + * The Server that corresponds to the requested server_id. This field + * should be set. + */ + 'server': (_grpc_channelz_v1_Server__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerSocketsRequest.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerSocketsRequest.ts new file mode 100644 index 000000000..c33056edc --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerSocketsRequest.ts @@ -0,0 +1,39 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface GetServerSocketsRequest { + 'server_id'?: (number | string | Long); + /** + * start_socket_id indicates that only sockets at or above this id should be + * included in the results. + * To request the first page, this must be set to 0. To request + * subsequent pages, the client generates this value by adding 1 to + * the highest seen result ID. + */ + 'start_socket_id'?: (number | string | Long); + /** + * If non-zero, the server will return a page of results containing + * at most this many items. If zero, the server will choose a + * reasonable page size. Must never be negative. + */ + 'max_results'?: (number | string | Long); +} + +export interface GetServerSocketsRequest__Output { + 'server_id': (string); + /** + * start_socket_id indicates that only sockets at or above this id should be + * included in the results. + * To request the first page, this must be set to 0. To request + * subsequent pages, the client generates this value by adding 1 to + * the highest seen result ID. + */ + 'start_socket_id': (string); + /** + * If non-zero, the server will return a page of results containing + * at most this many items. If zero, the server will choose a + * reasonable page size. Must never be negative. + */ + 'max_results': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerSocketsResponse.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerSocketsResponse.ts new file mode 100644 index 000000000..112f277e3 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServerSocketsResponse.ts @@ -0,0 +1,33 @@ +// Original file: proto/channelz.proto + +import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef'; + +export interface GetServerSocketsResponse { + /** + * list of socket refs that the connection detail service knows about. Sorted in + * ascending socket_id order. + * Must contain at least 1 result, otherwise 'end' must be true. + */ + 'socket_ref'?: (_grpc_channelz_v1_SocketRef)[]; + /** + * If set, indicates that the list of sockets is the final list. Requesting + * more sockets will only return more if they are created after this RPC + * completes. + */ + 'end'?: (boolean); +} + +export interface GetServerSocketsResponse__Output { + /** + * list of socket refs that the connection detail service knows about. Sorted in + * ascending socket_id order. + * Must contain at least 1 result, otherwise 'end' must be true. + */ + 'socket_ref': (_grpc_channelz_v1_SocketRef__Output)[]; + /** + * If set, indicates that the list of sockets is the final list. Requesting + * more sockets will only return more if they are created after this RPC + * completes. + */ + 'end': (boolean); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetServersRequest.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServersRequest.ts new file mode 100644 index 000000000..2defea62d --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServersRequest.ts @@ -0,0 +1,37 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface GetServersRequest { + /** + * start_server_id indicates that only servers at or above this id should be + * included in the results. + * To request the first page, this must be set to 0. To request + * subsequent pages, the client generates this value by adding 1 to + * the highest seen result ID. + */ + 'start_server_id'?: (number | string | Long); + /** + * If non-zero, the server will return a page of results containing + * at most this many items. If zero, the server will choose a + * reasonable page size. Must never be negative. + */ + 'max_results'?: (number | string | Long); +} + +export interface GetServersRequest__Output { + /** + * start_server_id indicates that only servers at or above this id should be + * included in the results. + * To request the first page, this must be set to 0. To request + * subsequent pages, the client generates this value by adding 1 to + * the highest seen result ID. + */ + 'start_server_id': (string); + /** + * If non-zero, the server will return a page of results containing + * at most this many items. If zero, the server will choose a + * reasonable page size. Must never be negative. + */ + 'max_results': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetServersResponse.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServersResponse.ts new file mode 100644 index 000000000..b07893b8c --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetServersResponse.ts @@ -0,0 +1,33 @@ +// Original file: proto/channelz.proto + +import type { Server as _grpc_channelz_v1_Server, Server__Output as _grpc_channelz_v1_Server__Output } from '../../../grpc/channelz/v1/Server'; + +export interface GetServersResponse { + /** + * list of servers that the connection detail service knows about. Sorted in + * ascending server_id order. + * Must contain at least 1 result, otherwise 'end' must be true. + */ + 'server'?: (_grpc_channelz_v1_Server)[]; + /** + * If set, indicates that the list of servers is the final list. Requesting + * more servers will only return more if they are created after this RPC + * completes. + */ + 'end'?: (boolean); +} + +export interface GetServersResponse__Output { + /** + * list of servers that the connection detail service knows about. Sorted in + * ascending server_id order. + * Must contain at least 1 result, otherwise 'end' must be true. + */ + 'server': (_grpc_channelz_v1_Server__Output)[]; + /** + * If set, indicates that the list of servers is the final list. Requesting + * more servers will only return more if they are created after this RPC + * completes. + */ + 'end': (boolean); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetSocketRequest.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSocketRequest.ts new file mode 100644 index 000000000..b3dc1608e --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSocketRequest.ts @@ -0,0 +1,29 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface GetSocketRequest { + /** + * socket_id is the identifier of the specific socket to get. + */ + 'socket_id'?: (number | string | Long); + /** + * If true, the response will contain only high level information + * that is inexpensive to obtain. Fields thay may be omitted are + * documented. + */ + 'summary'?: (boolean); +} + +export interface GetSocketRequest__Output { + /** + * socket_id is the identifier of the specific socket to get. + */ + 'socket_id': (string); + /** + * If true, the response will contain only high level information + * that is inexpensive to obtain. Fields thay may be omitted are + * documented. + */ + 'summary': (boolean); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetSocketResponse.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSocketResponse.ts new file mode 100644 index 000000000..b6304b7f0 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSocketResponse.ts @@ -0,0 +1,19 @@ +// Original file: proto/channelz.proto + +import type { Socket as _grpc_channelz_v1_Socket, Socket__Output as _grpc_channelz_v1_Socket__Output } from '../../../grpc/channelz/v1/Socket'; + +export interface GetSocketResponse { + /** + * The Socket that corresponds to the requested socket_id. This field + * should be set. + */ + 'socket'?: (_grpc_channelz_v1_Socket | null); +} + +export interface GetSocketResponse__Output { + /** + * The Socket that corresponds to the requested socket_id. This field + * should be set. + */ + 'socket': (_grpc_channelz_v1_Socket__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetSubchannelRequest.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSubchannelRequest.ts new file mode 100644 index 000000000..f481a81d2 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSubchannelRequest.ts @@ -0,0 +1,17 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface GetSubchannelRequest { + /** + * subchannel_id is the identifier of the specific subchannel to get. + */ + 'subchannel_id'?: (number | string | Long); +} + +export interface GetSubchannelRequest__Output { + /** + * subchannel_id is the identifier of the specific subchannel to get. + */ + 'subchannel_id': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetSubchannelResponse.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSubchannelResponse.ts new file mode 100644 index 000000000..57d2bf2dc --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetSubchannelResponse.ts @@ -0,0 +1,19 @@ +// Original file: proto/channelz.proto + +import type { Subchannel as _grpc_channelz_v1_Subchannel, Subchannel__Output as _grpc_channelz_v1_Subchannel__Output } from '../../../grpc/channelz/v1/Subchannel'; + +export interface GetSubchannelResponse { + /** + * The Subchannel that corresponds to the requested subchannel_id. This + * field should be set. + */ + 'subchannel'?: (_grpc_channelz_v1_Subchannel | null); +} + +export interface GetSubchannelResponse__Output { + /** + * The Subchannel that corresponds to the requested subchannel_id. This + * field should be set. + */ + 'subchannel': (_grpc_channelz_v1_Subchannel__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetTopChannelsRequest.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetTopChannelsRequest.ts new file mode 100644 index 000000000..a122d7a85 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetTopChannelsRequest.ts @@ -0,0 +1,37 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface GetTopChannelsRequest { + /** + * start_channel_id indicates that only channels at or above this id should be + * included in the results. + * To request the first page, this should be set to 0. To request + * subsequent pages, the client generates this value by adding 1 to + * the highest seen result ID. + */ + 'start_channel_id'?: (number | string | Long); + /** + * If non-zero, the server will return a page of results containing + * at most this many items. If zero, the server will choose a + * reasonable page size. Must never be negative. + */ + 'max_results'?: (number | string | Long); +} + +export interface GetTopChannelsRequest__Output { + /** + * start_channel_id indicates that only channels at or above this id should be + * included in the results. + * To request the first page, this should be set to 0. To request + * subsequent pages, the client generates this value by adding 1 to + * the highest seen result ID. + */ + 'start_channel_id': (string); + /** + * If non-zero, the server will return a page of results containing + * at most this many items. If zero, the server will choose a + * reasonable page size. Must never be negative. + */ + 'max_results': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/GetTopChannelsResponse.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/GetTopChannelsResponse.ts new file mode 100644 index 000000000..d96e63673 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/GetTopChannelsResponse.ts @@ -0,0 +1,33 @@ +// Original file: proto/channelz.proto + +import type { Channel as _grpc_channelz_v1_Channel, Channel__Output as _grpc_channelz_v1_Channel__Output } from '../../../grpc/channelz/v1/Channel'; + +export interface GetTopChannelsResponse { + /** + * list of channels that the connection detail service knows about. Sorted in + * ascending channel_id order. + * Must contain at least 1 result, otherwise 'end' must be true. + */ + 'channel'?: (_grpc_channelz_v1_Channel)[]; + /** + * If set, indicates that the list of channels is the final list. Requesting + * more channels can only return more if they are created after this RPC + * completes. + */ + 'end'?: (boolean); +} + +export interface GetTopChannelsResponse__Output { + /** + * list of channels that the connection detail service knows about. Sorted in + * ascending channel_id order. + * Must contain at least 1 result, otherwise 'end' must be true. + */ + 'channel': (_grpc_channelz_v1_Channel__Output)[]; + /** + * If set, indicates that the list of channels is the final list. Requesting + * more channels can only return more if they are created after this RPC + * completes. + */ + 'end': (boolean); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/Security.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/Security.ts new file mode 100644 index 000000000..e555d698e --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/Security.ts @@ -0,0 +1,87 @@ +// Original file: proto/channelz.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; + +export interface _grpc_channelz_v1_Security_OtherSecurity { + /** + * The human readable version of the value. + */ + 'name'?: (string); + /** + * The actual security details message. + */ + 'value'?: (_google_protobuf_Any | null); +} + +export interface _grpc_channelz_v1_Security_OtherSecurity__Output { + /** + * The human readable version of the value. + */ + 'name': (string); + /** + * The actual security details message. + */ + 'value': (_google_protobuf_Any__Output | null); +} + +export interface _grpc_channelz_v1_Security_Tls { + /** + * The cipher suite name in the RFC 4346 format: + * https://tools.ietf.org/html/rfc4346#appendix-C + */ + 'standard_name'?: (string); + /** + * Some other way to describe the cipher suite if + * the RFC 4346 name is not available. + */ + 'other_name'?: (string); + /** + * the certificate used by this endpoint. + */ + 'local_certificate'?: (Buffer | Uint8Array | string); + /** + * the certificate used by the remote endpoint. + */ + 'remote_certificate'?: (Buffer | Uint8Array | string); + 'cipher_suite'?: "standard_name"|"other_name"; +} + +export interface _grpc_channelz_v1_Security_Tls__Output { + /** + * The cipher suite name in the RFC 4346 format: + * https://tools.ietf.org/html/rfc4346#appendix-C + */ + 'standard_name'?: (string); + /** + * Some other way to describe the cipher suite if + * the RFC 4346 name is not available. + */ + 'other_name'?: (string); + /** + * the certificate used by this endpoint. + */ + 'local_certificate': (Buffer); + /** + * the certificate used by the remote endpoint. + */ + 'remote_certificate': (Buffer); + 'cipher_suite': "standard_name"|"other_name"; +} + +/** + * Security represents details about how secure the socket is. + */ +export interface Security { + 'tls'?: (_grpc_channelz_v1_Security_Tls | null); + 'other'?: (_grpc_channelz_v1_Security_OtherSecurity | null); + 'model'?: "tls"|"other"; +} + +/** + * Security represents details about how secure the socket is. + */ +export interface Security__Output { + 'tls'?: (_grpc_channelz_v1_Security_Tls__Output | null); + 'other'?: (_grpc_channelz_v1_Security_OtherSecurity__Output | null); + 'model': "tls"|"other"; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/Server.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/Server.ts new file mode 100644 index 000000000..958343358 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/Server.ts @@ -0,0 +1,45 @@ +// Original file: proto/channelz.proto + +import type { ServerRef as _grpc_channelz_v1_ServerRef, ServerRef__Output as _grpc_channelz_v1_ServerRef__Output } from '../../../grpc/channelz/v1/ServerRef'; +import type { ServerData as _grpc_channelz_v1_ServerData, ServerData__Output as _grpc_channelz_v1_ServerData__Output } from '../../../grpc/channelz/v1/ServerData'; +import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef'; + +/** + * Server represents a single server. There may be multiple servers in a single + * program. + */ +export interface Server { + /** + * The identifier for a Server. This should be set. + */ + 'ref'?: (_grpc_channelz_v1_ServerRef | null); + /** + * The associated data of the Server. + */ + 'data'?: (_grpc_channelz_v1_ServerData | null); + /** + * The sockets that the server is listening on. There are no ordering + * guarantees. This may be absent. + */ + 'listen_socket'?: (_grpc_channelz_v1_SocketRef)[]; +} + +/** + * Server represents a single server. There may be multiple servers in a single + * program. + */ +export interface Server__Output { + /** + * The identifier for a Server. This should be set. + */ + 'ref': (_grpc_channelz_v1_ServerRef__Output | null); + /** + * The associated data of the Server. + */ + 'data': (_grpc_channelz_v1_ServerData__Output | null); + /** + * The sockets that the server is listening on. There are no ordering + * guarantees. This may be absent. + */ + 'listen_socket': (_grpc_channelz_v1_SocketRef__Output)[]; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ServerData.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ServerData.ts new file mode 100644 index 000000000..ce48e36f5 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ServerData.ts @@ -0,0 +1,57 @@ +// Original file: proto/channelz.proto + +import type { ChannelTrace as _grpc_channelz_v1_ChannelTrace, ChannelTrace__Output as _grpc_channelz_v1_ChannelTrace__Output } from '../../../grpc/channelz/v1/ChannelTrace'; +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { Long } from '@grpc/proto-loader'; + +/** + * ServerData is data for a specific Server. + */ +export interface ServerData { + /** + * A trace of recent events on the server. May be absent. + */ + 'trace'?: (_grpc_channelz_v1_ChannelTrace | null); + /** + * The number of incoming calls started on the server + */ + 'calls_started'?: (number | string | Long); + /** + * The number of incoming calls that have completed with an OK status + */ + 'calls_succeeded'?: (number | string | Long); + /** + * The number of incoming calls that have a completed with a non-OK status + */ + 'calls_failed'?: (number | string | Long); + /** + * The last time a call was started on the server. + */ + 'last_call_started_timestamp'?: (_google_protobuf_Timestamp | null); +} + +/** + * ServerData is data for a specific Server. + */ +export interface ServerData__Output { + /** + * A trace of recent events on the server. May be absent. + */ + 'trace': (_grpc_channelz_v1_ChannelTrace__Output | null); + /** + * The number of incoming calls started on the server + */ + 'calls_started': (string); + /** + * The number of incoming calls that have completed with an OK status + */ + 'calls_succeeded': (string); + /** + * The number of incoming calls that have a completed with a non-OK status + */ + 'calls_failed': (string); + /** + * The last time a call was started on the server. + */ + 'last_call_started_timestamp': (_google_protobuf_Timestamp__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ServerRef.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ServerRef.ts new file mode 100644 index 000000000..389183bdc --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ServerRef.ts @@ -0,0 +1,31 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +/** + * ServerRef is a reference to a Server. + */ +export interface ServerRef { + /** + * A globally unique identifier for this server. Must be a positive number. + */ + 'server_id'?: (number | string | Long); + /** + * An optional name associated with the server. + */ + 'name'?: (string); +} + +/** + * ServerRef is a reference to a Server. + */ +export interface ServerRef__Output { + /** + * A globally unique identifier for this server. Must be a positive number. + */ + 'server_id': (string); + /** + * An optional name associated with the server. + */ + 'name': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/Socket.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/Socket.ts new file mode 100644 index 000000000..5829afe98 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/Socket.ts @@ -0,0 +1,70 @@ +// Original file: proto/channelz.proto + +import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef'; +import type { SocketData as _grpc_channelz_v1_SocketData, SocketData__Output as _grpc_channelz_v1_SocketData__Output } from '../../../grpc/channelz/v1/SocketData'; +import type { Address as _grpc_channelz_v1_Address, Address__Output as _grpc_channelz_v1_Address__Output } from '../../../grpc/channelz/v1/Address'; +import type { Security as _grpc_channelz_v1_Security, Security__Output as _grpc_channelz_v1_Security__Output } from '../../../grpc/channelz/v1/Security'; + +/** + * Information about an actual connection. Pronounced "sock-ay". + */ +export interface Socket { + /** + * The identifier for the Socket. + */ + 'ref'?: (_grpc_channelz_v1_SocketRef | null); + /** + * Data specific to this Socket. + */ + 'data'?: (_grpc_channelz_v1_SocketData | null); + /** + * The locally bound address. + */ + 'local'?: (_grpc_channelz_v1_Address | null); + /** + * The remote bound address. May be absent. + */ + 'remote'?: (_grpc_channelz_v1_Address | null); + /** + * Security details for this socket. May be absent if not available, or + * there is no security on the socket. + */ + 'security'?: (_grpc_channelz_v1_Security | null); + /** + * Optional, represents the name of the remote endpoint, if different than + * the original target name. + */ + 'remote_name'?: (string); +} + +/** + * Information about an actual connection. Pronounced "sock-ay". + */ +export interface Socket__Output { + /** + * The identifier for the Socket. + */ + 'ref': (_grpc_channelz_v1_SocketRef__Output | null); + /** + * Data specific to this Socket. + */ + 'data': (_grpc_channelz_v1_SocketData__Output | null); + /** + * The locally bound address. + */ + 'local': (_grpc_channelz_v1_Address__Output | null); + /** + * The remote bound address. May be absent. + */ + 'remote': (_grpc_channelz_v1_Address__Output | null); + /** + * Security details for this socket. May be absent if not available, or + * there is no security on the socket. + */ + 'security': (_grpc_channelz_v1_Security__Output | null); + /** + * Optional, represents the name of the remote endpoint, if different than + * the original target name. + */ + 'remote_name': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/SocketData.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketData.ts new file mode 100644 index 000000000..c62d4d10c --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketData.ts @@ -0,0 +1,150 @@ +// Original file: proto/channelz.proto + +import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { Int64Value as _google_protobuf_Int64Value, Int64Value__Output as _google_protobuf_Int64Value__Output } from '../../../google/protobuf/Int64Value'; +import type { SocketOption as _grpc_channelz_v1_SocketOption, SocketOption__Output as _grpc_channelz_v1_SocketOption__Output } from '../../../grpc/channelz/v1/SocketOption'; +import type { Long } from '@grpc/proto-loader'; + +/** + * SocketData is data associated for a specific Socket. The fields present + * are specific to the implementation, so there may be minor differences in + * the semantics. (e.g. flow control windows) + */ +export interface SocketData { + /** + * The number of streams that have been started. + */ + 'streams_started'?: (number | string | Long); + /** + * The number of streams that have ended successfully: + * On client side, received frame with eos bit set; + * On server side, sent frame with eos bit set. + */ + 'streams_succeeded'?: (number | string | Long); + /** + * The number of streams that have ended unsuccessfully: + * On client side, ended without receiving frame with eos bit set; + * On server side, ended without sending frame with eos bit set. + */ + 'streams_failed'?: (number | string | Long); + /** + * The number of grpc messages successfully sent on this socket. + */ + 'messages_sent'?: (number | string | Long); + /** + * The number of grpc messages received on this socket. + */ + 'messages_received'?: (number | string | Long); + /** + * The number of keep alives sent. This is typically implemented with HTTP/2 + * ping messages. + */ + 'keep_alives_sent'?: (number | string | Long); + /** + * The last time a stream was created by this endpoint. Usually unset for + * servers. + */ + 'last_local_stream_created_timestamp'?: (_google_protobuf_Timestamp | null); + /** + * The last time a stream was created by the remote endpoint. Usually unset + * for clients. + */ + 'last_remote_stream_created_timestamp'?: (_google_protobuf_Timestamp | null); + /** + * The last time a message was sent by this endpoint. + */ + 'last_message_sent_timestamp'?: (_google_protobuf_Timestamp | null); + /** + * The last time a message was received by this endpoint. + */ + 'last_message_received_timestamp'?: (_google_protobuf_Timestamp | null); + /** + * The amount of window, granted to the local endpoint by the remote endpoint. + * This may be slightly out of date due to network latency. This does NOT + * include stream level or TCP level flow control info. + */ + 'local_flow_control_window'?: (_google_protobuf_Int64Value | null); + /** + * The amount of window, granted to the remote endpoint by the local endpoint. + * This may be slightly out of date due to network latency. This does NOT + * include stream level or TCP level flow control info. + */ + 'remote_flow_control_window'?: (_google_protobuf_Int64Value | null); + /** + * Socket options set on this socket. May be absent if 'summary' is set + * on GetSocketRequest. + */ + 'option'?: (_grpc_channelz_v1_SocketOption)[]; +} + +/** + * SocketData is data associated for a specific Socket. The fields present + * are specific to the implementation, so there may be minor differences in + * the semantics. (e.g. flow control windows) + */ +export interface SocketData__Output { + /** + * The number of streams that have been started. + */ + 'streams_started': (string); + /** + * The number of streams that have ended successfully: + * On client side, received frame with eos bit set; + * On server side, sent frame with eos bit set. + */ + 'streams_succeeded': (string); + /** + * The number of streams that have ended unsuccessfully: + * On client side, ended without receiving frame with eos bit set; + * On server side, ended without sending frame with eos bit set. + */ + 'streams_failed': (string); + /** + * The number of grpc messages successfully sent on this socket. + */ + 'messages_sent': (string); + /** + * The number of grpc messages received on this socket. + */ + 'messages_received': (string); + /** + * The number of keep alives sent. This is typically implemented with HTTP/2 + * ping messages. + */ + 'keep_alives_sent': (string); + /** + * The last time a stream was created by this endpoint. Usually unset for + * servers. + */ + 'last_local_stream_created_timestamp': (_google_protobuf_Timestamp__Output | null); + /** + * The last time a stream was created by the remote endpoint. Usually unset + * for clients. + */ + 'last_remote_stream_created_timestamp': (_google_protobuf_Timestamp__Output | null); + /** + * The last time a message was sent by this endpoint. + */ + 'last_message_sent_timestamp': (_google_protobuf_Timestamp__Output | null); + /** + * The last time a message was received by this endpoint. + */ + 'last_message_received_timestamp': (_google_protobuf_Timestamp__Output | null); + /** + * The amount of window, granted to the local endpoint by the remote endpoint. + * This may be slightly out of date due to network latency. This does NOT + * include stream level or TCP level flow control info. + */ + 'local_flow_control_window': (_google_protobuf_Int64Value__Output | null); + /** + * The amount of window, granted to the remote endpoint by the local endpoint. + * This may be slightly out of date due to network latency. This does NOT + * include stream level or TCP level flow control info. + */ + 'remote_flow_control_window': (_google_protobuf_Int64Value__Output | null); + /** + * Socket options set on this socket. May be absent if 'summary' is set + * on GetSocketRequest. + */ + 'option': (_grpc_channelz_v1_SocketOption__Output)[]; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOption.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOption.ts new file mode 100644 index 000000000..115b36aae --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOption.ts @@ -0,0 +1,47 @@ +// Original file: proto/channelz.proto + +import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any'; + +/** + * SocketOption represents socket options for a socket. Specifically, these + * are the options returned by getsockopt(). + */ +export interface SocketOption { + /** + * The full name of the socket option. Typically this will be the upper case + * name, such as "SO_REUSEPORT". + */ + 'name'?: (string); + /** + * The human readable value of this socket option. At least one of value or + * additional will be set. + */ + 'value'?: (string); + /** + * Additional data associated with the socket option. At least one of value + * or additional will be set. + */ + 'additional'?: (_google_protobuf_Any | null); +} + +/** + * SocketOption represents socket options for a socket. Specifically, these + * are the options returned by getsockopt(). + */ +export interface SocketOption__Output { + /** + * The full name of the socket option. Typically this will be the upper case + * name, such as "SO_REUSEPORT". + */ + 'name': (string); + /** + * The human readable value of this socket option. At least one of value or + * additional will be set. + */ + 'value': (string); + /** + * Additional data associated with the socket option. At least one of value + * or additional will be set. + */ + 'additional': (_google_protobuf_Any__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionLinger.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionLinger.ts new file mode 100644 index 000000000..d83fa3238 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionLinger.ts @@ -0,0 +1,33 @@ +// Original file: proto/channelz.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; + +/** + * For use with SocketOption's additional field. This is primarily used for + * SO_LINGER. + */ +export interface SocketOptionLinger { + /** + * active maps to `struct linger.l_onoff` + */ + 'active'?: (boolean); + /** + * duration maps to `struct linger.l_linger` + */ + 'duration'?: (_google_protobuf_Duration | null); +} + +/** + * For use with SocketOption's additional field. This is primarily used for + * SO_LINGER. + */ +export interface SocketOptionLinger__Output { + /** + * active maps to `struct linger.l_onoff` + */ + 'active': (boolean); + /** + * duration maps to `struct linger.l_linger` + */ + 'duration': (_google_protobuf_Duration__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionTcpInfo.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionTcpInfo.ts new file mode 100644 index 000000000..2f8affe80 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionTcpInfo.ts @@ -0,0 +1,74 @@ +// Original file: proto/channelz.proto + + +/** + * For use with SocketOption's additional field. Tcp info for + * SOL_TCP and TCP_INFO. + */ +export interface SocketOptionTcpInfo { + 'tcpi_state'?: (number); + 'tcpi_ca_state'?: (number); + 'tcpi_retransmits'?: (number); + 'tcpi_probes'?: (number); + 'tcpi_backoff'?: (number); + 'tcpi_options'?: (number); + 'tcpi_snd_wscale'?: (number); + 'tcpi_rcv_wscale'?: (number); + 'tcpi_rto'?: (number); + 'tcpi_ato'?: (number); + 'tcpi_snd_mss'?: (number); + 'tcpi_rcv_mss'?: (number); + 'tcpi_unacked'?: (number); + 'tcpi_sacked'?: (number); + 'tcpi_lost'?: (number); + 'tcpi_retrans'?: (number); + 'tcpi_fackets'?: (number); + 'tcpi_last_data_sent'?: (number); + 'tcpi_last_ack_sent'?: (number); + 'tcpi_last_data_recv'?: (number); + 'tcpi_last_ack_recv'?: (number); + 'tcpi_pmtu'?: (number); + 'tcpi_rcv_ssthresh'?: (number); + 'tcpi_rtt'?: (number); + 'tcpi_rttvar'?: (number); + 'tcpi_snd_ssthresh'?: (number); + 'tcpi_snd_cwnd'?: (number); + 'tcpi_advmss'?: (number); + 'tcpi_reordering'?: (number); +} + +/** + * For use with SocketOption's additional field. Tcp info for + * SOL_TCP and TCP_INFO. + */ +export interface SocketOptionTcpInfo__Output { + 'tcpi_state': (number); + 'tcpi_ca_state': (number); + 'tcpi_retransmits': (number); + 'tcpi_probes': (number); + 'tcpi_backoff': (number); + 'tcpi_options': (number); + 'tcpi_snd_wscale': (number); + 'tcpi_rcv_wscale': (number); + 'tcpi_rto': (number); + 'tcpi_ato': (number); + 'tcpi_snd_mss': (number); + 'tcpi_rcv_mss': (number); + 'tcpi_unacked': (number); + 'tcpi_sacked': (number); + 'tcpi_lost': (number); + 'tcpi_retrans': (number); + 'tcpi_fackets': (number); + 'tcpi_last_data_sent': (number); + 'tcpi_last_ack_sent': (number); + 'tcpi_last_data_recv': (number); + 'tcpi_last_ack_recv': (number); + 'tcpi_pmtu': (number); + 'tcpi_rcv_ssthresh': (number); + 'tcpi_rtt': (number); + 'tcpi_rttvar': (number); + 'tcpi_snd_ssthresh': (number); + 'tcpi_snd_cwnd': (number); + 'tcpi_advmss': (number); + 'tcpi_reordering': (number); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionTimeout.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionTimeout.ts new file mode 100644 index 000000000..185839b2c --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketOptionTimeout.ts @@ -0,0 +1,19 @@ +// Original file: proto/channelz.proto + +import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; + +/** + * For use with SocketOption's additional field. This is primarily used for + * SO_RCVTIMEO and SO_SNDTIMEO + */ +export interface SocketOptionTimeout { + 'duration'?: (_google_protobuf_Duration | null); +} + +/** + * For use with SocketOption's additional field. This is primarily used for + * SO_RCVTIMEO and SO_SNDTIMEO + */ +export interface SocketOptionTimeout__Output { + 'duration': (_google_protobuf_Duration__Output | null); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/SocketRef.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketRef.ts new file mode 100644 index 000000000..52fdb2bd3 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/SocketRef.ts @@ -0,0 +1,31 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +/** + * SocketRef is a reference to a Socket. + */ +export interface SocketRef { + /** + * The globally unique id for this socket. Must be a positive number. + */ + 'socket_id'?: (number | string | Long); + /** + * An optional name associated with the socket. + */ + 'name'?: (string); +} + +/** + * SocketRef is a reference to a Socket. + */ +export interface SocketRef__Output { + /** + * The globally unique id for this socket. Must be a positive number. + */ + 'socket_id': (string); + /** + * An optional name associated with the socket. + */ + 'name': (string); +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/Subchannel.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/Subchannel.ts new file mode 100644 index 000000000..7122fac83 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/Subchannel.ts @@ -0,0 +1,70 @@ +// Original file: proto/channelz.proto + +import type { SubchannelRef as _grpc_channelz_v1_SubchannelRef, SubchannelRef__Output as _grpc_channelz_v1_SubchannelRef__Output } from '../../../grpc/channelz/v1/SubchannelRef'; +import type { ChannelData as _grpc_channelz_v1_ChannelData, ChannelData__Output as _grpc_channelz_v1_ChannelData__Output } from '../../../grpc/channelz/v1/ChannelData'; +import type { ChannelRef as _grpc_channelz_v1_ChannelRef, ChannelRef__Output as _grpc_channelz_v1_ChannelRef__Output } from '../../../grpc/channelz/v1/ChannelRef'; +import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef'; + +/** + * Subchannel is a logical grouping of channels, subchannels, and sockets. + * A subchannel is load balanced over by it's ancestor + */ +export interface Subchannel { + /** + * The identifier for this channel. + */ + 'ref'?: (_grpc_channelz_v1_SubchannelRef | null); + /** + * Data specific to this channel. + */ + 'data'?: (_grpc_channelz_v1_ChannelData | null); + /** + * There are no ordering guarantees on the order of channel refs. + * There may not be cycles in the ref graph. + * A channel ref may be present in more than one channel or subchannel. + */ + 'channel_ref'?: (_grpc_channelz_v1_ChannelRef)[]; + /** + * At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + * There are no ordering guarantees on the order of subchannel refs. + * There may not be cycles in the ref graph. + * A sub channel ref may be present in more than one channel or subchannel. + */ + 'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef)[]; + /** + * There are no ordering guarantees on the order of sockets. + */ + 'socket_ref'?: (_grpc_channelz_v1_SocketRef)[]; +} + +/** + * Subchannel is a logical grouping of channels, subchannels, and sockets. + * A subchannel is load balanced over by it's ancestor + */ +export interface Subchannel__Output { + /** + * The identifier for this channel. + */ + 'ref': (_grpc_channelz_v1_SubchannelRef__Output | null); + /** + * Data specific to this channel. + */ + 'data': (_grpc_channelz_v1_ChannelData__Output | null); + /** + * There are no ordering guarantees on the order of channel refs. + * There may not be cycles in the ref graph. + * A channel ref may be present in more than one channel or subchannel. + */ + 'channel_ref': (_grpc_channelz_v1_ChannelRef__Output)[]; + /** + * At most one of 'channel_ref+subchannel_ref' and 'socket' is set. + * There are no ordering guarantees on the order of subchannel refs. + * There may not be cycles in the ref graph. + * A sub channel ref may be present in more than one channel or subchannel. + */ + 'subchannel_ref': (_grpc_channelz_v1_SubchannelRef__Output)[]; + /** + * There are no ordering guarantees on the order of sockets. + */ + 'socket_ref': (_grpc_channelz_v1_SocketRef__Output)[]; +} diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/SubchannelRef.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/SubchannelRef.ts new file mode 100644 index 000000000..b6911c773 --- /dev/null +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/SubchannelRef.ts @@ -0,0 +1,31 @@ +// Original file: proto/channelz.proto + +import type { Long } from '@grpc/proto-loader'; + +/** + * SubchannelRef is a reference to a Subchannel. + */ +export interface SubchannelRef { + /** + * The globally unique id for this subchannel. Must be a positive number. + */ + 'subchannel_id'?: (number | string | Long); + /** + * An optional name associated with the subchannel. + */ + 'name'?: (string); +} + +/** + * SubchannelRef is a reference to a Subchannel. + */ +export interface SubchannelRef__Output { + /** + * The globally unique id for this subchannel. Must be a positive number. + */ + 'subchannel_id': (string); + /** + * An optional name associated with the subchannel. + */ + 'name': (string); +} diff --git a/packages/grpc-js/src/http_proxy.ts b/packages/grpc-js/src/http_proxy.ts index 6e62eddd0..6faa1976d 100644 --- a/packages/grpc-js/src/http_proxy.ts +++ b/packages/grpc-js/src/http_proxy.ts @@ -26,7 +26,7 @@ import { SubchannelAddress, isTcpSubchannelAddress, subchannelAddressToString, -} from './subchannel'; +} from './subchannel-address'; import { ChannelOptions } from './channel-options'; import { GrpcUri, parseUri, splitHostPort, uriToString } from './uri-parser'; import { URL } from 'url'; @@ -93,7 +93,7 @@ function getProxyInfo(): ProxyInfo { port = '80'; } const result: ProxyInfo = { - address: `${hostname}:${port}` + address: `${hostname}:${port}`, }; if (userCred) { result.creds = userCred; @@ -136,6 +136,9 @@ export function mapProxyName( if ((options['grpc.enable_http_proxy'] ?? 1) === 0) { return noProxyResult; } + if (target.scheme === 'unix') { + return noProxyResult; + } const proxyInfo = getProxyInfo(); if (!proxyInfo.address) { return noProxyResult; @@ -147,7 +150,9 @@ export function mapProxyName( const serverHost = hostPort.host; for (const host of getNoProxyHostList()) { if (host === serverHost) { - trace('Not using proxy for target in no_proxy list: ' + uriToString(target)); + trace( + 'Not using proxy for target in no_proxy list: ' + uriToString(target) + ); return noProxyResult; } } @@ -188,6 +193,9 @@ export function getProxiedConnection( method: 'CONNECT', path: parsedTarget.path, }; + const headers: http.OutgoingHttpHeaders = { + Host: parsedTarget.path, + }; // Connect to the subchannel address as a proxy if (isTcpSubchannelAddress(address)) { options.host = address.host; @@ -196,14 +204,13 @@ export function getProxiedConnection( options.socketPath = address.path; } if ('grpc.http_connect_creds' in channelOptions) { - options.headers = { - 'Proxy-Authorization': - 'Basic ' + - Buffer.from( - channelOptions['grpc.http_connect_creds'] as string - ).toString('base64'), - }; + headers['Proxy-Authorization'] = + 'Basic ' + + Buffer.from( + channelOptions['grpc.http_connect_creds'] as string + ).toString('base64'); } + options.headers = headers const proxyAddressString = subchannelAddressToString(address); trace('Using proxy ' + proxyAddressString + ' to connect to ' + options.path); return new Promise((resolve, reject) => { @@ -226,7 +233,7 @@ export function getProxiedConnection( const targetPath = getDefaultAuthority(parsedTarget); const hostPort = splitHostPort(targetPath); const remoteHost = hostPort?.host ?? targetPath; - + const cts = tls.connect( { host: remoteHost, diff --git a/packages/grpc-js/src/index.ts b/packages/grpc-js/src/index.ts index 05288855c..51f394785 100644 --- a/packages/grpc-js/src/index.ts +++ b/packages/grpc-js/src/index.ts @@ -23,8 +23,10 @@ import { ServiceError, } from './call'; import { CallCredentials, OAuth2Client } from './call-credentials'; -import { Deadline, StatusObject } from './call-stream'; -import { Channel, ConnectivityState, ChannelImplementation } from './channel'; +import { StatusObject } from './call-interface'; +import { Channel, ChannelImplementation } from './channel'; +import { CompressionAlgorithms } from './compression-algorithms'; +import { ConnectivityState } from './connectivity-state'; import { ChannelCredentials } from './channel-credentials'; import { CallOptions, @@ -41,10 +43,12 @@ import { loadPackageDefinition, makeClientConstructor, MethodDefinition, + ProtobufTypeDefinition, Serialize, + ServiceClientConstructor, ServiceDefinition, } from './make-client'; -import { Metadata, MetadataValue } from './metadata'; +import { Metadata, MetadataOptions, MetadataValue } from './metadata'; import { Server, UntypedHandleCall, @@ -62,6 +66,7 @@ import { ServerReadableStream, ServerWritableStream, ServerDuplexStream, + ServerErrorResponse, } from './server-call'; export { OAuth2Client }; @@ -104,6 +109,7 @@ export const credentials = { // from channel-credentials.ts createInsecure: ChannelCredentials.createInsecure, createSsl: ChannelCredentials.createSsl, + createFromSecureContext: ChannelCredentials.createFromSecureContext, // from call-credentials.ts createFromMetadataGenerator: CallCredentials.createFromMetadataGenerator, @@ -113,7 +119,7 @@ export const credentials = { /**** Metadata ****/ -export { Metadata, MetadataValue }; +export { Metadata, MetadataOptions, MetadataValue }; /**** Constants ****/ @@ -122,6 +128,7 @@ export { Status as status, ConnectivityState as connectivityState, Propagate as propagate, + CompressionAlgorithms as compressionAlgorithms // TODO: Other constants as well }; @@ -173,6 +180,7 @@ export { ServerReadableStream, ServerWritableStream, ServerDuplexStream, + ServerErrorResponse, ServiceDefinition, UntypedHandleCall, UntypedServiceImplementation, @@ -180,7 +188,12 @@ export { /**** Server ****/ -export { handleBidiStreamingCall, handleServerStreamingCall, handleUnaryCall, handleClientStreamingCall }; +export { + handleBidiStreamingCall, + handleServerStreamingCall, + handleUnaryCall, + handleClientStreamingCall, +}; /* eslint-disable @typescript-eslint/no-explicit-any */ export type Call = @@ -194,13 +207,13 @@ export type Call = /* eslint-disable @typescript-eslint/no-explicit-any */ -export const loadObject = (value: any, options: any) => { +export const loadObject = (value: any, options: any): never => { throw new Error( 'Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead' ); }; -export const load = (filename: any, format: any, options: any) => { +export const load = (filename: any, format: any, options: any): never => { throw new Error( 'Not available in this library. Use @grpc/proto-loader and loadPackageDefinition instead' ); @@ -224,7 +237,7 @@ export const getClientChannel = (client: Client) => { export { StatusBuilder }; -export { Listener } from './call-stream'; +export { Listener, InterceptingListener } from './call-interface'; export { Requester, @@ -235,22 +248,45 @@ export { InterceptorProvider, InterceptingCall, InterceptorConfigurationError, + NextCall } from './client-interceptors'; -export { GrpcObject } from './make-client'; +export { + GrpcObject, + ServiceClientConstructor, + ProtobufTypeDefinition +} from './make-client'; export { ChannelOptions } from './channel-options'; +export { + getChannelzServiceDefinition, + getChannelzHandlers +} from './channelz'; + +export { addAdminServicesToServer } from './admin'; + import * as experimental from './experimental'; export { experimental }; -import * as resolver from './resolver'; -import * as load_balancer from './load-balancer'; +import * as resolver_dns from './resolver-dns'; +import * as resolver_uds from './resolver-uds'; +import * as resolver_ip from './resolver-ip'; +import * as load_balancer_pick_first from './load-balancer-pick-first'; +import * as load_balancer_round_robin from './load-balancer-round-robin'; +import * as load_balancer_outlier_detection from './load-balancer-outlier-detection'; +import * as channelz from './channelz'; +import { Deadline } from './deadline'; const clientVersion = require('../../package.json').version; (() => { logging.trace(LogVerbosity.DEBUG, 'index', 'Loading @grpc/grpc-js version ' + clientVersion); - resolver.registerAll(); - load_balancer.registerAll(); + resolver_dns.setup(); + resolver_uds.setup(); + resolver_ip.setup(); + load_balancer_pick_first.setup(); + load_balancer_round_robin.setup(); + load_balancer_outlier_detection.setup(); + channelz.setup(); })(); diff --git a/packages/grpc-js/src/internal-channel.ts b/packages/grpc-js/src/internal-channel.ts new file mode 100644 index 000000000..14038bd3f --- /dev/null +++ b/packages/grpc-js/src/internal-channel.ts @@ -0,0 +1,630 @@ +/* + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { ChannelCredentials } from './channel-credentials'; +import { ChannelOptions } from './channel-options'; +import { ResolvingLoadBalancer } from './resolving-load-balancer'; +import { SubchannelPool, getSubchannelPool } from './subchannel-pool'; +import { ChannelControlHelper } from './load-balancer'; +import { UnavailablePicker, Picker, PickResultType } from './picker'; +import { Metadata } from './metadata'; +import { Status, LogVerbosity, Propagate } from './constants'; +import { FilterStackFactory } from './filter-stack'; +import { CompressionFilterFactory } from './compression-filter'; +import { + CallConfig, + ConfigSelector, + getDefaultAuthority, + mapUriDefaultScheme, +} from './resolver'; +import { trace, log } from './logging'; +import { SubchannelAddress } from './subchannel-address'; +import { MaxMessageSizeFilterFactory } from './max-message-size-filter'; +import { mapProxyName } from './http_proxy'; +import { GrpcUri, parseUri, splitHostPort, uriToString } from './uri-parser'; +import { ServerSurfaceCall } from './server-call'; +import { Filter } from './filter'; + +import { ConnectivityState } from './connectivity-state'; +import { ChannelInfo, ChannelRef, ChannelzCallTracker, ChannelzChildrenTracker, ChannelzTrace, registerChannelzChannel, SubchannelRef, unregisterChannelzRef } from './channelz'; +import { Subchannel } from './subchannel'; +import { LoadBalancingCall } from './load-balancing-call'; +import { CallCredentials } from './call-credentials'; +import { Call, CallStreamOptions, InterceptingListener, MessageContext, StatusObject } from './call-interface'; +import { SubchannelCall } from './subchannel-call'; +import { Deadline, deadlineToString, getDeadlineTimeoutString } from './deadline'; +import { ResolvingCall } from './resolving-call'; +import { getNextCallNumber } from './call-number'; +import { restrictControlPlaneStatusCode } from './control-plane-status'; +import { MessageBufferTracker, RetryingCall, RetryThrottler } from './retrying-call'; +import { BaseSubchannelWrapper, ConnectivityStateListener, SubchannelInterface } from './subchannel-interface'; + +/** + * See https://nodejs.org/api/timers.html#timers_setinterval_callback_delay_args + */ +const MAX_TIMEOUT_TIME = 2147483647; + +interface ConnectivityStateWatcher { + currentState: ConnectivityState; + timer: NodeJS.Timeout | null; + callback: (error?: Error) => void; +} + +interface NoneConfigResult { + type: 'NONE'; +} + +interface SuccessConfigResult { + type: 'SUCCESS'; + config: CallConfig; +} + +interface ErrorConfigResult { + type: 'ERROR'; + error: StatusObject; +} + +type GetConfigResult = NoneConfigResult | SuccessConfigResult | ErrorConfigResult; + +const RETRY_THROTTLER_MAP: Map = new Map(); + +const DEFAULT_RETRY_BUFFER_SIZE_BYTES = 1<<24; // 16 MB +const DEFAULT_PER_RPC_RETRY_BUFFER_SIZE_BYTES = 1<<20; // 1 MB + +class ChannelSubchannelWrapper extends BaseSubchannelWrapper implements SubchannelInterface { + private refCount = 0; + private subchannelStateListener: ConnectivityStateListener; + constructor(childSubchannel: SubchannelInterface, private channel: InternalChannel) { + super(childSubchannel); + this.subchannelStateListener = (subchannel, previousState, newState, keepaliveTime) => { + channel.throttleKeepalive(keepaliveTime); + }; + childSubchannel.addConnectivityStateListener(this.subchannelStateListener); + } + + ref(): void { + this.child.ref(); + this.refCount += 1; + } + + unref(): void { + this.child.unref(); + this.refCount -= 1; + if (this.refCount <= 0) { + this.child.removeConnectivityStateListener(this.subchannelStateListener); + this.channel.removeWrappedSubchannel(this); + } + } +} + +export class InternalChannel { + + private resolvingLoadBalancer: ResolvingLoadBalancer; + private subchannelPool: SubchannelPool; + private connectivityState: ConnectivityState = ConnectivityState.IDLE; + private currentPicker: Picker = new UnavailablePicker(); + /** + * Calls queued up to get a call config. Should only be populated before the + * first time the resolver returns a result, which includes the ConfigSelector. + */ + private configSelectionQueue: ResolvingCall[] = []; + private pickQueue: LoadBalancingCall[] = []; + private connectivityStateWatchers: ConnectivityStateWatcher[] = []; + private defaultAuthority: string; + private filterStackFactory: FilterStackFactory; + private target: GrpcUri; + /** + * This timer does not do anything on its own. Its purpose is to hold the + * event loop open while there are any pending calls for the channel that + * have not yet been assigned to specific subchannels. In other words, + * the invariant is that callRefTimer is reffed if and only if pickQueue + * is non-empty. + */ + private callRefTimer: NodeJS.Timer; + private configSelector: ConfigSelector | null = null; + /** + * This is the error from the name resolver if it failed most recently. It + * is only used to end calls that start while there is no config selector + * and the name resolver is in backoff, so it should be nulled if + * configSelector becomes set or the channel state becomes anything other + * than TRANSIENT_FAILURE. + */ + private currentResolutionError: StatusObject | null = null; + private retryBufferTracker: MessageBufferTracker; + private keepaliveTime: number; + private wrappedSubchannels: Set = new Set(); + + // Channelz info + private readonly channelzEnabled: boolean = true; + private originalTarget: string; + private channelzRef: ChannelRef; + private channelzTrace: ChannelzTrace; + private callTracker = new ChannelzCallTracker(); + private childrenTracker = new ChannelzChildrenTracker(); + + constructor( + target: string, + private readonly credentials: ChannelCredentials, + private readonly options: ChannelOptions + ) { + if (typeof target !== 'string') { + throw new TypeError('Channel target must be a string'); + } + if (!(credentials instanceof ChannelCredentials)) { + throw new TypeError( + 'Channel credentials must be a ChannelCredentials object' + ); + } + if (options) { + if (typeof options !== 'object') { + throw new TypeError('Channel options must be an object'); + } + } + this.originalTarget = target; + const originalTargetUri = parseUri(target); + if (originalTargetUri === null) { + throw new Error(`Could not parse target name "${target}"`); + } + /* This ensures that the target has a scheme that is registered with the + * resolver */ + const defaultSchemeMapResult = mapUriDefaultScheme(originalTargetUri); + if (defaultSchemeMapResult === null) { + throw new Error( + `Could not find a default scheme for target name "${target}"` + ); + } + + this.callRefTimer = setInterval(() => {}, MAX_TIMEOUT_TIME); + this.callRefTimer.unref?.(); + + if (this.options['grpc.enable_channelz'] === 0) { + this.channelzEnabled = false; + } + + this.channelzTrace = new ChannelzTrace(); + this.channelzRef = registerChannelzChannel(target, () => this.getChannelzInfo(), this.channelzEnabled); + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Channel created'); + } + + if (this.options['grpc.default_authority']) { + this.defaultAuthority = this.options['grpc.default_authority'] as string; + } else { + this.defaultAuthority = getDefaultAuthority(defaultSchemeMapResult); + } + const proxyMapResult = mapProxyName(defaultSchemeMapResult, options); + this.target = proxyMapResult.target; + this.options = Object.assign({}, this.options, proxyMapResult.extraOptions); + + /* The global boolean parameter to getSubchannelPool has the inverse meaning to what + * the grpc.use_local_subchannel_pool channel option means. */ + this.subchannelPool = getSubchannelPool( + (options['grpc.use_local_subchannel_pool'] ?? 0) === 0 + ); + this.retryBufferTracker = new MessageBufferTracker( + options['grpc.retry_buffer_size'] ?? DEFAULT_RETRY_BUFFER_SIZE_BYTES, + options['grpc.per_rpc_retry_buffer_size'] ?? DEFAULT_PER_RPC_RETRY_BUFFER_SIZE_BYTES + ); + this.keepaliveTime = options['grpc.keepalive_time_ms'] ?? -1; + const channelControlHelper: ChannelControlHelper = { + createSubchannel: ( + subchannelAddress: SubchannelAddress, + subchannelArgs: ChannelOptions + ) => { + const subchannel = this.subchannelPool.getOrCreateSubchannel( + this.target, + subchannelAddress, + Object.assign({}, this.options, subchannelArgs), + this.credentials + ); + subchannel.throttleKeepalive(this.keepaliveTime); + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Created subchannel or used existing subchannel', subchannel.getChannelzRef()); + } + const wrappedSubchannel = new ChannelSubchannelWrapper(subchannel, this); + this.wrappedSubchannels.add(wrappedSubchannel); + return wrappedSubchannel; + }, + updateState: (connectivityState: ConnectivityState, picker: Picker) => { + this.currentPicker = picker; + const queueCopy = this.pickQueue.slice(); + this.pickQueue = []; + this.callRefTimerUnref(); + for (const call of queueCopy) { + call.doPick(); + } + this.updateState(connectivityState); + }, + requestReresolution: () => { + // This should never be called. + throw new Error( + 'Resolving load balancer should never call requestReresolution' + ); + }, + addChannelzChild: (child: ChannelRef | SubchannelRef) => { + if (this.channelzEnabled) { + this.childrenTracker.refChild(child); + } + }, + removeChannelzChild: (child: ChannelRef | SubchannelRef) => { + if (this.channelzEnabled) { + this.childrenTracker.unrefChild(child); + } + } + }; + this.resolvingLoadBalancer = new ResolvingLoadBalancer( + this.target, + channelControlHelper, + options, + (serviceConfig, configSelector) => { + if (serviceConfig.retryThrottling) { + RETRY_THROTTLER_MAP.set(this.getTarget(), new RetryThrottler(serviceConfig.retryThrottling.maxTokens, serviceConfig.retryThrottling.tokenRatio, RETRY_THROTTLER_MAP.get(this.getTarget()))); + } else { + RETRY_THROTTLER_MAP.delete(this.getTarget()); + } + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Address resolution succeeded'); + } + this.configSelector = configSelector; + this.currentResolutionError = null; + /* We process the queue asynchronously to ensure that the corresponding + * load balancer update has completed. */ + process.nextTick(() => { + const localQueue = this.configSelectionQueue; + this.configSelectionQueue = []; + this.callRefTimerUnref(); + for (const call of localQueue) { + call.getConfig(); + } + this.configSelectionQueue = []; + }); + + }, + (status) => { + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_WARNING', 'Address resolution failed with code ' + status.code + ' and details "' + status.details + '"'); + } + if (this.configSelectionQueue.length > 0) { + this.trace('Name resolution failed with calls queued for config selection'); + } + if (this.configSelector === null) { + this.currentResolutionError = {...restrictControlPlaneStatusCode(status.code, status.details), metadata: status.metadata}; + } + const localQueue = this.configSelectionQueue; + this.configSelectionQueue = []; + this.callRefTimerUnref(); + for (const call of localQueue) { + call.reportResolverError(status); + } + } + ); + this.filterStackFactory = new FilterStackFactory([ + new MaxMessageSizeFilterFactory(this.options), + new CompressionFilterFactory(this, this.options), + ]); + this.trace('Channel constructed with options ' + JSON.stringify(options, undefined, 2)); + const error = new Error(); + trace(LogVerbosity.DEBUG, 'channel_stacktrace', '(' + this.channelzRef.id + ') ' + 'Channel constructed \n' + error.stack?.substring(error.stack.indexOf('\n')+1)); + } + + private getChannelzInfo(): ChannelInfo { + return { + target: this.originalTarget, + state: this.connectivityState, + trace: this.channelzTrace, + callTracker: this.callTracker, + children: this.childrenTracker.getChildLists() + }; + } + + private trace(text: string, verbosityOverride?: LogVerbosity) { + trace(verbosityOverride ?? LogVerbosity.DEBUG, 'channel', '(' + this.channelzRef.id + ') ' + uriToString(this.target) + ' ' + text); + } + + private callRefTimerRef() { + // If the hasRef function does not exist, always run the code + if (!this.callRefTimer.hasRef?.()) { + this.trace( + 'callRefTimer.ref | configSelectionQueue.length=' + + this.configSelectionQueue.length + + ' pickQueue.length=' + + this.pickQueue.length + ); + this.callRefTimer.ref?.(); + } + } + + private callRefTimerUnref() { + // If the hasRef function does not exist, always run the code + if (!this.callRefTimer.hasRef || this.callRefTimer.hasRef()) { + this.trace( + 'callRefTimer.unref | configSelectionQueue.length=' + + this.configSelectionQueue.length + + ' pickQueue.length=' + + this.pickQueue.length + ); + this.callRefTimer.unref?.(); + } + } + + private removeConnectivityStateWatcher( + watcherObject: ConnectivityStateWatcher + ) { + const watcherIndex = this.connectivityStateWatchers.findIndex( + (value) => value === watcherObject + ); + if (watcherIndex >= 0) { + this.connectivityStateWatchers.splice(watcherIndex, 1); + } + } + + private updateState(newState: ConnectivityState): void { + trace( + LogVerbosity.DEBUG, + 'connectivity_state', + '(' + this.channelzRef.id + ') ' + + uriToString(this.target) + + ' ' + + ConnectivityState[this.connectivityState] + + ' -> ' + + ConnectivityState[newState] + ); + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[newState]); + } + this.connectivityState = newState; + const watchersCopy = this.connectivityStateWatchers.slice(); + for (const watcherObject of watchersCopy) { + if (newState !== watcherObject.currentState) { + if (watcherObject.timer) { + clearTimeout(watcherObject.timer); + } + this.removeConnectivityStateWatcher(watcherObject); + watcherObject.callback(); + } + } + if (newState !== ConnectivityState.TRANSIENT_FAILURE) { + this.currentResolutionError = null; + } + } + + throttleKeepalive(newKeepaliveTime: number) { + if (newKeepaliveTime > this.keepaliveTime) { + this.keepaliveTime = newKeepaliveTime; + for (const wrappedSubchannel of this.wrappedSubchannels) { + wrappedSubchannel.throttleKeepalive(newKeepaliveTime); + } + } + } + + removeWrappedSubchannel(wrappedSubchannel: ChannelSubchannelWrapper) { + this.wrappedSubchannels.delete(wrappedSubchannel); + } + + doPick(metadata: Metadata, extraPickInfo: {[key: string]: string}) { + return this.currentPicker.pick({metadata: metadata, extraPickInfo: extraPickInfo}); + } + + queueCallForPick(call: LoadBalancingCall) { + this.pickQueue.push(call); + this.callRefTimerRef(); + } + + getConfig(method: string, metadata: Metadata): GetConfigResult { + this.resolvingLoadBalancer.exitIdle(); + if (this.configSelector) { + return { + type: 'SUCCESS', + config: this.configSelector(method, metadata) + }; + } else { + if (this.currentResolutionError) { + return { + type: 'ERROR', + error: this.currentResolutionError + } + } else { + return { + type: 'NONE' + } + } + } + } + + queueCallForConfig(call: ResolvingCall) { + this.configSelectionQueue.push(call); + this.callRefTimerRef(); + } + + createLoadBalancingCall( + callConfig: CallConfig, + method: string, + host: string, + credentials: CallCredentials, + deadline: Deadline + ): LoadBalancingCall { + const callNumber = getNextCallNumber(); + this.trace( + 'createLoadBalancingCall [' + + callNumber + + '] method="' + + method + + '"' + ); + return new LoadBalancingCall(this, callConfig, method, host, credentials, deadline, callNumber); + } + + createRetryingCall( + callConfig: CallConfig, + method: string, + host: string, + credentials: CallCredentials, + deadline: Deadline + ): RetryingCall { + const callNumber = getNextCallNumber(); + this.trace( + 'createRetryingCall [' + + callNumber + + '] method="' + + method + + '"' + ); + return new RetryingCall(this, callConfig, method, host, credentials, deadline, callNumber, this.retryBufferTracker, RETRY_THROTTLER_MAP.get(this.getTarget())) + } + + createInnerCall( + callConfig: CallConfig, + method: string, + host: string, + credentials: CallCredentials, + deadline: Deadline + ): Call { + // Create a RetryingCall if retries are enabled + if (this.options['grpc.enable_retries'] === 0) { + return this.createLoadBalancingCall(callConfig, method, host, credentials, deadline); + } else { + return this.createRetryingCall(callConfig, method, host, credentials, deadline); + } + } + + createResolvingCall( + method: string, + deadline: Deadline, + host: string | null | undefined, + parentCall: ServerSurfaceCall | null, + propagateFlags: number | null | undefined + ): ResolvingCall { + const callNumber = getNextCallNumber(); + this.trace( + 'createResolvingCall [' + + callNumber + + '] method="' + + method + + '", deadline=' + + deadlineToString(deadline) + ); + const finalOptions: CallStreamOptions = { + deadline: deadline, + flags: propagateFlags ?? Propagate.DEFAULTS, + host: host ?? this.defaultAuthority, + parentCall: parentCall, + }; + + const call = new ResolvingCall(this, method, finalOptions, this.filterStackFactory.clone(), this.credentials._getCallCredentials(), callNumber); + + if (this.channelzEnabled) { + this.callTracker.addCallStarted(); + call.addStatusWatcher(status => { + if (status.code === Status.OK) { + this.callTracker.addCallSucceeded(); + } else { + this.callTracker.addCallFailed(); + } + }); + } + return call; + + } + + close() { + this.resolvingLoadBalancer.destroy(); + this.updateState(ConnectivityState.SHUTDOWN); + clearInterval(this.callRefTimer); + if (this.channelzEnabled) { + unregisterChannelzRef(this.channelzRef); + } + + this.subchannelPool.unrefUnusedSubchannels(); + } + + getTarget() { + return uriToString(this.target); + } + + getConnectivityState(tryToConnect: boolean) { + const connectivityState = this.connectivityState; + if (tryToConnect) { + this.resolvingLoadBalancer.exitIdle(); + } + return connectivityState; + } + + watchConnectivityState( + currentState: ConnectivityState, + deadline: Date | number, + callback: (error?: Error) => void + ): void { + if (this.connectivityState === ConnectivityState.SHUTDOWN) { + throw new Error('Channel has been shut down'); + } + let timer = null; + if (deadline !== Infinity) { + const deadlineDate: Date = + deadline instanceof Date ? deadline : new Date(deadline); + const now = new Date(); + if (deadline === -Infinity || deadlineDate <= now) { + process.nextTick( + callback, + new Error('Deadline passed without connectivity state change') + ); + return; + } + timer = setTimeout(() => { + this.removeConnectivityStateWatcher(watcherObject); + callback( + new Error('Deadline passed without connectivity state change') + ); + }, deadlineDate.getTime() - now.getTime()); + } + const watcherObject = { + currentState, + callback, + timer, + }; + this.connectivityStateWatchers.push(watcherObject); + } + + /** + * Get the channelz reference object for this channel. The returned value is + * garbage if channelz is disabled for this channel. + * @returns + */ + getChannelzRef() { + return this.channelzRef; + } + + createCall( + method: string, + deadline: Deadline, + host: string | null | undefined, + parentCall: ServerSurfaceCall | null, + propagateFlags: number | null | undefined + ): Call { + if (typeof method !== 'string') { + throw new TypeError('Channel#createCall: method must be a string'); + } + if (!(typeof deadline === 'number' || deadline instanceof Date)) { + throw new TypeError( + 'Channel#createCall: deadline must be a number or Date' + ); + } + if (this.connectivityState === ConnectivityState.SHUTDOWN) { + throw new Error('Channel has been shut down'); + } + return this.createResolvingCall(method, deadline, host, parentCall, propagateFlags); + } +} diff --git a/packages/grpc-js/src/load-balancer-child-handler.ts b/packages/grpc-js/src/load-balancer-child-handler.ts index 337174c0d..64b341810 100644 --- a/packages/grpc-js/src/load-balancer-child-handler.ts +++ b/packages/grpc-js/src/load-balancer-child-handler.ts @@ -18,13 +18,15 @@ import { LoadBalancer, ChannelControlHelper, + LoadBalancingConfig, createLoadBalancer, - LoadBalancingConfig } from './load-balancer'; -import { SubchannelAddress, Subchannel } from './subchannel'; +import { SubchannelAddress } from './subchannel-address'; import { ChannelOptions } from './channel-options'; -import { ConnectivityState } from './channel'; +import { ConnectivityState } from './connectivity-state'; import { Picker } from './picker'; +import { ChannelRef, SubchannelRef } from './channelz'; +import { SubchannelInterface } from './subchannel-interface'; const TYPE_NAME = 'child_load_balancer_helper'; @@ -38,7 +40,7 @@ export class ChildLoadBalancerHandler implements LoadBalancer { createSubchannel( subchannelAddress: SubchannelAddress, subchannelArgs: ChannelOptions - ): Subchannel { + ): SubchannelInterface { return this.parent.channelControlHelper.createSubchannel( subchannelAddress, subchannelArgs @@ -46,7 +48,7 @@ export class ChildLoadBalancerHandler implements LoadBalancer { } updateState(connectivityState: ConnectivityState, picker: Picker): void { if (this.calledByPendingChild()) { - if (connectivityState !== ConnectivityState.READY) { + if (connectivityState === ConnectivityState.CONNECTING) { return; } this.parent.currentChild?.destroy(); @@ -66,6 +68,13 @@ export class ChildLoadBalancerHandler implements LoadBalancer { setChild(newChild: LoadBalancer) { this.child = newChild; } + addChannelzChild(child: ChannelRef | SubchannelRef) { + this.parent.channelControlHelper.addChannelzChild(child); + } + removeChannelzChild(child: ChannelRef | SubchannelRef) { + this.parent.channelControlHelper.removeChannelzChild(child); + } + private calledByPendingChild(): boolean { return this.child === this.parent.pendingChild; } @@ -116,9 +125,9 @@ export class ChildLoadBalancerHandler implements LoadBalancer { } exitIdle(): void { if (this.currentChild) { - this.currentChild.resetBackoff(); + this.currentChild.exitIdle(); if (this.pendingChild) { - this.pendingChild.resetBackoff(); + this.pendingChild.exitIdle(); } } } diff --git a/packages/grpc-js/src/load-balancer-outlier-detection.ts b/packages/grpc-js/src/load-balancer-outlier-detection.ts new file mode 100644 index 000000000..ce8668f18 --- /dev/null +++ b/packages/grpc-js/src/load-balancer-outlier-detection.ts @@ -0,0 +1,662 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { ChannelOptions } from "./channel-options"; +import { ConnectivityState } from "./connectivity-state"; +import { LogVerbosity, Status } from "./constants"; +import { durationToMs, isDuration, msToDuration } from "./duration"; +import { ChannelControlHelper, createChildChannelControlHelper, registerLoadBalancerType } from "./experimental"; +import { BaseFilter, Filter, FilterFactory } from "./filter"; +import { getFirstUsableConfig, LoadBalancer, LoadBalancingConfig, validateLoadBalancingConfig } from "./load-balancer"; +import { ChildLoadBalancerHandler } from "./load-balancer-child-handler"; +import { PickArgs, Picker, PickResult, PickResultType, QueuePicker, UnavailablePicker } from "./picker"; +import { Subchannel } from "./subchannel"; +import { SubchannelAddress, subchannelAddressToString } from "./subchannel-address"; +import { BaseSubchannelWrapper, ConnectivityStateListener, SubchannelInterface } from "./subchannel-interface"; +import * as logging from './logging'; + +const TRACER_NAME = 'outlier_detection'; + +function trace(text: string): void { + logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text); +} + +const TYPE_NAME = 'outlier_detection'; + +const OUTLIER_DETECTION_ENABLED = (process.env.GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION ?? 'true') === 'true'; + +export interface SuccessRateEjectionConfig { + readonly stdev_factor: number; + readonly enforcement_percentage: number; + readonly minimum_hosts: number; + readonly request_volume: number; +} + +export interface FailurePercentageEjectionConfig { + readonly threshold: number; + readonly enforcement_percentage: number; + readonly minimum_hosts: number; + readonly request_volume: number; +} + +const defaultSuccessRateEjectionConfig: SuccessRateEjectionConfig = { + stdev_factor: 1900, + enforcement_percentage: 100, + minimum_hosts: 5, + request_volume: 100 +}; + +const defaultFailurePercentageEjectionConfig: FailurePercentageEjectionConfig = { + threshold: 85, + enforcement_percentage: 100, + minimum_hosts: 5, + request_volume: 50 +} + +type TypeofValues = 'object' | 'boolean' | 'function' | 'number' | 'string' | 'undefined'; + +function validateFieldType(obj: any, fieldName: string, expectedType: TypeofValues, objectName?: string) { + if (fieldName in obj && typeof obj[fieldName] !== expectedType) { + const fullFieldName = objectName ? `${objectName}.${fieldName}` : fieldName; + throw new Error(`outlier detection config ${fullFieldName} parse error: expected ${expectedType}, got ${typeof obj[fieldName]}`); + } +} + +function validatePositiveDuration(obj: any, fieldName: string, objectName?: string) { + const fullFieldName = objectName ? `${objectName}.${fieldName}` : fieldName; + if (fieldName in obj) { + if (!isDuration(obj[fieldName])) { + throw new Error(`outlier detection config ${fullFieldName} parse error: expected Duration, got ${typeof obj[fieldName]}`); + } + if (!(obj[fieldName].seconds >= 0 && obj[fieldName].seconds <= 315_576_000_000 && obj[fieldName].nanos >= 0 && obj[fieldName].nanos <= 999_999_999)) { + throw new Error(`outlier detection config ${fullFieldName} parse error: values out of range for non-negative Duaration`); + } + } +} + +function validatePercentage(obj: any, fieldName: string, objectName?: string) { + const fullFieldName = objectName ? `${objectName}.${fieldName}` : fieldName; + validateFieldType(obj, fieldName, 'number', objectName); + if (fieldName in obj && !(obj[fieldName] >= 0 && obj[fieldName] <= 100)) { + throw new Error(`outlier detection config ${fullFieldName} parse error: value out of range for percentage (0-100)`); + } +} + +export class OutlierDetectionLoadBalancingConfig implements LoadBalancingConfig { + private readonly intervalMs: number; + private readonly baseEjectionTimeMs: number; + private readonly maxEjectionTimeMs: number; + private readonly maxEjectionPercent: number; + private readonly successRateEjection: SuccessRateEjectionConfig | null; + private readonly failurePercentageEjection: FailurePercentageEjectionConfig | null; + + constructor( + intervalMs: number | null, + baseEjectionTimeMs: number | null, + maxEjectionTimeMs: number | null, + maxEjectionPercent: number | null, + successRateEjection: Partial | null, + failurePercentageEjection: Partial | null, + private readonly childPolicy: LoadBalancingConfig[] + ) { + if (childPolicy.length > 0 && childPolicy[0].getLoadBalancerName() === 'pick_first') { + throw new Error('outlier_detection LB policy cannot have a pick_first child policy'); + } + this.intervalMs = intervalMs ?? 10_000; + this.baseEjectionTimeMs = baseEjectionTimeMs ?? 30_000; + this.maxEjectionTimeMs = maxEjectionTimeMs ?? 300_000; + this.maxEjectionPercent = maxEjectionPercent ?? 10; + this.successRateEjection = successRateEjection ? {...defaultSuccessRateEjectionConfig, ...successRateEjection} : null; + this.failurePercentageEjection = failurePercentageEjection ? {...defaultFailurePercentageEjectionConfig, ...failurePercentageEjection}: null; + } + getLoadBalancerName(): string { + return TYPE_NAME; + } + toJsonObject(): object { + return { + interval: msToDuration(this.intervalMs), + base_ejection_time: msToDuration(this.baseEjectionTimeMs), + max_ejection_time: msToDuration(this.maxEjectionTimeMs), + max_ejection_percent: this.maxEjectionPercent, + success_rate_ejection: this.successRateEjection, + failure_percentage_ejection: this.failurePercentageEjection, + child_policy: this.childPolicy.map(policy => policy.toJsonObject()) + }; + } + + getIntervalMs(): number { + return this.intervalMs; + } + getBaseEjectionTimeMs(): number { + return this.baseEjectionTimeMs; + } + getMaxEjectionTimeMs(): number { + return this.maxEjectionTimeMs; + } + getMaxEjectionPercent(): number { + return this.maxEjectionPercent; + } + getSuccessRateEjectionConfig(): SuccessRateEjectionConfig | null { + return this.successRateEjection; + } + getFailurePercentageEjectionConfig(): FailurePercentageEjectionConfig | null { + return this.failurePercentageEjection; + } + getChildPolicy(): LoadBalancingConfig[] { + return this.childPolicy; + } + + copyWithChildPolicy(childPolicy: LoadBalancingConfig[]): OutlierDetectionLoadBalancingConfig { + return new OutlierDetectionLoadBalancingConfig(this.intervalMs, this.baseEjectionTimeMs, this.maxEjectionTimeMs, this.maxEjectionPercent, this.successRateEjection, this.failurePercentageEjection, childPolicy); + } + + static createFromJson(obj: any): OutlierDetectionLoadBalancingConfig { + validatePositiveDuration(obj, 'interval'); + validatePositiveDuration(obj, 'base_ejection_time'); + validatePositiveDuration(obj, 'max_ejection_time'); + validatePercentage(obj, 'max_ejection_percent'); + if ('success_rate_ejection' in obj) { + if (typeof obj.success_rate_ejection !== 'object') { + throw new Error('outlier detection config success_rate_ejection must be an object'); + } + validateFieldType(obj.success_rate_ejection, 'stdev_factor', 'number', 'success_rate_ejection'); + validatePercentage(obj.success_rate_ejection, 'enforcement_percentage', 'success_rate_ejection'); + validateFieldType(obj.success_rate_ejection, 'minimum_hosts', 'number', 'success_rate_ejection'); + validateFieldType(obj.success_rate_ejection, 'request_volume', 'number', 'success_rate_ejection'); + } + if ('failure_percentage_ejection' in obj) { + if (typeof obj.failure_percentage_ejection !== 'object') { + throw new Error('outlier detection config failure_percentage_ejection must be an object'); + } + validatePercentage(obj.failure_percentage_ejection, 'threshold', 'failure_percentage_ejection'); + validatePercentage(obj.failure_percentage_ejection, 'enforcement_percentage', 'failure_percentage_ejection'); + validateFieldType(obj.failure_percentage_ejection, 'minimum_hosts', 'number', 'failure_percentage_ejection'); + validateFieldType(obj.failure_percentage_ejection, 'request_volume', 'number', 'failure_percentage_ejection'); + } + + return new OutlierDetectionLoadBalancingConfig( + obj.interval ? durationToMs(obj.interval) : null, + obj.base_ejection_time ? durationToMs(obj.base_ejection_time) : null, + obj.max_ejection_time ? durationToMs(obj.max_ejection_time) : null, + obj.max_ejection_percent ?? null, + obj.success_rate_ejection, + obj.failure_percentage_ejection, + obj.child_policy.map(validateLoadBalancingConfig) + ); + } +} + +class OutlierDetectionSubchannelWrapper extends BaseSubchannelWrapper implements SubchannelInterface { + private childSubchannelState: ConnectivityState; + private stateListeners: ConnectivityStateListener[] = []; + private ejected: boolean = false; + private refCount: number = 0; + constructor(childSubchannel: SubchannelInterface, private mapEntry?: MapEntry) { + super(childSubchannel); + this.childSubchannelState = childSubchannel.getConnectivityState(); + childSubchannel.addConnectivityStateListener((subchannel, previousState, newState, keepaliveTime) => { + this.childSubchannelState = newState; + if (!this.ejected) { + for (const listener of this.stateListeners) { + listener(this, previousState, newState, keepaliveTime); + } + } + }); + } + + getConnectivityState(): ConnectivityState { + if (this.ejected) { + return ConnectivityState.TRANSIENT_FAILURE; + } else { + return this.childSubchannelState; + } + } + + /** + * Add a listener function to be called whenever the wrapper's + * connectivity state changes. + * @param listener + */ + addConnectivityStateListener(listener: ConnectivityStateListener) { + this.stateListeners.push(listener); + } + + /** + * Remove a listener previously added with `addConnectivityStateListener` + * @param listener A reference to a function previously passed to + * `addConnectivityStateListener` + */ + removeConnectivityStateListener(listener: ConnectivityStateListener) { + const listenerIndex = this.stateListeners.indexOf(listener); + if (listenerIndex > -1) { + this.stateListeners.splice(listenerIndex, 1); + } + } + + ref() { + this.child.ref(); + this.refCount += 1; + } + + unref() { + this.child.unref(); + this.refCount -= 1; + if (this.refCount <= 0) { + if (this.mapEntry) { + const index = this.mapEntry.subchannelWrappers.indexOf(this); + if (index >= 0) { + this.mapEntry.subchannelWrappers.splice(index, 1); + } + } + } + } + + eject() { + this.ejected = true; + for (const listener of this.stateListeners) { + listener(this, this.childSubchannelState, ConnectivityState.TRANSIENT_FAILURE, -1); + } + } + + uneject() { + this.ejected = false; + for (const listener of this.stateListeners) { + listener(this, ConnectivityState.TRANSIENT_FAILURE, this.childSubchannelState, -1); + } + } + + getMapEntry(): MapEntry | undefined { + return this.mapEntry; + } + + getWrappedSubchannel(): SubchannelInterface { + return this.child; + } +} + +interface CallCountBucket { + success: number; + failure: number; +} + +function createEmptyBucket(): CallCountBucket { + return { + success: 0, + failure: 0 + } +} + +class CallCounter { + private activeBucket: CallCountBucket = createEmptyBucket(); + private inactiveBucket: CallCountBucket = createEmptyBucket(); + addSuccess() { + this.activeBucket.success += 1; + } + addFailure() { + this.activeBucket.failure += 1; + } + switchBuckets() { + this.inactiveBucket = this.activeBucket; + this.activeBucket = createEmptyBucket(); + } + getLastSuccesses() { + return this.inactiveBucket.success; + } + getLastFailures() { + return this.inactiveBucket.failure; + } +} + +interface MapEntry { + counter: CallCounter; + currentEjectionTimestamp: Date | null; + ejectionTimeMultiplier: number; + subchannelWrappers: OutlierDetectionSubchannelWrapper[]; +} + +class OutlierDetectionPicker implements Picker { + constructor(private wrappedPicker: Picker, private countCalls: boolean) {} + pick(pickArgs: PickArgs): PickResult { + const wrappedPick = this.wrappedPicker.pick(pickArgs); + if (wrappedPick.pickResultType === PickResultType.COMPLETE) { + const subchannelWrapper = wrappedPick.subchannel as OutlierDetectionSubchannelWrapper; + const mapEntry = subchannelWrapper.getMapEntry(); + if (mapEntry) { + let onCallEnded = wrappedPick.onCallEnded; + if (this.countCalls) { + onCallEnded = statusCode => { + if (statusCode === Status.OK) { + mapEntry.counter.addSuccess(); + } else { + mapEntry.counter.addFailure(); + } + wrappedPick.onCallEnded?.(statusCode); + }; + } + return { + ...wrappedPick, + subchannel: subchannelWrapper.getWrappedSubchannel(), + onCallEnded: onCallEnded + }; + } else { + return { + ...wrappedPick, + subchannel: subchannelWrapper.getWrappedSubchannel() + } + } + } else { + return wrappedPick; + } + } + +} + +export class OutlierDetectionLoadBalancer implements LoadBalancer { + private childBalancer: ChildLoadBalancerHandler; + private addressMap: Map = new Map(); + private latestConfig: OutlierDetectionLoadBalancingConfig | null = null; + private ejectionTimer: NodeJS.Timer; + private timerStartTime: Date | null = null; + + constructor(channelControlHelper: ChannelControlHelper) { + this.childBalancer = new ChildLoadBalancerHandler(createChildChannelControlHelper(channelControlHelper, { + createSubchannel: (subchannelAddress: SubchannelAddress, subchannelArgs: ChannelOptions) => { + const originalSubchannel = channelControlHelper.createSubchannel(subchannelAddress, subchannelArgs); + const mapEntry = this.addressMap.get(subchannelAddressToString(subchannelAddress)); + const subchannelWrapper = new OutlierDetectionSubchannelWrapper(originalSubchannel, mapEntry); + if (mapEntry?.currentEjectionTimestamp !== null) { + // If the address is ejected, propagate that to the new subchannel wrapper + subchannelWrapper.eject(); + } + mapEntry?.subchannelWrappers.push(subchannelWrapper); + return subchannelWrapper; + }, + updateState: (connectivityState: ConnectivityState, picker: Picker) => { + if (connectivityState === ConnectivityState.READY) { + channelControlHelper.updateState(connectivityState, new OutlierDetectionPicker(picker, this.isCountingEnabled())); + } else { + channelControlHelper.updateState(connectivityState, picker); + } + } + })); + this.ejectionTimer = setInterval(() => {}, 0); + clearInterval(this.ejectionTimer); + } + + private isCountingEnabled(): boolean { + return this.latestConfig !== null && + (this.latestConfig.getSuccessRateEjectionConfig() !== null || + this.latestConfig.getFailurePercentageEjectionConfig() !== null); + } + + private getCurrentEjectionPercent() { + let ejectionCount = 0; + for (const mapEntry of this.addressMap.values()) { + if (mapEntry.currentEjectionTimestamp !== null) { + ejectionCount += 1; + } + } + return (ejectionCount * 100) / this.addressMap.size; + } + + private runSuccessRateCheck(ejectionTimestamp: Date) { + if (!this.latestConfig) { + return; + } + const successRateConfig = this.latestConfig.getSuccessRateEjectionConfig(); + if (!successRateConfig) { + return; + } + trace('Running success rate check'); + // Step 1 + const targetRequestVolume = successRateConfig.request_volume; + let addresesWithTargetVolume = 0; + const successRates: number[] = [] + for (const [address, mapEntry] of this.addressMap) { + const successes = mapEntry.counter.getLastSuccesses(); + const failures = mapEntry.counter.getLastFailures(); + trace('Stats for ' + address + ': successes=' + successes + ' failures=' + failures + ' targetRequestVolume=' + targetRequestVolume); + if (successes + failures >= targetRequestVolume) { + addresesWithTargetVolume += 1; + successRates.push(successes/(successes + failures)); + } + } + trace('Found ' + addresesWithTargetVolume + ' success rate candidates; currentEjectionPercent=' + this.getCurrentEjectionPercent() + ' successRates=[' + successRates + ']'); + if (addresesWithTargetVolume < successRateConfig.minimum_hosts) { + return; + } + + // Step 2 + const successRateMean = successRates.reduce((a, b) => a + b) / successRates.length; + let successRateDeviationSum = 0; + for (const rate of successRates) { + const deviation = rate - successRateMean; + successRateDeviationSum += deviation * deviation; + } + const successRateVariance = successRateDeviationSum / successRates.length; + const successRateStdev = Math.sqrt(successRateVariance); + const ejectionThreshold = successRateMean - successRateStdev * (successRateConfig.stdev_factor / 1000); + trace('stdev=' + successRateStdev + ' ejectionThreshold=' + ejectionThreshold); + + // Step 3 + for (const [address, mapEntry] of this.addressMap.entries()) { + // Step 3.i + if (this.getCurrentEjectionPercent() >= this.latestConfig.getMaxEjectionPercent()) { + break; + } + // Step 3.ii + const successes = mapEntry.counter.getLastSuccesses(); + const failures = mapEntry.counter.getLastFailures(); + if (successes + failures < targetRequestVolume) { + continue; + } + // Step 3.iii + const successRate = successes / (successes + failures); + trace('Checking candidate ' + address + ' successRate=' + successRate); + if (successRate < ejectionThreshold) { + const randomNumber = Math.random() * 100; + trace('Candidate ' + address + ' randomNumber=' + randomNumber + ' enforcement_percentage=' + successRateConfig.enforcement_percentage); + if (randomNumber < successRateConfig.enforcement_percentage) { + trace('Ejecting candidate ' + address); + this.eject(mapEntry, ejectionTimestamp); + } + } + } + } + + private runFailurePercentageCheck(ejectionTimestamp: Date) { + if (!this.latestConfig) { + return; + } + const failurePercentageConfig = this.latestConfig.getFailurePercentageEjectionConfig() + if (!failurePercentageConfig) { + return; + } + trace('Running failure percentage check. threshold=' + failurePercentageConfig.threshold + ' request volume threshold=' + failurePercentageConfig.request_volume); + // Step 1 + let addressesWithTargetVolume = 0; + for (const mapEntry of this.addressMap.values()) { + const successes = mapEntry.counter.getLastSuccesses(); + const failures = mapEntry.counter.getLastFailures(); + if (successes + failures >= failurePercentageConfig.request_volume) { + addressesWithTargetVolume += 1; + } + } + if (addressesWithTargetVolume < failurePercentageConfig.minimum_hosts) { + return; + } + + // Step 2 + for (const [address, mapEntry] of this.addressMap.entries()) { + // Step 2.i + if (this.getCurrentEjectionPercent() >= this.latestConfig.getMaxEjectionPercent()) { + break; + } + // Step 2.ii + const successes = mapEntry.counter.getLastSuccesses(); + const failures = mapEntry.counter.getLastFailures(); + trace('Candidate successes=' + successes + ' failures=' + failures); + if (successes + failures < failurePercentageConfig.request_volume) { + continue; + } + // Step 2.iii + const failurePercentage = (failures * 100) / (failures + successes); + if (failurePercentage > failurePercentageConfig.threshold) { + const randomNumber = Math.random() * 100; + trace('Candidate ' + address + ' randomNumber=' + randomNumber + ' enforcement_percentage=' + failurePercentageConfig.enforcement_percentage); + if (randomNumber < failurePercentageConfig.enforcement_percentage) { + trace('Ejecting candidate ' + address); + this.eject(mapEntry, ejectionTimestamp); + } + } + } + } + + private eject(mapEntry: MapEntry, ejectionTimestamp: Date) { + mapEntry.currentEjectionTimestamp = new Date(); + mapEntry.ejectionTimeMultiplier += 1; + for (const subchannelWrapper of mapEntry.subchannelWrappers) { + subchannelWrapper.eject(); + } + } + + private uneject(mapEntry: MapEntry) { + mapEntry.currentEjectionTimestamp = null; + for (const subchannelWrapper of mapEntry.subchannelWrappers) { + subchannelWrapper.uneject(); + } + } + + private switchAllBuckets() { + for (const mapEntry of this.addressMap.values()) { + mapEntry.counter.switchBuckets(); + } + } + + private startTimer(delayMs: number) { + this.ejectionTimer = setTimeout(() => this.runChecks(), delayMs); + this.ejectionTimer.unref?.(); + } + + private runChecks() { + const ejectionTimestamp = new Date(); + trace('Ejection timer running'); + + this.switchAllBuckets(); + + if (!this.latestConfig) { + return; + } + this.timerStartTime = ejectionTimestamp; + this.startTimer(this.latestConfig.getIntervalMs()); + + this.runSuccessRateCheck(ejectionTimestamp); + this.runFailurePercentageCheck(ejectionTimestamp); + + for (const [address, mapEntry] of this.addressMap.entries()) { + if (mapEntry.currentEjectionTimestamp === null) { + if (mapEntry.ejectionTimeMultiplier > 0) { + mapEntry.ejectionTimeMultiplier -= 1; + } + } else { + const baseEjectionTimeMs = this.latestConfig.getBaseEjectionTimeMs(); + const maxEjectionTimeMs = this.latestConfig.getMaxEjectionTimeMs(); + const returnTime = new Date(mapEntry.currentEjectionTimestamp.getTime()); + returnTime.setMilliseconds(returnTime.getMilliseconds() + Math.min(baseEjectionTimeMs * mapEntry.ejectionTimeMultiplier, Math.max(baseEjectionTimeMs, maxEjectionTimeMs))); + if (returnTime < new Date()) { + trace('Unejecting ' + address); + this.uneject(mapEntry); + } + } + } + } + + updateAddressList(addressList: SubchannelAddress[], lbConfig: LoadBalancingConfig, attributes: { [key: string]: unknown; }): void { + if (!(lbConfig instanceof OutlierDetectionLoadBalancingConfig)) { + return; + } + const subchannelAddresses = new Set(); + for (const address of addressList) { + subchannelAddresses.add(subchannelAddressToString(address)); + } + for (const address of subchannelAddresses) { + if (!this.addressMap.has(address)) { + trace('Adding map entry for ' + address); + this.addressMap.set(address, { + counter: new CallCounter(), + currentEjectionTimestamp: null, + ejectionTimeMultiplier: 0, + subchannelWrappers: [] + }); + } + } + for (const key of this.addressMap.keys()) { + if (!subchannelAddresses.has(key)) { + trace('Removing map entry for ' + key); + this.addressMap.delete(key); + } + } + const childPolicy: LoadBalancingConfig = getFirstUsableConfig( + lbConfig.getChildPolicy(), + true + ); + this.childBalancer.updateAddressList(addressList, childPolicy, attributes); + + if (lbConfig.getSuccessRateEjectionConfig() || lbConfig.getFailurePercentageEjectionConfig()) { + if (this.timerStartTime) { + trace('Previous timer existed. Replacing timer'); + clearTimeout(this.ejectionTimer); + const remainingDelay = lbConfig.getIntervalMs() - ((new Date()).getTime() - this.timerStartTime.getTime()); + this.startTimer(remainingDelay); + } else { + trace('Starting new timer'); + this.timerStartTime = new Date(); + this.startTimer(lbConfig.getIntervalMs()); + this.switchAllBuckets(); + } + } else { + trace('Counting disabled. Cancelling timer.'); + this.timerStartTime = null; + clearTimeout(this.ejectionTimer); + for (const mapEntry of this.addressMap.values()) { + this.uneject(mapEntry); + mapEntry.ejectionTimeMultiplier = 0; + } + } + + this.latestConfig = lbConfig; + } + exitIdle(): void { + this.childBalancer.exitIdle(); + } + resetBackoff(): void { + this.childBalancer.resetBackoff(); + } + destroy(): void { + clearTimeout(this.ejectionTimer); + this.childBalancer.destroy(); + } + getTypeName(): string { + return TYPE_NAME; + } +} + +export function setup() { + if (OUTLIER_DETECTION_ENABLED) { + registerLoadBalancerType(TYPE_NAME, OutlierDetectionLoadBalancer, OutlierDetectionLoadBalancingConfig); + } +} diff --git a/packages/grpc-js/src/load-balancer-pick-first.ts b/packages/grpc-js/src/load-balancer-pick-first.ts index 31dc17847..41d21a2ea 100644 --- a/packages/grpc-js/src/load-balancer-pick-first.ts +++ b/packages/grpc-js/src/load-balancer-pick-first.ts @@ -18,10 +18,11 @@ import { LoadBalancer, ChannelControlHelper, + LoadBalancingConfig, + registerDefaultLoadBalancerType, registerLoadBalancerType, - LoadBalancingConfig } from './load-balancer'; -import { ConnectivityState } from './channel'; +import { ConnectivityState } from './connectivity-state'; import { QueuePicker, Picker, @@ -31,13 +32,13 @@ import { UnavailablePicker, } from './picker'; import { - Subchannel, - ConnectivityStateListener, SubchannelAddress, + subchannelAddressEqual, subchannelAddressToString, -} from './subchannel'; +} from './subchannel-address'; import * as logging from './logging'; import { LogVerbosity } from './constants'; +import { SubchannelInterface, ConnectivityStateListener } from './subchannel-interface'; const TRACER_NAME = 'pick_first'; @@ -62,10 +63,11 @@ export class PickFirstLoadBalancingConfig implements LoadBalancingConfig { toJsonObject(): object { return { - [TYPE_NAME]: {} + [TYPE_NAME]: {}, }; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any static createFromJson(obj: any) { return new PickFirstLoadBalancingConfig(); } @@ -76,15 +78,15 @@ export class PickFirstLoadBalancingConfig implements LoadBalancingConfig { * picked subchannel. */ class PickFirstPicker implements Picker { - constructor(private subchannel: Subchannel) {} + constructor(private subchannel: SubchannelInterface) {} pick(pickArgs: PickArgs): CompletePickResult { return { pickResultType: PickResultType.COMPLETE, subchannel: this.subchannel, status: null, - extraFilterFactory: null, onCallStarted: null, + onCallEnded: null }; } } @@ -106,7 +108,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { * The list of subchannels this load balancer is currently attempting to * connect to. */ - private subchannels: Subchannel[] = []; + private subchannels: SubchannelInterface[] = []; /** * The current connectivity state of the load balancer. */ @@ -123,7 +125,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { * and only if the load balancer's current state is READY. In that case, * the subchannel's current state is also READY. */ - private currentPick: Subchannel | null = null; + private currentPick: SubchannelInterface | null = null; /** * Listener callback attached to each subchannel in the `subchannels` list * while establishing a connection. @@ -156,7 +158,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { [ConnectivityState.TRANSIENT_FAILURE]: 0, }; this.subchannelStateListener = ( - subchannel: Subchannel, + subchannel: SubchannelInterface, previousState: ConnectivityState, newState: ConnectivityState ) => { @@ -167,7 +169,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { * connecting to the next one instead of waiting for the connection * delay timer. */ if ( - subchannel === this.subchannels[this.currentSubchannelIndex] && + subchannel.getRealSubchannel() === this.subchannels[this.currentSubchannelIndex].getRealSubchannel() && newState === ConnectivityState.TRANSIENT_FAILURE ) { this.startNextSubchannelConnecting(); @@ -183,8 +185,10 @@ export class PickFirstLoadBalancer implements LoadBalancer { ) { /* If all of the subchannels are IDLE we should go back to a * basic IDLE state where there is no subchannel list to avoid - * holding unused resources */ - this.resetSubchannelList(); + * holding unused resources. We do not reset triedAllSubchannels + * because that is a reminder to request reresolution the next time + * this LB policy needs to connect. */ + this.resetSubchannelList(false); this.updateState(ConnectivityState.IDLE, new QueuePicker(this)); return; } @@ -218,7 +222,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { } }; this.pickedSubchannelStateListener = ( - subchannel: Subchannel, + subchannel: SubchannelInterface, previousState: ConnectivityState, newState: ConnectivityState ) => { @@ -228,6 +232,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { subchannel.removeConnectivityStateListener( this.pickedSubchannelStateListener ); + this.channelControlHelper.removeChannelzChild(subchannel.getChannelzRef()); if (this.subchannels.length > 0) { if (this.triedAllSubchannels) { let newLBState: ConnectivityState; @@ -308,7 +313,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { }, CONNECTION_DELAY_INTERVAL_MS); } - private pickSubchannel(subchannel: Subchannel) { + private pickSubchannel(subchannel: SubchannelInterface) { trace('Pick subchannel with address ' + subchannel.getAddress()); if (this.currentPick !== null) { this.currentPick.unref(); @@ -317,11 +322,12 @@ export class PickFirstLoadBalancer implements LoadBalancer { ); } this.currentPick = subchannel; - this.updateState(ConnectivityState.READY, new PickFirstPicker(subchannel)); subchannel.addConnectivityStateListener(this.pickedSubchannelStateListener); subchannel.ref(); + this.channelControlHelper.addChannelzChild(subchannel.getChannelzRef()); this.resetSubchannelList(); clearTimeout(this.connectionDelayTimeout); + this.updateState(ConnectivityState.READY, new PickFirstPicker(subchannel)); } private updateState(newState: ConnectivityState, picker: Picker) { @@ -334,10 +340,11 @@ export class PickFirstLoadBalancer implements LoadBalancer { this.channelControlHelper.updateState(newState, picker); } - private resetSubchannelList() { + private resetSubchannelList(resetTriedAllSubchannels = true) { for (const subchannel of this.subchannels) { subchannel.removeConnectivityStateListener(this.subchannelStateListener); subchannel.unref(); + this.channelControlHelper.removeChannelzChild(subchannel.getChannelzRef()); } this.currentSubchannelIndex = 0; this.subchannelStateCounts = { @@ -348,7 +355,9 @@ export class PickFirstLoadBalancer implements LoadBalancer { [ConnectivityState.TRANSIENT_FAILURE]: 0, }; this.subchannels = []; - this.triedAllSubchannels = false; + if (resetTriedAllSubchannels) { + this.triedAllSubchannels = false; + } } /** @@ -368,6 +377,7 @@ export class PickFirstLoadBalancer implements LoadBalancer { ); for (const subchannel of this.subchannels) { subchannel.ref(); + this.channelControlHelper.addChannelzChild(subchannel.getChannelzRef()); } for (const subchannel of this.subchannels) { subchannel.addConnectivityStateListener(this.subchannelStateListener); @@ -410,8 +420,9 @@ export class PickFirstLoadBalancer implements LoadBalancer { * address list is different from the existing one */ if ( this.subchannels.length === 0 || + this.latestAddressList.length !== addressList.length || !this.latestAddressList.every( - (value, index) => addressList[index] === value + (value, index) => addressList[index] && subchannelAddressEqual(addressList[index], value) ) ) { this.latestAddressList = addressList; @@ -420,6 +431,12 @@ export class PickFirstLoadBalancer implements LoadBalancer { } exitIdle() { + if ( + this.currentState === ConnectivityState.IDLE || + this.triedAllSubchannels + ) { + this.channelControlHelper.requestReresolution(); + } for (const subchannel of this.subchannels) { subchannel.startConnecting(); } @@ -428,12 +445,6 @@ export class PickFirstLoadBalancer implements LoadBalancer { this.connectToAddressList(); } } - if ( - this.currentState === ConnectivityState.IDLE || - this.triedAllSubchannels - ) { - this.channelControlHelper.requestReresolution(); - } } resetBackoff() { @@ -444,10 +455,15 @@ export class PickFirstLoadBalancer implements LoadBalancer { destroy() { this.resetSubchannelList(); if (this.currentPick !== null) { - this.currentPick.unref(); - this.currentPick.removeConnectivityStateListener( + /* Unref can cause a state change, which can cause a change in the value + * of this.currentPick, so we hold a local reference to make sure that + * does not impact this function. */ + const currentPick = this.currentPick; + currentPick.unref(); + currentPick.removeConnectivityStateListener( this.pickedSubchannelStateListener ); + this.channelControlHelper.removeChannelzChild(currentPick.getChannelzRef()); } } @@ -457,5 +473,10 @@ export class PickFirstLoadBalancer implements LoadBalancer { } export function setup(): void { - registerLoadBalancerType(TYPE_NAME, PickFirstLoadBalancer, PickFirstLoadBalancingConfig); + registerLoadBalancerType( + TYPE_NAME, + PickFirstLoadBalancer, + PickFirstLoadBalancingConfig + ); + registerDefaultLoadBalancerType(TYPE_NAME); } diff --git a/packages/grpc-js/src/load-balancer-round-robin.ts b/packages/grpc-js/src/load-balancer-round-robin.ts index daba45941..91c10b238 100644 --- a/packages/grpc-js/src/load-balancer-round-robin.ts +++ b/packages/grpc-js/src/load-balancer-round-robin.ts @@ -18,10 +18,10 @@ import { LoadBalancer, ChannelControlHelper, + LoadBalancingConfig, registerLoadBalancerType, - LoadBalancingConfig } from './load-balancer'; -import { ConnectivityState } from './channel'; +import { ConnectivityState } from './connectivity-state'; import { QueuePicker, Picker, @@ -31,13 +31,12 @@ import { UnavailablePicker, } from './picker'; import { - Subchannel, - ConnectivityStateListener, SubchannelAddress, subchannelAddressToString, -} from './subchannel'; +} from './subchannel-address'; import * as logging from './logging'; import { LogVerbosity } from './constants'; +import { ConnectivityStateListener, SubchannelInterface } from './subchannel-interface'; const TRACER_NAME = 'round_robin'; @@ -56,10 +55,11 @@ class RoundRobinLoadBalancingConfig implements LoadBalancingConfig { toJsonObject(): object { return { - [TYPE_NAME]: {} + [TYPE_NAME]: {}, }; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any static createFromJson(obj: any) { return new RoundRobinLoadBalancingConfig(); } @@ -67,7 +67,7 @@ class RoundRobinLoadBalancingConfig implements LoadBalancingConfig { class RoundRobinPicker implements Picker { constructor( - private readonly subchannelList: Subchannel[], + private readonly subchannelList: SubchannelInterface[], private nextIndex = 0 ) {} @@ -78,8 +78,8 @@ class RoundRobinPicker implements Picker { pickResultType: PickResultType.COMPLETE, subchannel: pickedSubchannel, status: null, - extraFilterFactory: null, onCallStarted: null, + onCallEnded: null }; } @@ -88,7 +88,7 @@ class RoundRobinPicker implements Picker { * balancer implementation to preserve this part of the picker state if * possible when a subchannel connects or disconnects. */ - peekNextSubchannel(): Subchannel { + peekNextSubchannel(): SubchannelInterface { return this.subchannelList[this.nextIndex]; } } @@ -102,7 +102,7 @@ interface ConnectivityStateCounts { } export class RoundRobinLoadBalancer implements LoadBalancer { - private subchannels: Subchannel[] = []; + private subchannels: SubchannelInterface[] = []; private currentState: ConnectivityState = ConnectivityState.IDLE; @@ -121,14 +121,14 @@ export class RoundRobinLoadBalancer implements LoadBalancer { [ConnectivityState.TRANSIENT_FAILURE]: 0, }; this.subchannelStateListener = ( - subchannel: Subchannel, + subchannel: SubchannelInterface, previousState: ConnectivityState, newState: ConnectivityState ) => { this.subchannelStateCounts[previousState] -= 1; this.subchannelStateCounts[newState] += 1; this.calculateAndUpdateState(); - + if ( newState === ConnectivityState.TRANSIENT_FAILURE || newState === ConnectivityState.IDLE @@ -191,6 +191,7 @@ export class RoundRobinLoadBalancer implements LoadBalancer { for (const subchannel of this.subchannels) { subchannel.removeConnectivityStateListener(this.subchannelStateListener); subchannel.unref(); + this.channelControlHelper.removeChannelzChild(subchannel.getChannelzRef()); } this.subchannelStateCounts = { [ConnectivityState.CONNECTING]: 0, @@ -217,6 +218,7 @@ export class RoundRobinLoadBalancer implements LoadBalancer { for (const subchannel of this.subchannels) { subchannel.ref(); subchannel.addConnectivityStateListener(this.subchannelStateListener); + this.channelControlHelper.addChannelzChild(subchannel.getChannelzRef()); const subchannelState = subchannel.getConnectivityState(); this.subchannelStateCounts[subchannelState] += 1; if ( @@ -247,5 +249,9 @@ export class RoundRobinLoadBalancer implements LoadBalancer { } export function setup() { - registerLoadBalancerType(TYPE_NAME, RoundRobinLoadBalancer, RoundRobinLoadBalancingConfig); + registerLoadBalancerType( + TYPE_NAME, + RoundRobinLoadBalancer, + RoundRobinLoadBalancingConfig + ); } diff --git a/packages/grpc-js/src/load-balancer.ts b/packages/grpc-js/src/load-balancer.ts index 8d5c7c837..48930c7db 100644 --- a/packages/grpc-js/src/load-balancer.ts +++ b/packages/grpc-js/src/load-balancer.ts @@ -16,11 +16,12 @@ */ import { ChannelOptions } from './channel-options'; -import { Subchannel, SubchannelAddress } from './subchannel'; -import { ConnectivityState } from './channel'; +import { Subchannel } from './subchannel'; +import { SubchannelAddress } from './subchannel-address'; +import { ConnectivityState } from './connectivity-state'; import { Picker } from './picker'; -import * as load_balancer_pick_first from './load-balancer-pick-first'; -import * as load_balancer_round_robin from './load-balancer-round-robin'; +import { ChannelRef, SubchannelRef } from './channelz'; +import { SubchannelInterface } from './subchannel-interface'; /** * A collection of functions associated with a channel that a load balancer @@ -35,7 +36,7 @@ export interface ChannelControlHelper { createSubchannel( subchannelAddress: SubchannelAddress, subchannelArgs: ChannelOptions - ): Subchannel; + ): SubchannelInterface; /** * Passes a new subchannel picker up to the channel. This is called if either * the connectivity state changes or if a different picker is needed for any @@ -48,6 +49,26 @@ export interface ChannelControlHelper { * Request new data from the resolver. */ requestReresolution(): void; + addChannelzChild(child: ChannelRef | SubchannelRef): void; + removeChannelzChild(child: ChannelRef | SubchannelRef): void; +} + +/** + * Create a child ChannelControlHelper that overrides some methods of the + * parent while letting others pass through to the parent unmodified. This + * allows other code to create these children without needing to know about + * all of the methods to be passed through. + * @param parent + * @param overrides + */ +export function createChildChannelControlHelper(parent: ChannelControlHelper, overrides: Partial): ChannelControlHelper { + return { + createSubchannel: overrides.createSubchannel?.bind(overrides) ?? parent.createSubchannel.bind(parent), + updateState: overrides.updateState?.bind(overrides) ?? parent.updateState.bind(parent), + requestReresolution: overrides.requestReresolution?.bind(overrides) ?? parent.requestReresolution.bind(parent), + addChannelzChild: overrides.addChannelzChild?.bind(overrides) ?? parent.addChannelzChild.bind(parent), + removeChannelzChild: overrides.removeChannelzChild?.bind(overrides) ?? parent.removeChannelzChild.bind(parent) + }; } /** @@ -102,17 +123,21 @@ export interface LoadBalancingConfig { } export interface LoadBalancingConfigConstructor { - new(...args: any): LoadBalancingConfig; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + new (...args: any): LoadBalancingConfig; + // eslint-disable-next-line @typescript-eslint/no-explicit-any createFromJson(obj: any): LoadBalancingConfig; } const registeredLoadBalancerTypes: { [name: string]: { - LoadBalancer: LoadBalancerConstructor, - LoadBalancingConfig: LoadBalancingConfigConstructor + LoadBalancer: LoadBalancerConstructor; + LoadBalancingConfig: LoadBalancingConfigConstructor; }; } = {}; +let defaultLoadBalancerType: string | null = null; + export function registerLoadBalancerType( typeName: string, loadBalancerType: LoadBalancerConstructor, @@ -120,17 +145,23 @@ export function registerLoadBalancerType( ) { registeredLoadBalancerTypes[typeName] = { LoadBalancer: loadBalancerType, - LoadBalancingConfig: loadBalancingConfigType + LoadBalancingConfig: loadBalancingConfigType, }; } +export function registerDefaultLoadBalancerType(typeName: string) { + defaultLoadBalancerType = typeName; +} + export function createLoadBalancer( config: LoadBalancingConfig, channelControlHelper: ChannelControlHelper ): LoadBalancer | null { const typeName = config.getLoadBalancerName(); if (typeName in registeredLoadBalancerTypes) { - return new registeredLoadBalancerTypes[typeName].LoadBalancer(channelControlHelper); + return new registeredLoadBalancerTypes[typeName].LoadBalancer( + channelControlHelper + ); } else { return null; } @@ -140,40 +171,49 @@ export function isLoadBalancerNameRegistered(typeName: string): boolean { return typeName in registeredLoadBalancerTypes; } -export function getFirstUsableConfig(configs: LoadBalancingConfig[], defaultPickFirst?: true): LoadBalancingConfig; export function getFirstUsableConfig( configs: LoadBalancingConfig[], - defaultPickFirst: boolean = false + fallbackTodefault?: true +): LoadBalancingConfig; +export function getFirstUsableConfig( + configs: LoadBalancingConfig[], + fallbackTodefault = false ): LoadBalancingConfig | null { for (const config of configs) { if (config.getLoadBalancerName() in registeredLoadBalancerTypes) { return config; } } - if (defaultPickFirst) { - return new load_balancer_pick_first.PickFirstLoadBalancingConfig() + if (fallbackTodefault) { + if (defaultLoadBalancerType) { + return new registeredLoadBalancerTypes[ + defaultLoadBalancerType + ]!.LoadBalancingConfig(); + } else { + return null; + } } else { return null; } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function validateLoadBalancingConfig(obj: any): LoadBalancingConfig { - if (!(obj !== null && (typeof obj === 'object'))) { + if (!(obj !== null && typeof obj === 'object')) { throw new Error('Load balancing config must be an object'); } const keys = Object.keys(obj); if (keys.length !== 1) { - throw new Error('Provided load balancing config has multiple conflicting entries'); + throw new Error( + 'Provided load balancing config has multiple conflicting entries' + ); } const typeName = keys[0]; if (typeName in registeredLoadBalancerTypes) { - return registeredLoadBalancerTypes[typeName].LoadBalancingConfig.createFromJson(obj[typeName]); + return registeredLoadBalancerTypes[ + typeName + ].LoadBalancingConfig.createFromJson(obj[typeName]); } else { throw new Error(`Unrecognized load balancing config name ${typeName}`); } } - -export function registerAll() { - load_balancer_pick_first.setup(); - load_balancer_round_robin.setup(); -} diff --git a/packages/grpc-js/src/load-balancing-call.ts b/packages/grpc-js/src/load-balancing-call.ts new file mode 100644 index 000000000..d88bdb809 --- /dev/null +++ b/packages/grpc-js/src/load-balancing-call.ts @@ -0,0 +1,283 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { CallCredentials } from "./call-credentials"; +import { Call, InterceptingListener, MessageContext, StatusObject } from "./call-interface"; +import { SubchannelCall } from "./subchannel-call"; +import { ConnectivityState } from "./connectivity-state"; +import { LogVerbosity, Status } from "./constants"; +import { Deadline, getDeadlineTimeoutString } from "./deadline"; +import { FilterStack, FilterStackFactory } from "./filter-stack"; +import { InternalChannel } from "./internal-channel"; +import { Metadata } from "./metadata"; +import { PickResultType } from "./picker"; +import { CallConfig } from "./resolver"; +import { splitHostPort } from "./uri-parser"; +import * as logging from './logging'; +import { restrictControlPlaneStatusCode } from "./control-plane-status"; +import * as http2 from 'http2'; + +const TRACER_NAME = 'load_balancing_call'; + +export type RpcProgress = 'NOT_STARTED' | 'DROP' | 'REFUSED' | 'PROCESSED'; + +export interface StatusObjectWithProgress extends StatusObject { + progress: RpcProgress; +} + +export interface LoadBalancingCallInterceptingListener extends InterceptingListener { + onReceiveStatus(status: StatusObjectWithProgress): void; +} + +export class LoadBalancingCall implements Call { + private child: SubchannelCall | null = null; + private readPending = false; + private pendingMessage: {context: MessageContext, message: Buffer} | null = null; + private pendingHalfClose = false; + private pendingChildStatus: StatusObject | null = null; + private ended = false; + private serviceUrl: string; + private metadata: Metadata | null = null; + private listener: InterceptingListener | null = null; + private onCallEnded: ((statusCode: Status) => void) | null = null; + constructor( + private readonly channel: InternalChannel, + private readonly callConfig: CallConfig, + private readonly methodName: string, + private readonly host : string, + private readonly credentials: CallCredentials, + private readonly deadline: Deadline, + private readonly callNumber: number + ) { + const splitPath: string[] = this.methodName.split('/'); + let serviceName = ''; + /* The standard path format is "/{serviceName}/{methodName}", so if we split + * by '/', the first item should be empty and the second should be the + * service name */ + if (splitPath.length >= 2) { + serviceName = splitPath[1]; + } + const hostname = splitHostPort(this.host)?.host ?? 'localhost'; + /* Currently, call credentials are only allowed on HTTPS connections, so we + * can assume that the scheme is "https" */ + this.serviceUrl = `https://${hostname}/${serviceName}`; + } + + private trace(text: string): void { + logging.trace( + LogVerbosity.DEBUG, + TRACER_NAME, + '[' + this.callNumber + '] ' + text + ); + } + + private outputStatus(status: StatusObject, progress: RpcProgress) { + if (!this.ended) { + this.ended = true; + this.trace('ended with status: code=' + status.code + ' details="' + status.details + '"'); + const finalStatus = {...status, progress}; + this.listener?.onReceiveStatus(finalStatus); + this.onCallEnded?.(finalStatus.code); + } + } + + doPick() { + if (this.ended) { + return; + } + if (!this.metadata) { + throw new Error('doPick called before start'); + } + this.trace('Pick called') + const pickResult = this.channel.doPick(this.metadata, this.callConfig.pickInformation); + const subchannelString = pickResult.subchannel ? + '(' + pickResult.subchannel.getChannelzRef().id + ') ' + pickResult.subchannel.getAddress() : + '' + pickResult.subchannel; + this.trace( + 'Pick result: ' + + PickResultType[pickResult.pickResultType] + + ' subchannel: ' + + subchannelString + + ' status: ' + + pickResult.status?.code + + ' ' + + pickResult.status?.details + ); + switch (pickResult.pickResultType) { + case PickResultType.COMPLETE: + this.credentials.generateMetadata({service_url: this.serviceUrl}).then( + (credsMetadata) => { + const finalMetadata = this.metadata!.clone(); + finalMetadata.merge(credsMetadata); + if (finalMetadata.get('authorization').length > 1) { + this.outputStatus( + { + code: Status.INTERNAL, + details: '"authorization" metadata cannot have multiple values', + metadata: new Metadata() + }, + 'PROCESSED' + ); + } + if (pickResult.subchannel!.getConnectivityState() !== ConnectivityState.READY) { + this.trace( + 'Picked subchannel ' + + subchannelString + + ' has state ' + + ConnectivityState[pickResult.subchannel!.getConnectivityState()] + + ' after getting credentials metadata. Retrying pick' + ); + this.doPick(); + return; + } + + if (this.deadline !== Infinity) { + finalMetadata.set('grpc-timeout', getDeadlineTimeoutString(this.deadline)); + } + try { + this.child = pickResult.subchannel!.getRealSubchannel().createCall(finalMetadata, this.host, this.methodName, { + onReceiveMetadata: metadata => { + this.trace('Received metadata'); + this.listener!.onReceiveMetadata(metadata); + }, + onReceiveMessage: message => { + this.trace('Received message'); + this.listener!.onReceiveMessage(message); + }, + onReceiveStatus: status => { + this.trace('Received status'); + if (status.rstCode === http2.constants.NGHTTP2_REFUSED_STREAM) { + this.outputStatus(status, 'REFUSED'); + } else { + this.outputStatus(status, 'PROCESSED'); + } + } + }); + } catch (error) { + this.trace( + 'Failed to start call on picked subchannel ' + + subchannelString + + ' with error ' + + (error as Error).message + ); + this.outputStatus( + { + code: Status.INTERNAL, + details: 'Failed to start HTTP/2 stream with error ' + (error as Error).message, + metadata: new Metadata() + }, + 'NOT_STARTED' + ); + return; + } + this.callConfig.onCommitted?.(); + pickResult.onCallStarted?.(); + this.onCallEnded = pickResult.onCallEnded; + this.trace('Created child call [' + this.child.getCallNumber() + ']'); + if (this.readPending) { + this.child.startRead(); + } + if (this.pendingMessage) { + this.child.sendMessageWithContext(this.pendingMessage.context, this.pendingMessage.message); + } + if (this.pendingHalfClose) { + this.child.halfClose(); + } + }, (error: Error & { code: number }) => { + // We assume the error code isn't 0 (Status.OK) + const {code, details} = restrictControlPlaneStatusCode( + typeof error.code === 'number' ? error.code : Status.UNKNOWN, + `Getting metadata from plugin failed with error: ${error.message}` + ) + this.outputStatus( + { + code: code, + details: details, + metadata: new Metadata() + }, + 'PROCESSED' + ); + } + ); + break; + case PickResultType.DROP: + const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details); + setImmediate(() => { + this.outputStatus({code, details, metadata: pickResult.status!.metadata}, 'DROP'); + }); + break; + case PickResultType.TRANSIENT_FAILURE: + if (this.metadata.getOptions().waitForReady) { + this.channel.queueCallForPick(this); + } else { + const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details); + setImmediate(() => { + this.outputStatus({code, details, metadata: pickResult.status!.metadata}, 'PROCESSED'); + }); + } + break; + case PickResultType.QUEUE: + this.channel.queueCallForPick(this); + } + } + + cancelWithStatus(status: Status, details: string): void { + this.trace('cancelWithStatus code: ' + status + ' details: "' + details + '"'); + this.child?.cancelWithStatus(status, details); + this.outputStatus({code: status, details: details, metadata: new Metadata()}, 'PROCESSED'); + } + getPeer(): string { + return this.child?.getPeer() ?? this.channel.getTarget(); + } + start(metadata: Metadata, listener: LoadBalancingCallInterceptingListener): void { + this.trace('start called'); + this.listener = listener; + this.metadata = metadata; + this.doPick(); + } + sendMessageWithContext(context: MessageContext, message: Buffer): void { + this.trace('write() called with message of length ' + message.length); + if (this.child) { + this.child.sendMessageWithContext(context, message); + } else { + this.pendingMessage = {context, message}; + } + } + startRead(): void { + this.trace('startRead called'); + if (this.child) { + this.child.startRead(); + } else { + this.readPending = true; + } + } + halfClose(): void { + this.trace('halfClose called'); + if (this.child) { + this.child.halfClose(); + } else { + this.pendingHalfClose = true; + } + } + setCredentials(credentials: CallCredentials): void { + throw new Error("Method not implemented."); + } + + getCallNumber(): number { + return this.callNumber; + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/logging.ts b/packages/grpc-js/src/logging.ts index 71683dbf7..ec845c1a5 100644 --- a/packages/grpc-js/src/logging.ts +++ b/packages/grpc-js/src/logging.ts @@ -17,10 +17,23 @@ import { LogVerbosity } from './constants'; -let _logger: Partial = console; +const DEFAULT_LOGGER: Partial = { + error: (message?: any, ...optionalParams: any[]) => { + console.error('E ' + message, ...optionalParams); + }, + info: (message?: any, ...optionalParams: any[]) => { + console.error('I ' + message, ...optionalParams); + }, + debug: (message?: any, ...optionalParams: any[]) => { + console.error('D ' + message, ...optionalParams); + }, +} + +let _logger: Partial = DEFAULT_LOGGER; let _logVerbosity: LogVerbosity = LogVerbosity.ERROR; -const verbosityString = process.env.GRPC_NODE_VERBOSITY ?? process.env.GRPC_VERBOSITY ?? ''; +const verbosityString = + process.env.GRPC_NODE_VERBOSITY ?? process.env.GRPC_VERBOSITY ?? ''; switch (verbosityString.toUpperCase()) { case 'DEBUG': @@ -53,19 +66,39 @@ export const setLoggerVerbosity = (verbosity: LogVerbosity): void => { // eslint-disable-next-line @typescript-eslint/no-explicit-any export const log = (severity: LogVerbosity, ...args: any[]): void => { - if (severity >= _logVerbosity && typeof _logger.error === 'function') { - _logger.error(...args); + let logFunction: typeof DEFAULT_LOGGER.error; + if (severity >= _logVerbosity) { + switch (severity) { + case LogVerbosity.DEBUG: + logFunction = _logger.debug; + break; + case LogVerbosity.INFO: + logFunction = _logger.info; + break; + case LogVerbosity.ERROR: + logFunction = _logger.error; + break; + } + /* Fall back to _logger.error when other methods are not available for + * compatiblity with older behavior that always logged to _logger.error */ + if (!logFunction) { + logFunction = _logger.error; + } + if (logFunction) { + logFunction.bind(_logger)(...args); + } } }; -const tracersString = process.env.GRPC_NODE_TRACE ?? process.env.GRPC_TRACE ?? ''; +const tracersString = + process.env.GRPC_NODE_TRACE ?? process.env.GRPC_TRACE ?? ''; const enabledTracers = new Set(); const disabledTracers = new Set(); for (const tracerName of tracersString.split(',')) { if (tracerName.startsWith('-')) { disabledTracers.add(tracerName.substring(1)); } else { - enabledTracers.add(tracerName) + enabledTracers.add(tracerName); } } const allEnabled = enabledTracers.has('all'); @@ -75,7 +108,12 @@ export function trace( tracer: string, text: string ): void { - if (!disabledTracers.has(tracer) && (allEnabled || enabledTracers.has(tracer))) { + if (isTracerEnabled(tracer)) { log(severity, new Date().toISOString() + ' | ' + tracer + ' | ' + text); } } + +export function isTracerEnabled(tracer: string): boolean { + return !disabledTracers.has(tracer) && + (allEnabled || enabledTracers.has(tracer)); +} diff --git a/packages/grpc-js/src/make-client.ts b/packages/grpc-js/src/make-client.ts index a6cb91007..7d08fee20 100644 --- a/packages/grpc-js/src/make-client.ts +++ b/packages/grpc-js/src/make-client.ts @@ -91,6 +91,7 @@ export interface ServiceClientConstructor { options?: Partial ): ServiceClient; service: ServiceDefinition; + serviceName: string; } /** @@ -98,7 +99,7 @@ export interface ServiceClientConstructor { * keys. * @param key key for check, string. */ -function isPrototypePolluted(key: string): Boolean { +function isPrototypePolluted(key: string): boolean { return ['__proto__', 'prototype', 'constructor'].includes(key); } @@ -127,6 +128,7 @@ export function makeClientConstructor( class ServiceClientImpl extends Client implements ServiceClient { static service: ServiceDefinition; + static serviceName: string; [methodName: string]: Function; } @@ -171,6 +173,7 @@ export function makeClientConstructor( }); ServiceClientImpl.service = methods; + ServiceClientImpl.serviceName = serviceName; return ServiceClientImpl; } diff --git a/packages/grpc-js/src/max-message-size-filter.ts b/packages/grpc-js/src/max-message-size-filter.ts index f820c02e6..62d01077c 100644 --- a/packages/grpc-js/src/max-message-size-filter.ts +++ b/packages/grpc-js/src/max-message-size-filter.ts @@ -15,17 +15,21 @@ * */ -import { BaseFilter, Filter, FilterFactory } from "./filter"; -import { Call, WriteObject } from "./call-stream"; -import { Status, DEFAULT_MAX_SEND_MESSAGE_LENGTH, DEFAULT_MAX_RECEIVE_MESSAGE_LENGTH } from "./constants"; -import { ChannelOptions } from "./channel-options"; +import { BaseFilter, Filter, FilterFactory } from './filter'; +import { WriteObject } from './call-interface'; +import { + Status, + DEFAULT_MAX_SEND_MESSAGE_LENGTH, + DEFAULT_MAX_RECEIVE_MESSAGE_LENGTH, +} from './constants'; +import { ChannelOptions } from './channel-options'; +import { Metadata } from './metadata'; export class MaxMessageSizeFilter extends BaseFilter implements Filter { private maxSendMessageSize: number = DEFAULT_MAX_SEND_MESSAGE_LENGTH; private maxReceiveMessageSize: number = DEFAULT_MAX_RECEIVE_MESSAGE_LENGTH; constructor( - private readonly options: ChannelOptions, - private readonly callStream: Call + private readonly options: ChannelOptions ) { super(); if ('grpc.max_send_message_length' in options) { @@ -44,8 +48,11 @@ export class MaxMessageSizeFilter extends BaseFilter implements Filter { } else { const concreteMessage = await message; if (concreteMessage.message.length > this.maxSendMessageSize) { - this.callStream.cancelWithStatus(Status.RESOURCE_EXHAUSTED, `Sent message larger than max (${concreteMessage.message.length} vs. ${this.maxSendMessageSize})`); - return Promise.reject('Message too large'); + throw { + code: Status.RESOURCE_EXHAUSTED, + details: `Sent message larger than max (${concreteMessage.message.length} vs. ${this.maxSendMessageSize})`, + metadata: new Metadata() + }; } else { return concreteMessage; } @@ -60,8 +67,11 @@ export class MaxMessageSizeFilter extends BaseFilter implements Filter { } else { const concreteMessage = await message; if (concreteMessage.length > this.maxReceiveMessageSize) { - this.callStream.cancelWithStatus(Status.RESOURCE_EXHAUSTED, `Received message larger than max (${concreteMessage.length} vs. ${this.maxReceiveMessageSize})`); - return Promise.reject('Message too large'); + throw { + code: Status.RESOURCE_EXHAUSTED, + details: `Received message larger than max (${concreteMessage.length} vs. ${this.maxReceiveMessageSize})`, + metadata: new Metadata() + }; } else { return concreteMessage; } @@ -69,10 +79,11 @@ export class MaxMessageSizeFilter extends BaseFilter implements Filter { } } -export class MaxMessageSizeFilterFactory implements FilterFactory { +export class MaxMessageSizeFilterFactory + implements FilterFactory { constructor(private readonly options: ChannelOptions) {} - createFilter(callStream: Call): MaxMessageSizeFilter { - return new MaxMessageSizeFilter(this.options, callStream); + createFilter(): MaxMessageSizeFilter { + return new MaxMessageSizeFilter(this.options); } } diff --git a/packages/grpc-js/src/metadata.ts b/packages/grpc-js/src/metadata.ts index 4947bf0ad..0dddd9465 100644 --- a/packages/grpc-js/src/metadata.ts +++ b/packages/grpc-js/src/metadata.ts @@ -18,6 +18,7 @@ import * as http2 from 'http2'; import { log } from './logging'; import { LogVerbosity } from './constants'; +import { getErrorMessage } from './error'; const LEGAL_KEY_REGEX = /^[0-9a-z_.-]+$/; const LEGAL_NON_BINARY_VALUE_REGEX = /^[ -~]*$/; @@ -48,13 +49,14 @@ function validate(key: string, value?: MetadataValue): void { if (!isLegalKey(key)) { throw new Error('Metadata key "' + key + '" contains illegal characters'); } + if (value !== null && value !== undefined) { if (isBinaryKey(key)) { - if (!(value instanceof Buffer)) { + if (!Buffer.isBuffer(value)) { throw new Error("keys that end with '-bin' must have Buffer values"); } } else { - if (value instanceof Buffer) { + if (Buffer.isBuffer(value)) { throw new Error( "keys that don't end with '-bin' must have String values" ); @@ -88,12 +90,8 @@ export class Metadata { protected internalRepr: MetadataObject = new Map(); private options: MetadataOptions; - constructor(options?: MetadataOptions) { - if (options === undefined) { - this.options = {}; - } else { - this.options = options; - } + constructor(options: MetadataOptions = {}) { + this.options = options; } /** @@ -120,9 +118,7 @@ export class Metadata { key = normalizeKey(key); validate(key, value); - const existingValue: MetadataValue[] | undefined = this.internalRepr.get( - key - ); + const existingValue: MetadataValue[] | undefined = this.internalRepr.get(key); if (existingValue === undefined) { this.internalRepr.set(key, [value]); @@ -137,7 +133,7 @@ export class Metadata { */ remove(key: string): void { key = normalizeKey(key); - validate(key); + // validate(key); this.internalRepr.delete(key); } @@ -148,7 +144,7 @@ export class Metadata { */ get(key: string): MetadataValue[] { key = normalizeKey(key); - validate(key); + // validate(key); return this.internalRepr.get(key) || []; } @@ -160,12 +156,12 @@ export class Metadata { getMap(): { [key: string]: MetadataValue } { const result: { [key: string]: MetadataValue } = {}; - this.internalRepr.forEach((values, key) => { + for (const [key, values] of this.internalRepr) { if (values.length > 0) { const v = values[0]; - result[key] = v instanceof Buffer ? v.slice() : v; + result[key] = Buffer.isBuffer(v) ? Buffer.from(v) : v; } - }); + } return result; } @@ -177,9 +173,9 @@ export class Metadata { const newMetadata = new Metadata(this.options); const newInternalRepr = newMetadata.internalRepr; - this.internalRepr.forEach((value, key) => { + for (const [key, value] of this.internalRepr) { const clonedValue: MetadataValue[] = value.map((v) => { - if (v instanceof Buffer) { + if (Buffer.isBuffer(v)) { return Buffer.from(v); } else { return v; @@ -187,7 +183,7 @@ export class Metadata { }); newInternalRepr.set(key, clonedValue); - }); + } return newMetadata; } @@ -200,13 +196,13 @@ export class Metadata { * @param other A Metadata object. */ merge(other: Metadata): void { - other.internalRepr.forEach((values, key) => { + for (const [key, values] of other.internalRepr) { const mergedValue: MetadataValue[] = ( this.internalRepr.get(key) || [] ).concat(values); this.internalRepr.set(key, mergedValue); - }); + } } setOptions(options: MetadataOptions) { @@ -223,17 +219,13 @@ export class Metadata { toHttp2Headers(): http2.OutgoingHttpHeaders { // NOTE: Node <8.9 formats http2 headers incorrectly. const result: http2.OutgoingHttpHeaders = {}; - this.internalRepr.forEach((values, key) => { + + for (const [key, values] of this.internalRepr) { // We assume that the user's interaction with this object is limited to // through its public API (i.e. keys and values are already validated). - result[key] = values.map((value) => { - if (value instanceof Buffer) { - return value.toString('base64'); - } else { - return value; - } - }); - }); + result[key] = values.map(bufToString); + } + return result; } @@ -242,6 +234,18 @@ export class Metadata { return this.internalRepr; } + /** + * This modifies the behavior of JSON.stringify to show an object + * representation of the metadata map. + */ + toJSON() { + const result: { [key: string]: MetadataValue[] } = {}; + for (const [key, values] of this.internalRepr) { + result[key] = values; + } + return result; + } + /** * Returns a new Metadata object based fields in a given IncomingHttpHeaders * object. @@ -249,10 +253,10 @@ export class Metadata { */ static fromHttp2Headers(headers: http2.IncomingHttpHeaders): Metadata { const result = new Metadata(); - Object.keys(headers).forEach((key) => { + for (const key of Object.keys(headers)) { // Reserved headers (beginning with `:`) are not valid keys. if (key.charAt(0) === ':') { - return; + continue; } const values = headers[key]; @@ -282,10 +286,15 @@ export class Metadata { } } } catch (error) { - const message = `Failed to add metadata entry ${key}: ${values}. ${error.message}. For more information see https://github.com/grpc/grpc-node/issues/1173`; + const message = `Failed to add metadata entry ${key}: ${values}. ${getErrorMessage(error)}. For more information see https://github.com/grpc/grpc-node/issues/1173`; log(LogVerbosity.ERROR, message); } - }); + } + return result; } } + +const bufToString = (val: string | Buffer): string => { + return Buffer.isBuffer(val) ? val.toString('base64') : val +}; diff --git a/packages/grpc-js/src/object-stream.ts b/packages/grpc-js/src/object-stream.ts index b17058a7a..22ab8a41f 100644 --- a/packages/grpc-js/src/object-stream.ts +++ b/packages/grpc-js/src/object-stream.ts @@ -36,9 +36,9 @@ export interface IntermediateObjectWritable extends Writable { write(chunk: any & T, cb?: WriteCallback): boolean; write(chunk: any & T, encoding?: any, cb?: WriteCallback): boolean; setDefaultEncoding(encoding: string): this; - end(): void; - end(chunk: any & T, cb?: Function): void; - end(chunk: any & T, encoding?: any, cb?: Function): void; + end(): ReturnType extends Writable ? this : void; + end(chunk: any & T, cb?: Function): ReturnType extends Writable ? this : void; + end(chunk: any & T, encoding?: any, cb?: Function): ReturnType extends Writable ? this : void; } export interface ObjectWritable extends IntermediateObjectWritable { @@ -46,20 +46,7 @@ export interface ObjectWritable extends IntermediateObjectWritable { write(chunk: T, cb?: Function): boolean; write(chunk: T, encoding?: any, cb?: Function): boolean; setDefaultEncoding(encoding: string): this; - end(): void; - end(chunk: T, cb?: Function): void; - end(chunk: T, encoding?: any, cb?: Function): void; + end(): ReturnType extends Writable ? this : void; + end(chunk: T, cb?: Function): ReturnType extends Writable ? this : void; + end(chunk: T, encoding?: any, cb?: Function): ReturnType extends Writable ? this : void; } - -export type ObjectDuplex = { - read(size?: number): U; - - _write(chunk: T, encoding: string, callback: Function): void; - write(chunk: T, cb?: Function): boolean; - write(chunk: T, encoding?: any, cb?: Function): boolean; - end(): void; - end(chunk: T, cb?: Function): void; - end(chunk: T, encoding?: any, cb?: Function): void; -} & Duplex & - ObjectWritable & - ObjectReadable; diff --git a/packages/grpc-js/src/picker.ts b/packages/grpc-js/src/picker.ts index 6df61b59a..162596ef5 100644 --- a/packages/grpc-js/src/picker.ts +++ b/packages/grpc-js/src/picker.ts @@ -15,12 +15,11 @@ * */ -import { Subchannel } from './subchannel'; -import { StatusObject } from './call-stream'; +import { StatusObject } from './call-interface'; import { Metadata } from './metadata'; import { Status } from './constants'; import { LoadBalancer } from './load-balancer'; -import { FilterFactory, Filter } from './filter'; +import { SubchannelInterface } from './subchannel-interface'; export enum PickResultType { COMPLETE, @@ -36,56 +35,51 @@ export interface PickResult { * `pickResultType` is COMPLETE. If null, indicates that the call should be * dropped. */ - subchannel: Subchannel | null; + subchannel: SubchannelInterface | null; /** * The status object to end the call with. Populated if and only if * `pickResultType` is TRANSIENT_FAILURE. */ status: StatusObject | null; - /** - * Extra FilterFactory (can be multiple encapsulated in a FilterStackFactory) - * provided by the load balancer to be used with the call. For technical - * reasons filters from this factory will not see sendMetadata events. - */ - extraFilterFactory: FilterFactory | null; onCallStarted: (() => void) | null; + onCallEnded: ((statusCode: Status) => void) | null; } export interface CompletePickResult extends PickResult { pickResultType: PickResultType.COMPLETE; - subchannel: Subchannel | null; + subchannel: SubchannelInterface | null; status: null; - extraFilterFactory: FilterFactory | null; onCallStarted: (() => void) | null; + onCallEnded: ((statusCode: Status) => void) | null; } export interface QueuePickResult extends PickResult { pickResultType: PickResultType.QUEUE; subchannel: null; status: null; - extraFilterFactory: null; onCallStarted: null; + onCallEnded: null; } export interface TransientFailurePickResult extends PickResult { pickResultType: PickResultType.TRANSIENT_FAILURE; subchannel: null; status: StatusObject; - extraFilterFactory: null; onCallStarted: null; + onCallEnded: null; } export interface DropCallPickResult extends PickResult { pickResultType: PickResultType.DROP; subchannel: null; status: StatusObject; - extraFilterFactory: null; onCallStarted: null; + onCallEnded: null; } export interface PickArgs { metadata: Metadata; - extraPickInfo: {[key: string]: string}; + extraPickInfo: { [key: string]: string }; } /** @@ -119,8 +113,8 @@ export class UnavailablePicker implements Picker { pickResultType: PickResultType.TRANSIENT_FAILURE, subchannel: null, status: this.status, - extraFilterFactory: null, onCallStarted: null, + onCallEnded: null }; } } @@ -148,8 +142,8 @@ export class QueuePicker { pickResultType: PickResultType.QUEUE, subchannel: null, status: null, - extraFilterFactory: null, onCallStarted: null, + onCallEnded: null }; } } diff --git a/packages/grpc-js/src/resolver-dns.ts b/packages/grpc-js/src/resolver-dns.ts index 67f1f8c45..b20b7a543 100644 --- a/packages/grpc-js/src/resolver-dns.ts +++ b/packages/grpc-js/src/resolver-dns.ts @@ -24,14 +24,15 @@ import * as dns from 'dns'; import * as util from 'util'; import { extractAndSelectServiceConfig, ServiceConfig } from './service-config'; import { Status } from './constants'; -import { StatusObject } from './call-stream'; +import { StatusObject } from './call-interface'; import { Metadata } from './metadata'; import * as logging from './logging'; import { LogVerbosity } from './constants'; -import { SubchannelAddress, TcpSubchannelAddress } from './subchannel'; +import { SubchannelAddress, TcpSubchannelAddress } from './subchannel-address'; import { GrpcUri, uriToString, splitHostPort } from './uri-parser'; import { isIPv6, isIPv4 } from 'net'; import { ChannelOptions } from './channel-options'; +import { BackoffOptions, BackoffTimeout } from './backoff-timeout'; const TRACER_NAME = 'dns_resolver'; @@ -44,6 +45,8 @@ function trace(text: string): void { */ const DEFAULT_PORT = 443; +const DEFAULT_MIN_TIME_BETWEEN_RESOLUTIONS_MS = 30_000; + const resolveTxtPromise = util.promisify(dns.resolveTxt); const dnsLookupPromise = util.promisify(dns.lookup); @@ -78,6 +81,12 @@ class DnsResolver implements Resolver { private readonly ipResult: SubchannelAddress[] | null; private readonly dnsHostname: string | null; private readonly port: number | null; + /** + * Minimum time between resolutions, measured as the time between starting + * successive resolution requests. Only applies to successful resolutions. + * Failures are handled by the backoff timer. + */ + private readonly minTimeBetweenResolutionsMs: number; private pendingLookupPromise: Promise | null = null; private pendingTxtPromise: Promise | null = null; private latestLookupResult: TcpSubchannelAddress[] | null = null; @@ -85,6 +94,11 @@ class DnsResolver implements Resolver { private latestServiceConfigError: StatusObject | null = null; private percentage: number; private defaultResolutionError: StatusObject; + private backoff: BackoffTimeout; + private continueResolving = false; + private nextResolutionTimer: NodeJS.Timer; + private isNextResolutionTimerRunning = false; + private isServiceConfigEnabled = true; constructor( private target: GrpcUri, private listener: ResolverListener, @@ -114,11 +128,31 @@ class DnsResolver implements Resolver { } this.percentage = Math.random() * 100; + if (channelOptions['grpc.service_config_disable_resolution'] === 1) { + this.isServiceConfigEnabled = false; + } + this.defaultResolutionError = { code: Status.UNAVAILABLE, details: `Name resolution failed for target ${uriToString(this.target)}`, metadata: new Metadata(), }; + + const backoffOptions: BackoffOptions = { + initialDelay: channelOptions['grpc.initial_reconnect_backoff_ms'], + maxDelay: channelOptions['grpc.max_reconnect_backoff_ms'], + }; + + this.backoff = new BackoffTimeout(() => { + if (this.continueResolving) { + this.startResolutionWithBackoff(); + } + }, backoffOptions); + this.backoff.unref(); + + this.minTimeBetweenResolutionsMs = channelOptions['grpc.dns_min_time_between_resolutions_ms'] ?? DEFAULT_MIN_TIME_BETWEEN_RESOLUTIONS_MS; + this.nextResolutionTimer = setTimeout(() => {}, 0); + clearTimeout(this.nextResolutionTimer); } /** @@ -129,11 +163,20 @@ class DnsResolver implements Resolver { if (this.ipResult !== null) { trace('Returning IP address for target ' + uriToString(this.target)); setImmediate(() => { - this.listener.onSuccessfulResolution(this.ipResult!, null, null, null, {}); + this.listener.onSuccessfulResolution( + this.ipResult!, + null, + null, + null, + {} + ); }); + this.backoff.stop(); + this.backoff.reset(); return; } if (this.dnsHostname === null) { + trace('Failed to parse DNS address ' + uriToString(this.target)); setImmediate(() => { this.listener.onError({ code: Status.UNAVAILABLE, @@ -141,7 +184,12 @@ class DnsResolver implements Resolver { metadata: new Metadata(), }); }); + this.stopNextResolutionTimer(); } else { + if (this.pendingLookupPromise !== null) { + return; + } + trace('Looking up DNS hostname ' + this.dnsHostname); /* We clear out latestLookupResult here to ensure that it contains the * latest result since the last time we started resolving. That way, the * TXT resolution handler can use it, but only if it finishes second. We @@ -158,6 +206,8 @@ class DnsResolver implements Resolver { this.pendingLookupPromise.then( (addressList) => { this.pendingLookupPromise = null; + this.backoff.reset(); + this.backoff.stop(); const ip4Addresses: dns.LookupAddress[] = addressList.filter( (addr) => addr.family === 4 ); @@ -204,12 +254,13 @@ class DnsResolver implements Resolver { (err as Error).message ); this.pendingLookupPromise = null; + this.stopNextResolutionTimer(); this.listener.onError(this.defaultResolutionError); } ); /* If there already is a still-pending TXT resolution, we can just use * that result when it comes in */ - if (this.pendingTxtPromise === null) { + if (this.isServiceConfigEnabled && this.pendingTxtPromise === null) { /* We handle the TXT query promise differently than the others because * the name resolution attempt as a whole is a success even if the TXT * lookup fails */ @@ -225,7 +276,7 @@ class DnsResolver implements Resolver { } catch (err) { this.latestServiceConfigError = { code: Status.UNAVAILABLE, - details: 'Parsing service config failed', + details: `Parsing service config failed with error ${(err as Error).message}`, metadata: new Metadata(), }; } @@ -257,17 +308,49 @@ class DnsResolver implements Resolver { } } - updateResolution() { - trace('Resolution update requested for target ' + uriToString(this.target)); + private startNextResolutionTimer() { + clearTimeout(this.nextResolutionTimer); + this.nextResolutionTimer = setTimeout(() => { + this.stopNextResolutionTimer(); + if (this.continueResolving) { + this.startResolutionWithBackoff(); + } + }, this.minTimeBetweenResolutionsMs).unref?.(); + this.isNextResolutionTimerRunning = true; + } + + private stopNextResolutionTimer() { + clearTimeout(this.nextResolutionTimer); + this.isNextResolutionTimerRunning = false; + } + + private startResolutionWithBackoff() { if (this.pendingLookupPromise === null) { + this.continueResolving = false; this.startResolution(); + this.backoff.runOnce(); + this.startNextResolutionTimer(); + } + } + + updateResolution() { + /* If there is a pending lookup, just let it finish. Otherwise, if the + * nextResolutionTimer or backoff timer is running, set the + * continueResolving flag to resolve when whichever of those timers + * fires. Otherwise, start resolving immediately. */ + if (this.pendingLookupPromise === null) { + if (this.isNextResolutionTimerRunning || this.backoff.isRunning()) { + this.continueResolving = true; + } else { + this.startResolutionWithBackoff(); + } } } destroy() { - /* Do nothing. There is not a practical way to cancel in-flight DNS - * requests, and after this function is called we can expect that - * updateResolution will not be called again. */ + this.continueResolving = false; + this.backoff.stop(); + this.stopNextResolutionTimer(); } /** diff --git a/packages/grpc-js/src/resolver-ip.ts b/packages/grpc-js/src/resolver-ip.ts index 5c9e29c46..efb0b8dcb 100644 --- a/packages/grpc-js/src/resolver-ip.ts +++ b/packages/grpc-js/src/resolver-ip.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { isIPv4, isIPv6 } from "net"; -import { StatusObject } from "./call-stream"; -import { ChannelOptions } from "./channel-options"; -import { LogVerbosity, Status } from "./constants"; -import { Metadata } from "./metadata"; -import { registerResolver, Resolver, ResolverListener } from "./resolver"; -import { SubchannelAddress } from "./subchannel"; -import { GrpcUri, splitHostPort, uriToString } from "./uri-parser"; +import { isIPv4, isIPv6 } from 'net'; +import { StatusObject } from './call-interface'; +import { ChannelOptions } from './channel-options'; +import { LogVerbosity, Status } from './constants'; +import { Metadata } from './metadata'; +import { registerResolver, Resolver, ResolverListener } from './resolver'; +import { SubchannelAddress } from './subchannel-address'; +import { GrpcUri, splitHostPort, uriToString } from './uri-parser'; import * as logging from './logging'; const TRACER_NAME = 'ip_resolver'; @@ -52,7 +52,7 @@ class IpResolver implements Resolver { this.error = { code: Status.UNAVAILABLE, details: `Unrecognized scheme ${target.scheme} in IP resolver`, - metadata: new Metadata() + metadata: new Metadata(), }; return; } @@ -63,21 +63,24 @@ class IpResolver implements Resolver { this.error = { code: Status.UNAVAILABLE, details: `Failed to parse ${target.scheme} address ${path}`, - metadata: new Metadata() + metadata: new Metadata(), }; return; } - if ((target.scheme === IPV4_SCHEME && !isIPv4(hostPort.host)) || (target.scheme === IPV6_SCHEME && !isIPv6(hostPort.host))) { + if ( + (target.scheme === IPV4_SCHEME && !isIPv4(hostPort.host)) || + (target.scheme === IPV6_SCHEME && !isIPv6(hostPort.host)) + ) { this.error = { code: Status.UNAVAILABLE, details: `Failed to parse ${target.scheme} address ${path}`, - metadata: new Metadata() + metadata: new Metadata(), }; return; } addresses.push({ host: hostPort.host, - port: hostPort.port ?? DEFAULT_PORT + port: hostPort.port ?? DEFAULT_PORT, }); } this.addresses = addresses; @@ -86,9 +89,15 @@ class IpResolver implements Resolver { updateResolution(): void { process.nextTick(() => { if (this.error) { - this.listener.onError(this.error) + this.listener.onError(this.error); } else { - this.listener.onSuccessfulResolution(this.addresses, null, null, null, {}); + this.listener.onSuccessfulResolution( + this.addresses, + null, + null, + null, + {} + ); } }); } @@ -104,4 +113,4 @@ class IpResolver implements Resolver { export function setup() { registerResolver(IPV4_SCHEME, IpResolver); registerResolver(IPV6_SCHEME, IpResolver); -} \ No newline at end of file +} diff --git a/packages/grpc-js/src/resolver-uds.ts b/packages/grpc-js/src/resolver-uds.ts index 40502f113..24095ec29 100644 --- a/packages/grpc-js/src/resolver-uds.ts +++ b/packages/grpc-js/src/resolver-uds.ts @@ -15,7 +15,7 @@ */ import { Resolver, ResolverListener, registerResolver } from './resolver'; -import { SubchannelAddress } from './subchannel'; +import { SubchannelAddress } from './subchannel-address'; import { GrpcUri } from './uri-parser'; import { ChannelOptions } from './channel-options'; diff --git a/packages/grpc-js/src/resolver.ts b/packages/grpc-js/src/resolver.ts index 497f3dfa0..770004487 100644 --- a/packages/grpc-js/src/resolver.ts +++ b/packages/grpc-js/src/resolver.ts @@ -16,21 +16,20 @@ */ import { MethodConfig, ServiceConfig } from './service-config'; -import * as resolver_dns from './resolver-dns'; -import * as resolver_uds from './resolver-uds'; -import * as resolver_ip from './resolver-ip'; -import { StatusObject } from './call-stream'; -import { SubchannelAddress } from './subchannel'; +import { StatusObject } from './call-interface'; +import { SubchannelAddress } from './subchannel-address'; import { GrpcUri, uriToString } from './uri-parser'; import { ChannelOptions } from './channel-options'; import { Metadata } from './metadata'; import { Status } from './constants'; +import { Filter, FilterFactory } from './filter'; export interface CallConfig { methodConfig: MethodConfig; onCommitted?: () => void; - pickInformation: {[key: string]: string}; + pickInformation: { [key: string]: string }; status: Status; + dynamicFilterFactories: FilterFactory[]; } /** @@ -81,7 +80,7 @@ export interface Resolver { * called synchronously with the constructor or updateResolution. */ updateResolution(): void; - + /** * Destroy the resolver. Should be called when the owning channel shuts down. */ @@ -176,9 +175,3 @@ export function mapUriDefaultScheme(target: GrpcUri): GrpcUri | null { } return target; } - -export function registerAll() { - resolver_dns.setup(); - resolver_uds.setup(); - resolver_ip.setup(); -} diff --git a/packages/grpc-js/src/resolving-call.ts b/packages/grpc-js/src/resolving-call.ts new file mode 100644 index 000000000..f29fb7fd7 --- /dev/null +++ b/packages/grpc-js/src/resolving-call.ts @@ -0,0 +1,279 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { CallCredentials } from "./call-credentials"; +import { Call, CallStreamOptions, InterceptingListener, MessageContext, StatusObject } from "./call-interface"; +import { LogVerbosity, Propagate, Status } from "./constants"; +import { Deadline, deadlineToString, getDeadlineTimeoutString, getRelativeTimeout, minDeadline } from "./deadline"; +import { FilterStack, FilterStackFactory } from "./filter-stack"; +import { InternalChannel } from "./internal-channel"; +import { Metadata } from "./metadata"; +import * as logging from './logging'; +import { restrictControlPlaneStatusCode } from "./control-plane-status"; + +const TRACER_NAME = 'resolving_call'; + +export class ResolvingCall implements Call { + private child: Call | null = null; + private readPending = false; + private pendingMessage: {context: MessageContext, message: Buffer} | null = null; + private pendingHalfClose = false; + private ended = false; + private readFilterPending = false; + private writeFilterPending = false; + private pendingChildStatus: StatusObject | null = null; + private metadata: Metadata | null = null; + private listener: InterceptingListener | null = null; + private deadline: Deadline; + private host: string; + private statusWatchers: ((status: StatusObject) => void)[] = []; + private deadlineTimer: NodeJS.Timer = setTimeout(() => {}, 0); + private filterStack: FilterStack | null = null; + + constructor( + private readonly channel: InternalChannel, + private readonly method: string, + options: CallStreamOptions, + private readonly filterStackFactory: FilterStackFactory, + private credentials: CallCredentials, + private callNumber: number + ) { + this.deadline = options.deadline; + this.host = options.host; + if (options.parentCall) { + if (options.flags & Propagate.CANCELLATION) { + options.parentCall.on('cancelled', () => { + this.cancelWithStatus(Status.CANCELLED, 'Cancelled by parent call'); + }); + } + if (options.flags & Propagate.DEADLINE) { + this.trace('Propagating deadline from parent: ' + options.parentCall.getDeadline()); + this.deadline = minDeadline(this.deadline, options.parentCall.getDeadline()); + } + } + this.trace('Created'); + this.runDeadlineTimer(); + } + + private trace(text: string): void { + logging.trace( + LogVerbosity.DEBUG, + TRACER_NAME, + '[' + this.callNumber + '] ' + text + ); + } + + private runDeadlineTimer() { + clearTimeout(this.deadlineTimer); + this.trace('Deadline: ' + deadlineToString(this.deadline)); + const timeout = getRelativeTimeout(this.deadline); + if (timeout !== Infinity) { + this.trace('Deadline will be reached in ' + timeout + 'ms'); + const handleDeadline = () => { + this.cancelWithStatus( + Status.DEADLINE_EXCEEDED, + 'Deadline exceeded' + ); + } + if (timeout <= 0) { + process.nextTick(handleDeadline); + } else { + this.deadlineTimer = setTimeout(handleDeadline, timeout); + } + } + } + + private outputStatus(status: StatusObject) { + if (!this.ended) { + this.ended = true; + if (!this.filterStack) { + this.filterStack = this.filterStackFactory.createFilter(); + } + clearTimeout(this.deadlineTimer); + const filteredStatus = this.filterStack.receiveTrailers(status); + this.trace('ended with status: code=' + filteredStatus.code + ' details="' + filteredStatus.details + '"'); + this.statusWatchers.forEach(watcher => watcher(filteredStatus)); + process.nextTick(() => { + this.listener?.onReceiveStatus(filteredStatus); + }); + } + } + + private sendMessageOnChild(context: MessageContext, message: Buffer): void { + if (!this.child) { + throw new Error('sendMessageonChild called with child not populated'); + } + const child = this.child; + this.writeFilterPending = true; + this.filterStack!.sendMessage(Promise.resolve({message: message, flags: context.flags})).then((filteredMessage) => { + this.writeFilterPending = false; + child.sendMessageWithContext(context, filteredMessage.message); + if (this.pendingHalfClose) { + child.halfClose(); + } + }, (status: StatusObject) => { + this.cancelWithStatus(status.code, status.details); + }); + } + + getConfig(): void { + if (this.ended) { + return; + } + if (!this.metadata || !this.listener) { + throw new Error('getConfig called before start'); + } + const configResult = this.channel.getConfig(this.method, this.metadata); + if (configResult.type === 'NONE') { + this.channel.queueCallForConfig(this); + return; + } else if (configResult.type === 'ERROR') { + if (this.metadata.getOptions().waitForReady) { + this.channel.queueCallForConfig(this); + } else { + this.outputStatus(configResult.error); + } + return; + } + // configResult.type === 'SUCCESS' + const config = configResult.config; + if (config.status !== Status.OK) { + const {code, details} = restrictControlPlaneStatusCode(config.status, 'Failed to route call to method ' + this.method); + this.outputStatus({ + code: code, + details: details, + metadata: new Metadata() + }); + return; + } + + if (config.methodConfig.timeout) { + const configDeadline = new Date(); + configDeadline.setSeconds( + configDeadline.getSeconds() + config.methodConfig.timeout.seconds + ); + configDeadline.setMilliseconds( + configDeadline.getMilliseconds() + + config.methodConfig.timeout.nanos / 1_000_000 + ); + this.deadline = minDeadline(this.deadline, configDeadline); + this.runDeadlineTimer(); + } + + this.filterStackFactory.push(config.dynamicFilterFactories); + this.filterStack = this.filterStackFactory.createFilter(); + this.filterStack.sendMetadata(Promise.resolve(this.metadata)).then(filteredMetadata => { + this.child = this.channel.createInnerCall(config, this.method, this.host, this.credentials, this.deadline); + this.trace('Created child [' + this.child.getCallNumber() + ']') + this.child.start(filteredMetadata, { + onReceiveMetadata: metadata => { + this.trace('Received metadata') + this.listener!.onReceiveMetadata(this.filterStack!.receiveMetadata(metadata)); + }, + onReceiveMessage: message => { + this.trace('Received message'); + this.readFilterPending = true; + this.filterStack!.receiveMessage(message).then(filteredMesssage => { + this.trace('Finished filtering received message'); + this.readFilterPending = false; + this.listener!.onReceiveMessage(filteredMesssage); + if (this.pendingChildStatus) { + this.outputStatus(this.pendingChildStatus); + } + }, (status: StatusObject) => { + this.cancelWithStatus(status.code, status.details); + }); + }, + onReceiveStatus: status => { + this.trace('Received status'); + if (this.readFilterPending) { + this.pendingChildStatus = status; + } else { + this.outputStatus(status); + } + } + }); + if (this.readPending) { + this.child.startRead(); + } + if (this.pendingMessage) { + this.sendMessageOnChild(this.pendingMessage.context, this.pendingMessage.message); + } else if (this.pendingHalfClose) { + this.child.halfClose(); + } + }, (status: StatusObject) => { + this.outputStatus(status); + }) + } + + reportResolverError(status: StatusObject) { + if (this.metadata?.getOptions().waitForReady) { + this.channel.queueCallForConfig(this); + } else { + this.outputStatus(status); + } + } + cancelWithStatus(status: Status, details: string): void { + this.trace('cancelWithStatus code: ' + status + ' details: "' + details + '"'); + this.child?.cancelWithStatus(status, details); + this.outputStatus({code: status, details: details, metadata: new Metadata()}); + } + getPeer(): string { + return this.child?.getPeer() ?? this.channel.getTarget(); + } + start(metadata: Metadata, listener: InterceptingListener): void { + this.trace('start called'); + this.metadata = metadata.clone(); + this.listener = listener; + this.getConfig(); + } + sendMessageWithContext(context: MessageContext, message: Buffer): void { + this.trace('write() called with message of length ' + message.length); + if (this.child) { + this.sendMessageOnChild(context, message); + } else { + this.pendingMessage = {context, message}; + } + } + startRead(): void { + this.trace('startRead called'); + if (this.child) { + this.child.startRead(); + } else { + this.readPending = true; + } + } + halfClose(): void { + this.trace('halfClose called'); + if (this.child && !this.writeFilterPending) { + this.child.halfClose(); + } else { + this.pendingHalfClose = true; + } + } + setCredentials(credentials: CallCredentials): void { + this.credentials = this.credentials.compose(credentials); + } + + addStatusWatcher(watcher: (status: StatusObject) => void) { + this.statusWatchers.push(watcher); + } + + getCallNumber(): number { + return this.callNumber; + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/resolving-load-balancer.ts b/packages/grpc-js/src/resolving-load-balancer.ts index 94dd8c4a9..a39606f2c 100644 --- a/packages/grpc-js/src/resolving-load-balancer.ts +++ b/packages/grpc-js/src/resolving-load-balancer.ts @@ -18,21 +18,21 @@ import { ChannelControlHelper, LoadBalancer, + LoadBalancingConfig, getFirstUsableConfig, - LoadBalancingConfig } from './load-balancer'; import { ServiceConfig, validateServiceConfig } from './service-config'; -import { ConnectivityState } from './channel'; +import { ConnectivityState } from './connectivity-state'; import { ConfigSelector, createResolver, Resolver } from './resolver'; import { ServiceError } from './call'; import { Picker, UnavailablePicker, QueuePicker } from './picker'; -import { BackoffTimeout } from './backoff-timeout'; +import { BackoffOptions, BackoffTimeout } from './backoff-timeout'; import { Status } from './constants'; -import { StatusObject } from './call-stream'; +import { StatusObject } from './call-interface'; import { Metadata } from './metadata'; import * as logging from './logging'; import { LogVerbosity } from './constants'; -import { SubchannelAddress } from './subchannel'; +import { SubchannelAddress } from './subchannel-address'; import { GrpcUri, uriToString } from './uri-parser'; import { ChildLoadBalancerHandler } from './load-balancer-child-handler'; import { ChannelOptions } from './channel-options'; @@ -46,34 +46,44 @@ function trace(text: string): void { const DEFAULT_LOAD_BALANCER_NAME = 'pick_first'; -function getDefaultConfigSelector(serviceConfig: ServiceConfig | null): ConfigSelector { - return function defaultConfigSelector(methodName: string, metadata: Metadata) { - const splitName = methodName.split('/').filter(x => x.length > 0); +function getDefaultConfigSelector( + serviceConfig: ServiceConfig | null +): ConfigSelector { + return function defaultConfigSelector( + methodName: string, + metadata: Metadata + ) { + const splitName = methodName.split('/').filter((x) => x.length > 0); const service = splitName[0] ?? ''; const method = splitName[1] ?? ''; if (serviceConfig && serviceConfig.methodConfig) { for (const methodConfig of serviceConfig.methodConfig) { for (const name of methodConfig.name) { - if (name.service === service && (name.method === undefined || name.method === method)) { + if ( + name.service === service && + (name.method === undefined || name.method === method) + ) { return { methodConfig: methodConfig, pickInformation: {}, - status: Status.OK + status: Status.OK, + dynamicFilterFactories: [] }; } } } } return { - methodConfig: {name: []}, + methodConfig: { name: [] }, pickInformation: {}, - status: Status.OK + status: Status.OK, + dynamicFilterFactories: [] }; - } + }; } export interface ResolutionCallback { - (configSelector: ConfigSelector): void; + (serviceConfig: ServiceConfig, configSelector: ConfigSelector): void; } export interface ResolutionFailureCallback { @@ -162,6 +172,12 @@ export class ResolvingLoadBalancer implements LoadBalancer { this.latestChildPicker = picker; this.updateState(newState, picker); }, + addChannelzChild: channelControlHelper.addChannelzChild.bind( + channelControlHelper + ), + removeChannelzChild: channelControlHelper.removeChannelzChild.bind( + channelControlHelper + ) }); this.innerResolver = createResolver( target, @@ -201,7 +217,10 @@ export class ResolvingLoadBalancer implements LoadBalancer { } const workingConfigList = workingServiceConfig?.loadBalancingConfig ?? []; - const loadBalancingConfig = getFirstUsableConfig(workingConfigList, true); + const loadBalancingConfig = getFirstUsableConfig( + workingConfigList, + true + ); if (loadBalancingConfig === null) { // There were load balancing configs but none are supported. This counts as a resolution failure this.handleResolutionFailure({ @@ -217,8 +236,12 @@ export class ResolvingLoadBalancer implements LoadBalancer { loadBalancingConfig, attributes ); - const finalServiceConfig = workingServiceConfig ?? this.defaultServiceConfig; - this.onSuccessfulResolution(configSelector ?? getDefaultConfigSelector(finalServiceConfig)); + const finalServiceConfig = + workingServiceConfig ?? this.defaultServiceConfig; + this.onSuccessfulResolution( + finalServiceConfig, + configSelector ?? getDefaultConfigSelector(finalServiceConfig) + ); }, onError: (error: StatusObject) => { this.handleResolutionFailure(error); @@ -226,7 +249,10 @@ export class ResolvingLoadBalancer implements LoadBalancer { }, channelOptions ); - + const backoffOptions: BackoffOptions = { + initialDelay: channelOptions['grpc.initial_reconnect_backoff_ms'], + maxDelay: channelOptions['grpc.max_reconnect_backoff_ms'], + }; this.backoffTimeout = new BackoffTimeout(() => { if (this.continueResolving) { this.updateResolution(); @@ -234,7 +260,7 @@ export class ResolvingLoadBalancer implements LoadBalancer { } else { this.updateState(this.latestChildState, this.latestChildPicker); } - }); + }, backoffOptions); this.backoffTimeout.unref(); } @@ -243,6 +269,7 @@ export class ResolvingLoadBalancer implements LoadBalancer { if (this.currentState === ConnectivityState.IDLE) { this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); } + this.backoffTimeout.runOnce(); } private updateState(connectivityState: ConnectivityState, picker: Picker) { @@ -269,25 +296,23 @@ export class ResolvingLoadBalancer implements LoadBalancer { ); this.onFailedResolution(error); } - this.backoffTimeout.runOnce(); } exitIdle() { - this.childLoadBalancer.exitIdle(); - if (this.currentState === ConnectivityState.IDLE) { + if (this.currentState === ConnectivityState.IDLE || this.currentState === ConnectivityState.TRANSIENT_FAILURE) { if (this.backoffTimeout.isRunning()) { this.continueResolving = true; } else { this.updateResolution(); } - this.updateState(ConnectivityState.CONNECTING, new QueuePicker(this)); } + this.childLoadBalancer.exitIdle(); } updateAddressList( addressList: SubchannelAddress[], lbConfig: LoadBalancingConfig | null - ) { + ): never { throw new Error('updateAddressList not supported on ResolvingLoadBalancer'); } diff --git a/packages/grpc-js/src/retrying-call.ts b/packages/grpc-js/src/retrying-call.ts new file mode 100644 index 000000000..5ae585b9e --- /dev/null +++ b/packages/grpc-js/src/retrying-call.ts @@ -0,0 +1,671 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { CallCredentials } from "./call-credentials"; +import { LogVerbosity, Status } from "./constants"; +import { Deadline } from "./deadline"; +import { Metadata } from "./metadata"; +import { CallConfig } from "./resolver"; +import * as logging from './logging'; +import { Call, InterceptingListener, MessageContext, StatusObject, WriteCallback, WriteObject } from "./call-interface"; +import { LoadBalancingCall, StatusObjectWithProgress } from "./load-balancing-call"; +import { InternalChannel } from "./internal-channel"; + +const TRACER_NAME = 'retrying_call'; + +export class RetryThrottler { + private tokens: number; + constructor(private readonly maxTokens: number, private readonly tokenRatio: number, previousRetryThrottler?: RetryThrottler) { + if (previousRetryThrottler) { + /* When carrying over tokens from a previous config, rescale them to the + * new max value */ + this.tokens = previousRetryThrottler.tokens * (maxTokens / previousRetryThrottler.maxTokens); + } else { + this.tokens = maxTokens; + } + } + + addCallSucceeded() { + this.tokens = Math.max(this.tokens + this.tokenRatio, this.maxTokens); + } + + addCallFailed() { + this.tokens = Math.min(this.tokens - 1, 0); + } + + canRetryCall() { + return this.tokens > this.maxTokens / 2; + } +} + +export class MessageBufferTracker { + private totalAllocated: number = 0; + private allocatedPerCall: Map = new Map(); + + constructor(private totalLimit: number, private limitPerCall: number) {} + + allocate(size: number, callId: number): boolean { + const currentPerCall = this.allocatedPerCall.get(callId) ?? 0; + if (this.limitPerCall - currentPerCall < size || this.totalLimit - this.totalAllocated < size) { + return false; + } + this.allocatedPerCall.set(callId, currentPerCall + size); + this.totalAllocated += size; + return true; + } + + free(size: number, callId: number) { + if (this.totalAllocated < size) { + throw new Error(`Invalid buffer allocation state: call ${callId} freed ${size} > total allocated ${this.totalAllocated}`); + } + this.totalAllocated -= size; + const currentPerCall = this.allocatedPerCall.get(callId) ?? 0; + if (currentPerCall < size) { + throw new Error(`Invalid buffer allocation state: call ${callId} freed ${size} > allocated for call ${currentPerCall}`); + } + this.allocatedPerCall.set(callId, currentPerCall - size); + } + + freeAll(callId: number) { + const currentPerCall = this.allocatedPerCall.get(callId) ?? 0; + if (this.totalAllocated < currentPerCall) { + throw new Error(`Invalid buffer allocation state: call ${callId} allocated ${currentPerCall} > total allocated ${this.totalAllocated}`); + } + this.totalAllocated -= currentPerCall; + this.allocatedPerCall.delete(callId); + } +} + +type UnderlyingCallState = 'ACTIVE' | 'COMPLETED'; + +interface UnderlyingCall { + state: UnderlyingCallState; + call: LoadBalancingCall; + nextMessageToSend: number; +} + +/** + * A retrying call can be in one of these states: + * RETRY: Retries are configured and new attempts may be sent + * HEDGING: Hedging is configured and new attempts may be sent + * TRANSPARENT_ONLY: Neither retries nor hedging are configured, and + * transparent retry attempts may still be sent + * COMMITTED: One attempt is committed, and no new attempts will be + * sent + */ +type RetryingCallState = 'RETRY' | 'HEDGING' | 'TRANSPARENT_ONLY' | 'COMMITTED'; + +/** + * The different types of objects that can be stored in the write buffer, with + * the following meanings: + * MESSAGE: This is a message to be sent. + * HALF_CLOSE: When this entry is reached, the calls should send a half-close. + * FREED: This slot previously contained a message that has been sent on all + * child calls and is no longer needed. + */ +type WriteBufferEntryType = 'MESSAGE' | 'HALF_CLOSE' | 'FREED'; + +/** + * Entry in the buffer of messages to send to the remote end. + */ +interface WriteBufferEntry { + entryType: WriteBufferEntryType; + /** + * Message to send. + * Only populated if entryType is MESSAGE. + */ + message?: WriteObject; + /** + * Callback to call after sending the message. + * Only populated if entryType is MESSAGE and the call is in the COMMITTED + * state. + */ + callback?: WriteCallback; + /** + * Indicates whether the message is allocated in the buffer tracker. Ignored + * if entryType is not MESSAGE. Should be the return value of + * bufferTracker.allocate. + */ + allocated: boolean; +} + +const PREVIONS_RPC_ATTEMPTS_METADATA_KEY = 'grpc-previous-rpc-attempts'; + +export class RetryingCall implements Call { + private state: RetryingCallState; + private listener: InterceptingListener | null = null; + private initialMetadata: Metadata | null = null; + private underlyingCalls: UnderlyingCall[] = []; + private writeBuffer: WriteBufferEntry[] = []; + /** + * The offset of message indices in the writeBuffer. For example, if + * writeBufferOffset is 10, message 10 is in writeBuffer[0] and message 15 + * is in writeBuffer[5]. + */ + private writeBufferOffset = 0; + /** + * Tracks whether a read has been started, so that we know whether to start + * reads on new child calls. This only matters for the first read, because + * once a message comes in the child call becomes committed and there will + * be no new child calls. + */ + private readStarted = false; + private transparentRetryUsed: boolean = false; + /** + * Number of attempts so far + */ + private attempts: number = 0; + private hedgingTimer: NodeJS.Timer | null = null; + private committedCallIndex: number | null = null; + private initialRetryBackoffSec = 0; + private nextRetryBackoffSec = 0; + constructor( + private readonly channel: InternalChannel, + private readonly callConfig: CallConfig, + private readonly methodName: string, + private readonly host: string, + private readonly credentials: CallCredentials, + private readonly deadline: Deadline, + private readonly callNumber: number, + private readonly bufferTracker: MessageBufferTracker, + private readonly retryThrottler?: RetryThrottler + ) { + if (callConfig.methodConfig.retryPolicy) { + this.state = 'RETRY'; + const retryPolicy = callConfig.methodConfig.retryPolicy; + this.nextRetryBackoffSec = this.initialRetryBackoffSec = Number(retryPolicy.initialBackoff.substring(0, retryPolicy.initialBackoff.length - 1)); + } else if (callConfig.methodConfig.hedgingPolicy) { + this.state = 'HEDGING'; + } else { + this.state = 'TRANSPARENT_ONLY'; + } + } + getCallNumber(): number { + return this.callNumber; + } + + private trace(text: string): void { + logging.trace( + LogVerbosity.DEBUG, + TRACER_NAME, + '[' + this.callNumber + '] ' + text + ); + } + + private reportStatus(statusObject: StatusObject) { + this.trace('ended with status: code=' + statusObject.code + ' details="' + statusObject.details + '"'); + this.bufferTracker.freeAll(this.callNumber); + this.writeBufferOffset = this.writeBufferOffset + this.writeBuffer.length; + this.writeBuffer = []; + process.nextTick(() => { + // Explicitly construct status object to remove progress field + this.listener?.onReceiveStatus({ + code: statusObject.code, + details: statusObject.details, + metadata: statusObject.metadata + }); + }); + } + + cancelWithStatus(status: Status, details: string): void { + this.trace('cancelWithStatus code: ' + status + ' details: "' + details + '"'); + this.reportStatus({code: status, details, metadata: new Metadata()}); + for (const {call} of this.underlyingCalls) { + call.cancelWithStatus(status, details); + } + } + getPeer(): string { + if (this.committedCallIndex !== null) { + return this.underlyingCalls[this.committedCallIndex].call.getPeer(); + } else { + return 'unknown'; + } + } + + private getBufferEntry(messageIndex: number): WriteBufferEntry { + return this.writeBuffer[messageIndex - this.writeBufferOffset] ?? {entryType: 'FREED', allocated: false}; + } + + private getNextBufferIndex() { + return this.writeBufferOffset + this.writeBuffer.length; + } + + private clearSentMessages() { + if (this.state !== 'COMMITTED') { + return; + } + const earliestNeededMessageIndex = this.underlyingCalls[this.committedCallIndex!].nextMessageToSend; + for (let messageIndex = this.writeBufferOffset; messageIndex < earliestNeededMessageIndex; messageIndex++) { + const bufferEntry = this.getBufferEntry(messageIndex); + if (bufferEntry.allocated) { + this.bufferTracker.free(bufferEntry.message!.message.length, this.callNumber); + } + } + this.writeBuffer = this.writeBuffer.slice(earliestNeededMessageIndex - this.writeBufferOffset); + this.writeBufferOffset = earliestNeededMessageIndex; + } + + private commitCall(index: number) { + if (this.state === 'COMMITTED') { + return; + } + if (this.underlyingCalls[index].state === 'COMPLETED') { + return; + } + this.trace('Committing call [' + this.underlyingCalls[index].call.getCallNumber() + '] at index ' + index); + this.state = 'COMMITTED'; + this.committedCallIndex = index; + for (let i = 0; i < this.underlyingCalls.length; i++) { + if (i === index) { + continue; + } + if (this.underlyingCalls[i].state === 'COMPLETED') { + continue; + } + this.underlyingCalls[i].state = 'COMPLETED'; + this.underlyingCalls[i].call.cancelWithStatus(Status.CANCELLED, 'Discarded in favor of other hedged attempt'); + } + this.clearSentMessages(); + } + + private commitCallWithMostMessages() { + if (this.state === 'COMMITTED') { + return; + } + let mostMessages = -1; + let callWithMostMessages = -1; + for (const [index, childCall] of this.underlyingCalls.entries()) { + if (childCall.state === 'ACTIVE' && childCall.nextMessageToSend > mostMessages) { + mostMessages = childCall.nextMessageToSend; + callWithMostMessages = index; + } + } + if (callWithMostMessages === -1) { + /* There are no active calls, disable retries to force the next call that + * is started to be committed. */ + this.state = 'TRANSPARENT_ONLY'; + } else { + this.commitCall(callWithMostMessages); + } + } + + private isStatusCodeInList(list: (Status | string)[], code: Status) { + return list.some((value => value === code || value.toString().toLowerCase() === Status[code].toLowerCase())); + } + + private getNextRetryBackoffMs() { + const retryPolicy = this.callConfig?.methodConfig.retryPolicy; + if (!retryPolicy) { + return 0; + } + const nextBackoffMs = Math.random() * this.nextRetryBackoffSec * 1000; + const maxBackoffSec = Number(retryPolicy.maxBackoff.substring(0, retryPolicy.maxBackoff.length - 1)); + this.nextRetryBackoffSec = Math.min(this.nextRetryBackoffSec * retryPolicy.backoffMultiplier, maxBackoffSec); + return nextBackoffMs + } + + private maybeRetryCall(pushback: number | null, callback: (retried: boolean) => void) { + if (this.state !== 'RETRY') { + callback(false); + return; + } + const retryPolicy = this.callConfig!.methodConfig.retryPolicy!; + if (this.attempts >= Math.min(retryPolicy.maxAttempts, 5)) { + callback(false); + return; + } + let retryDelayMs: number; + if (pushback === null) { + retryDelayMs = this.getNextRetryBackoffMs(); + } else if (pushback < 0) { + this.state = 'TRANSPARENT_ONLY'; + callback(false); + return; + } else { + retryDelayMs = pushback; + this.nextRetryBackoffSec = this.initialRetryBackoffSec; + } + setTimeout(() => { + if (this.state !== 'RETRY') { + callback(false); + return; + } + if (this.retryThrottler?.canRetryCall() ?? true) { + callback(true); + this.attempts += 1; + this.startNewAttempt(); + } + }, retryDelayMs); + } + + private countActiveCalls(): number { + let count = 0; + for (const call of this.underlyingCalls) { + if (call?.state === 'ACTIVE') { + count += 1; + } + } + return count; + } + + private handleProcessedStatus(status: StatusObject, callIndex: number, pushback: number | null) { + switch (this.state) { + case 'COMMITTED': + case 'TRANSPARENT_ONLY': + this.commitCall(callIndex); + this.reportStatus(status); + break; + case 'HEDGING': + if (this.isStatusCodeInList(this.callConfig!.methodConfig.hedgingPolicy!.nonFatalStatusCodes ?? [], status.code)) { + this.retryThrottler?.addCallFailed(); + let delayMs: number; + if (pushback === null) { + delayMs = 0; + } else if (pushback < 0) { + this.state = 'TRANSPARENT_ONLY'; + this.commitCall(callIndex); + this.reportStatus(status); + return; + } else { + delayMs = pushback; + } + setTimeout(() => { + this.maybeStartHedgingAttempt(); + // If after trying to start a call there are no active calls, this was the last one + if (this.countActiveCalls() === 0) { + this.commitCall(callIndex); + this.reportStatus(status); + } + }, delayMs); + } else { + this.commitCall(callIndex); + this.reportStatus(status); + } + break; + case 'RETRY': + if (this.isStatusCodeInList(this.callConfig!.methodConfig.retryPolicy!.retryableStatusCodes, status.code)) { + this.retryThrottler?.addCallFailed(); + this.maybeRetryCall(pushback, (retried) => { + if (!retried) { + this.commitCall(callIndex); + this.reportStatus(status); + } + }); + } else { + this.commitCall(callIndex); + this.reportStatus(status); + } + break; + } + } + + private getPushback(metadata: Metadata): number | null { + const mdValue = metadata.get('grpc-retry-pushback-ms'); + if (mdValue.length === 0) { + return null; + } + try { + return parseInt(mdValue[0] as string); + } catch (e) { + return -1; + } + } + + private handleChildStatus(status: StatusObjectWithProgress, callIndex: number) { + if (this.underlyingCalls[callIndex].state === 'COMPLETED') { + return; + } + this.trace('state=' + this.state + ' handling status with progress ' + status.progress + ' from child [' + this.underlyingCalls[callIndex].call.getCallNumber() + '] in state ' + this.underlyingCalls[callIndex].state); + this.underlyingCalls[callIndex].state = 'COMPLETED'; + if (status.code === Status.OK) { + this.retryThrottler?.addCallSucceeded(); + this.commitCall(callIndex); + this.reportStatus(status); + return; + } + if (this.state === 'COMMITTED') { + this.reportStatus(status); + return; + } + const pushback = this.getPushback(status.metadata); + switch (status.progress) { + case 'NOT_STARTED': + // RPC never leaves the client, always safe to retry + this.startNewAttempt(); + break; + case 'REFUSED': + // RPC reaches the server library, but not the server application logic + if (this.transparentRetryUsed) { + this.handleProcessedStatus(status, callIndex, pushback); + } else { + this.transparentRetryUsed = true; + this.startNewAttempt(); + }; + break; + case 'DROP': + this.commitCall(callIndex); + this.reportStatus(status); + break; + case 'PROCESSED': + this.handleProcessedStatus(status, callIndex, pushback); + break; + } + } + + private maybeStartHedgingAttempt() { + if (this.state !== 'HEDGING') { + return; + } + if (!this.callConfig.methodConfig.hedgingPolicy) { + return; + } + const hedgingPolicy = this.callConfig.methodConfig.hedgingPolicy; + if (this.attempts >= Math.min(hedgingPolicy.maxAttempts, 5)) { + return; + } + this.attempts += 1; + this.startNewAttempt(); + this.maybeStartHedgingTimer(); + } + + private maybeStartHedgingTimer() { + if (this.hedgingTimer) { + clearTimeout(this.hedgingTimer); + } + if (this.state !== 'HEDGING') { + return; + } + if (!this.callConfig.methodConfig.hedgingPolicy) { + return; + } + const hedgingPolicy = this.callConfig.methodConfig.hedgingPolicy; + if (this.attempts >= Math.min(hedgingPolicy.maxAttempts, 5)) { + return; + } + const hedgingDelayString = hedgingPolicy.hedgingDelay ?? '0s'; + const hedgingDelaySec = Number(hedgingDelayString.substring(0, hedgingDelayString.length - 1)); + this.hedgingTimer = setTimeout(() => { + this.maybeStartHedgingAttempt(); + }, hedgingDelaySec * 1000); + this.hedgingTimer.unref?.(); + } + + private startNewAttempt() { + const child = this.channel.createLoadBalancingCall(this.callConfig, this.methodName, this.host, this.credentials, this.deadline); + this.trace('Created child call [' + child.getCallNumber() + '] for attempt ' + this.attempts); + const index = this.underlyingCalls.length; + this.underlyingCalls.push({state: 'ACTIVE', call: child, nextMessageToSend: 0}); + const previousAttempts = this.attempts - 1; + const initialMetadata = this.initialMetadata!.clone(); + if (previousAttempts > 0) { + initialMetadata.set(PREVIONS_RPC_ATTEMPTS_METADATA_KEY, `${previousAttempts}`); + } + let receivedMetadata = false; + child.start(initialMetadata, { + onReceiveMetadata: metadata => { + this.trace('Received metadata from child [' + child.getCallNumber() + ']'); + this.commitCall(index); + receivedMetadata = true; + if (previousAttempts > 0) { + metadata.set(PREVIONS_RPC_ATTEMPTS_METADATA_KEY, `${previousAttempts}`); + } + if (this.underlyingCalls[index].state === 'ACTIVE') { + this.listener!.onReceiveMetadata(metadata); + } + }, + onReceiveMessage: message => { + this.trace('Received message from child [' + child.getCallNumber() + ']'); + this.commitCall(index); + if (this.underlyingCalls[index].state === 'ACTIVE') { + this.listener!.onReceiveMessage(message); + } + }, + onReceiveStatus: status => { + this.trace('Received status from child [' + child.getCallNumber() + ']'); + if (!receivedMetadata && previousAttempts > 0) { + status.metadata.set(PREVIONS_RPC_ATTEMPTS_METADATA_KEY, `${previousAttempts}`); + } + this.handleChildStatus(status, index); + } + }); + this.sendNextChildMessage(index); + if (this.readStarted) { + child.startRead(); + } + } + + start(metadata: Metadata, listener: InterceptingListener): void { + this.trace('start called'); + this.listener = listener; + this.initialMetadata = metadata; + this.attempts += 1; + this.startNewAttempt(); + this.maybeStartHedgingTimer(); + } + + private handleChildWriteCompleted(childIndex: number) { + const childCall = this.underlyingCalls[childIndex]; + const messageIndex = childCall.nextMessageToSend; + this.getBufferEntry(messageIndex).callback?.(); + this.clearSentMessages(); + childCall.nextMessageToSend += 1; + this.sendNextChildMessage(childIndex); + } + + private sendNextChildMessage(childIndex: number) { + const childCall = this.underlyingCalls[childIndex]; + if (childCall.state === 'COMPLETED') { + return; + } + if (this.getBufferEntry(childCall.nextMessageToSend)) { + const bufferEntry = this.getBufferEntry(childCall.nextMessageToSend); + switch (bufferEntry.entryType) { + case 'MESSAGE': + childCall.call.sendMessageWithContext({ + callback: (error) => { + // Ignore error + this.handleChildWriteCompleted(childIndex); + } + }, bufferEntry.message!.message); + break; + case 'HALF_CLOSE': + childCall.nextMessageToSend += 1; + childCall.call.halfClose(); + break; + case 'FREED': + // Should not be possible + break; + } + } + } + + sendMessageWithContext(context: MessageContext, message: Buffer): void { + this.trace('write() called with message of length ' + message.length); + const writeObj: WriteObject = { + message, + flags: context.flags, + }; + const messageIndex = this.getNextBufferIndex(); + const bufferEntry: WriteBufferEntry = { + entryType: 'MESSAGE', + message: writeObj, + allocated: this.bufferTracker.allocate(message.length, this.callNumber) + }; + this.writeBuffer.push(bufferEntry); + if (bufferEntry.allocated) { + context.callback?.(); + for (const [callIndex, call] of this.underlyingCalls.entries()) { + if (call.state === 'ACTIVE' && call.nextMessageToSend === messageIndex) { + call.call.sendMessageWithContext({ + callback: (error) => { + // Ignore error + this.handleChildWriteCompleted(callIndex); + } + }, message); + } + } + } else { + this.commitCallWithMostMessages(); + // commitCallWithMostMessages can fail if we are between ping attempts + if (this.committedCallIndex === null) { + return; + } + const call = this.underlyingCalls[this.committedCallIndex]; + bufferEntry.callback = context.callback; + if (call.state === 'ACTIVE' && call.nextMessageToSend === messageIndex) { + call.call.sendMessageWithContext({ + callback: (error) => { + // Ignore error + this.handleChildWriteCompleted(this.committedCallIndex!); + } + }, message); + } + } + } + startRead(): void { + this.trace('startRead called'); + this.readStarted = true; + for (const underlyingCall of this.underlyingCalls) { + if (underlyingCall?.state === 'ACTIVE') { + underlyingCall.call.startRead(); + } + } + } + halfClose(): void { + this.trace('halfClose called'); + const halfCloseIndex = this.getNextBufferIndex(); + this.writeBuffer.push({ + entryType: 'HALF_CLOSE', + allocated: false + }); + for (const call of this.underlyingCalls) { + if (call?.state === 'ACTIVE' && call.nextMessageToSend === halfCloseIndex) { + call.nextMessageToSend += 1; + call.call.halfClose(); + } + } + } + setCredentials(newCredentials: CallCredentials): void { + throw new Error("Method not implemented."); + } + getMethod(): string { + return this.methodName; + } + getHost(): string { + return this.host; + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/server-call.ts b/packages/grpc-js/src/server-call.ts index 7d3fe192b..48186bc29 100644 --- a/packages/grpc-js/src/server-call.ts +++ b/packages/grpc-js/src/server-call.ts @@ -18,8 +18,9 @@ import { EventEmitter } from 'events'; import * as http2 from 'http2'; import { Duplex, Readable, Writable } from 'stream'; +import * as zlib from 'zlib'; +import { promisify } from 'util'; -import { Deadline, StatusObject } from './call-stream'; import { Status, DEFAULT_MAX_SEND_MESSAGE_LENGTH, @@ -32,8 +33,13 @@ import { StreamDecoder } from './stream-decoder'; import { ObjectReadable, ObjectWritable } from './object-stream'; import { ChannelOptions } from './channel-options'; import * as logging from './logging'; +import { StatusObject, PartialStatusObject } from './call-interface'; +import { Deadline } from './deadline'; +import { getErrorCode, getErrorMessage } from './error'; const TRACER_NAME = 'server_call'; +const unzip = promisify(zlib.unzip); +const inflate = promisify(zlib.inflate); function trace(text: string): void { logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text); @@ -57,11 +63,13 @@ const deadlineUnitsToMs: DeadlineUnitIndexSignature = { u: 0.001, n: 0.000001, }; -const defaultResponseHeaders = { +const defaultCompressionHeaders = { // TODO(cjihrig): Remove these encoding headers from the default response // once compression is integrated. - [GRPC_ACCEPT_ENCODING_HEADER]: 'identity', + [GRPC_ACCEPT_ENCODING_HEADER]: 'identity,deflate,gzip', [GRPC_ENCODING_HEADER]: 'identity', +} +const defaultResponseHeaders = { [http2.constants.HTTP2_HEADER_STATUS]: http2.constants.HTTP_STATUS_OK, [http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'application/grpc+proto', }; @@ -79,29 +87,28 @@ export type ServerSurfaceCall = { getPeer(): string; sendMetadata(responseMetadata: Metadata): void; getDeadline(): Deadline; + getPath(): string; } & EventEmitter; export type ServerUnaryCall = ServerSurfaceCall & { request: RequestType; }; -export type ServerReadableStream< - RequestType, - ResponseType -> = ServerSurfaceCall & ObjectReadable; -export type ServerWritableStream< - RequestType, - ResponseType -> = ServerSurfaceCall & - ObjectWritable & { - request: RequestType; - end: (metadata?: Metadata) => void; - }; +export type ServerReadableStream = + ServerSurfaceCall & ObjectReadable; +export type ServerWritableStream = + ServerSurfaceCall & + ObjectWritable & { + request: RequestType; + end: (metadata?: Metadata) => void; + }; export type ServerDuplexStream = ServerSurfaceCall & ObjectReadable & ObjectWritable & { end: (metadata?: Metadata) => void }; -export class ServerUnaryCallImpl extends EventEmitter - implements ServerUnaryCall { +export class ServerUnaryCallImpl + extends EventEmitter + implements ServerUnaryCall +{ cancelled: boolean; constructor( @@ -125,22 +132,28 @@ export class ServerUnaryCallImpl extends EventEmitter getDeadline(): Deadline { return this.call.getDeadline(); } + + getPath(): string { + return this.call.getPath(); + } } export class ServerReadableStreamImpl extends Readable - implements ServerReadableStream { + implements ServerReadableStream +{ cancelled: boolean; constructor( private call: Http2ServerCallStream, public metadata: Metadata, - public deserialize: Deserialize + public deserialize: Deserialize, + encoding: string ) { super({ objectMode: true }); this.cancelled = false; this.call.setupSurfaceCall(this); - this.call.setupReadable(this); + this.call.setupReadable(this, encoding); } _read(size: number) { @@ -162,11 +175,16 @@ export class ServerReadableStreamImpl getDeadline(): Deadline { return this.call.getDeadline(); } + + getPath(): string { + return this.call.getPath(); + } } export class ServerWritableStreamImpl extends Writable - implements ServerWritableStream { + implements ServerWritableStream +{ cancelled: boolean; private trailingMetadata: Metadata; @@ -199,6 +217,10 @@ export class ServerWritableStreamImpl return this.call.getDeadline(); } + getPath(): string { + return this.call.getPath(); + } + _write( chunk: ResponseType, encoding: string, @@ -213,8 +235,10 @@ export class ServerWritableStreamImpl return; } } catch (err) { - err.code = Status.INTERNAL; - this.emit('error', err); + this.emit('error', { + details: getErrorMessage(err), + code: Status.INTERNAL + }); } callback(); @@ -235,12 +259,14 @@ export class ServerWritableStreamImpl this.trailingMetadata = metadata; } - super.end(); + return super.end(); } } -export class ServerDuplexStreamImpl extends Duplex - implements ServerDuplexStream { +export class ServerDuplexStreamImpl + extends Duplex + implements ServerDuplexStream +{ cancelled: boolean; private trailingMetadata: Metadata; @@ -248,13 +274,14 @@ export class ServerDuplexStreamImpl extends Duplex private call: Http2ServerCallStream, public metadata: Metadata, public serialize: Serialize, - public deserialize: Deserialize + public deserialize: Deserialize, + encoding: string ) { super({ objectMode: true }); this.cancelled = false; this.trailingMetadata = new Metadata(); this.call.setupSurfaceCall(this); - this.call.setupReadable(this); + this.call.setupReadable(this, encoding); this.on('error', (err) => { this.call.sendError(err); @@ -274,13 +301,17 @@ export class ServerDuplexStreamImpl extends Duplex return this.call.getDeadline(); } + getPath(): string { + return this.call.getPath(); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any end(metadata?: any) { if (metadata) { this.trailingMetadata = metadata; } - super.end(); + return super.end(); } } @@ -290,7 +321,6 @@ ServerDuplexStreamImpl.prototype._write = ServerWritableStreamImpl.prototype._write; ServerDuplexStreamImpl.prototype._final = ServerWritableStreamImpl.prototype._final; -ServerDuplexStreamImpl.prototype.end = ServerWritableStreamImpl.prototype.end; // Unary response callback signature. export type sendUnaryData = ( @@ -374,7 +404,8 @@ export class Http2ServerCallStream< ResponseType > extends EventEmitter { cancelled = false; - deadlineTimer: NodeJS.Timer = setTimeout(() => {}, 0); + deadlineTimer: NodeJS.Timer | null = null; + private statusSent = false; private deadline: Deadline = Infinity; private wantTrailers = false; private metadataSent = false; @@ -407,8 +438,17 @@ export class Http2ServerCallStream< ' stream closed with rstCode ' + this.stream.rstCode ); - this.cancelled = true; - this.emit('cancelled', 'cancelled'); + + if (!this.statusSent) { + this.cancelled = true; + this.emit('cancelled', 'cancelled'); + this.emit('streamEnd', false); + this.sendStatus({ + code: Status.CANCELLED, + details: 'Cancelled by client', + metadata: null, + }); + } }); this.stream.on('drain', () => { @@ -421,9 +461,6 @@ export class Http2ServerCallStream< if ('grpc.max_receive_message_length' in options) { this.maxReceiveMessageSize = options['grpc.max_receive_message_length']!; } - - // Clear noop timer - clearTimeout(this.deadlineTimer); } private checkCancelled(): boolean { @@ -435,6 +472,24 @@ export class Http2ServerCallStream< return this.cancelled; } + private getDecompressedMessage( + message: Buffer, + encoding: string + ): Buffer | Promise { + if (encoding === 'deflate') { + return inflate(message.subarray(5)); + } else if (encoding === 'gzip') { + return unzip(message.subarray(5)); + } else if (encoding === 'identity') { + return message.subarray(5); + } + + return Promise.reject({ + code: Status.UNIMPLEMENTED, + details: `Received message compressed with unsupported encoding "${encoding}"`, + }); + } + sendMetadata(customMetadata?: Metadata) { if (this.checkCancelled()) { return; @@ -447,13 +502,22 @@ export class Http2ServerCallStream< this.metadataSent = true; const custom = customMetadata ? customMetadata.toHttp2Headers() : null; // TODO(cjihrig): Include compression headers. - const headers = Object.assign({}, defaultResponseHeaders, custom); + const headers = { ...defaultResponseHeaders, ...defaultCompressionHeaders, ...custom }; this.stream.respond(headers, defaultResponseOptions); } receiveMetadata(headers: http2.IncomingHttpHeaders) { const metadata = Metadata.fromHttp2Headers(headers); + if (logging.isTracerEnabled(TRACER_NAME)) { + trace( + 'Request to ' + + this.handler.path + + ' received headers ' + + JSON.stringify(metadata.toJSON()) + ); + } + // TODO(cjihrig): Receive compression metadata. const timeoutHeader = metadata.get(GRPC_TIMEOUT_HEADER); @@ -465,7 +529,7 @@ export class Http2ServerCallStream< const err = new Error('Invalid deadline') as ServerErrorResponse; err.code = Status.OUT_OF_RANGE; this.sendError(err); - return; + return metadata; } const timeout = (+match[1] * deadlineUnitsToMs[match[2]]) | 0; @@ -480,45 +544,102 @@ export class Http2ServerCallStream< metadata.remove(http2.constants.HTTP2_HEADER_ACCEPT_ENCODING); metadata.remove(http2.constants.HTTP2_HEADER_TE); metadata.remove(http2.constants.HTTP2_HEADER_CONTENT_TYPE); - metadata.remove('grpc-encoding'); metadata.remove('grpc-accept-encoding'); return metadata; } - receiveUnaryMessage(): Promise { - return new Promise((resolve, reject) => { - const stream = this.stream; - const chunks: Buffer[] = []; - let totalLength = 0; + receiveUnaryMessage( + encoding: string, + next: ( + err: Partial | null, + request?: RequestType + ) => void + ): void { + const { stream } = this; + + let receivedLength = 0; + const call = this; + const body: Buffer[] = []; + const limit = this.maxReceiveMessageSize; + + stream.on('data', onData); + stream.on('end', onEnd); + stream.on('error', onEnd); + + function onData(chunk: Buffer) { + receivedLength += chunk.byteLength; + + if (limit !== -1 && receivedLength > limit) { + stream.removeListener('data', onData); + stream.removeListener('end', onEnd); + stream.removeListener('error', onEnd); + next({ + code: Status.RESOURCE_EXHAUSTED, + details: `Received message larger than max (${receivedLength} vs. ${limit})`, + }); + return; + } - stream.on('data', (data: Buffer) => { - chunks.push(data); - totalLength += data.byteLength; - }); + body.push(chunk); + } - stream.once('end', async () => { - try { - const requestBytes = Buffer.concat(chunks, totalLength); - if ( - this.maxReceiveMessageSize !== -1 && - requestBytes.length > this.maxReceiveMessageSize - ) { - this.sendError({ - code: Status.RESOURCE_EXHAUSTED, - details: `Received message larger than max (${requestBytes.length} vs. ${this.maxReceiveMessageSize})`, - }); - resolve(); - } - - resolve(this.deserializeMessage(requestBytes)); - } catch (err) { - err.code = Status.INTERNAL; - this.sendError(err); - resolve(); - } + function onEnd(err?: Error) { + stream.removeListener('data', onData); + stream.removeListener('end', onEnd); + stream.removeListener('error', onEnd); + + if (err !== undefined) { + next({ code: Status.INTERNAL, details: err.message }); + return; + } + + if (receivedLength === 0) { + next({ code: Status.INTERNAL, details: 'received empty unary message' }) + return; + } + + call.emit('receiveMessage'); + + const requestBytes = Buffer.concat(body, receivedLength); + const compressed = requestBytes.readUInt8(0) === 1; + const compressedMessageEncoding = compressed ? encoding : 'identity'; + const decompressedMessage = call.getDecompressedMessage( + requestBytes, + compressedMessageEncoding + ); + + if (Buffer.isBuffer(decompressedMessage)) { + call.safeDeserializeMessage(decompressedMessage, next); + return; + } + + decompressedMessage.then( + (decompressed) => call.safeDeserializeMessage(decompressed, next), + (err: any) => next( + err.code + ? err + : { + code: Status.INTERNAL, + details: `Received "grpc-encoding" header "${encoding}" but ${encoding} decompression failed`, + } + ) + ) + } + } + + private safeDeserializeMessage( + buffer: Buffer, + next: (err: Partial | null, request?: RequestType) => void + ) { + try { + next(null, this.deserializeMessage(buffer)); + } catch (err) { + next({ + details: getErrorMessage(err), + code: Status.INTERNAL }); - }); + } } serializeMessage(value: ResponseType) { @@ -534,27 +655,25 @@ export class Http2ServerCallStream< } deserializeMessage(bytes: Buffer) { - // TODO(cjihrig): Call compression aware deserializeMessage(). - const receivedMessage = bytes.slice(5); - - return this.handler.deserialize(receivedMessage); + return this.handler.deserialize(bytes); } async sendUnaryMessage( err: ServerErrorResponse | ServerStatusResponse | null, value?: ResponseType | null, - metadata?: Metadata, + metadata?: Metadata | null, flags?: number ) { if (this.checkCancelled()) { return; } - if (!metadata) { - metadata = new Metadata(); + + if (metadata === undefined) { + metadata = null; } if (err) { - if (!Object.prototype.hasOwnProperty.call(err, 'metadata')) { + if (!Object.prototype.hasOwnProperty.call(err, 'metadata') && metadata) { err.metadata = metadata; } this.sendError(err); @@ -567,12 +686,16 @@ export class Http2ServerCallStream< this.write(response); this.sendStatus({ code: Status.OK, details: 'OK', metadata }); } catch (err) { - err.code = Status.INTERNAL; - this.sendError(err); + this.sendError({ + details: getErrorMessage(err), + code: Status.INTERNAL + }); } } - sendStatus(statusObj: StatusObject) { + sendStatus(statusObj: PartialStatusObject) { + this.emit('callEnd', statusObj.code); + this.emit('streamEnd', statusObj.code === Status.OK); if (this.checkCancelled()) { return; } @@ -586,37 +709,44 @@ export class Http2ServerCallStream< statusObj.details ); - clearTimeout(this.deadlineTimer); + if (this.deadlineTimer) clearTimeout(this.deadlineTimer); - if (!this.wantTrailers) { - this.wantTrailers = true; - this.stream.once('wantTrailers', () => { - const trailersToSend = Object.assign( - { + if (this.stream.headersSent) { + if (!this.wantTrailers) { + this.wantTrailers = true; + this.stream.once('wantTrailers', () => { + const trailersToSend = { [GRPC_STATUS_HEADER]: statusObj.code, - [GRPC_MESSAGE_HEADER]: encodeURI(statusObj.details as string), - }, - statusObj.metadata.toHttp2Headers() - ); - - this.stream.sendTrailers(trailersToSend); - }); - this.sendMetadata(); - this.stream.end(); + [GRPC_MESSAGE_HEADER]: encodeURI(statusObj.details), + ...statusObj.metadata?.toHttp2Headers(), + }; + + this.stream.sendTrailers(trailersToSend); + this.statusSent = true; + }); + this.stream.end(); + } + } else { + // Trailers-only response + const trailersToSend = { + [GRPC_STATUS_HEADER]: statusObj.code, + [GRPC_MESSAGE_HEADER]: encodeURI(statusObj.details), + ...defaultResponseHeaders, + ...statusObj.metadata?.toHttp2Headers(), + }; + this.stream.respond(trailersToSend, {endStream: true}); + this.statusSent = true; } } sendError(error: ServerErrorResponse | ServerStatusResponse) { - if (this.checkCancelled()) { - return; - } - const status: StatusObject = { + const status: PartialStatusObject = { code: Status.UNKNOWN, details: 'message' in error ? error.message : 'Unknown Error', metadata: 'metadata' in error && error.metadata !== undefined ? error.metadata - : new Metadata(), + : null, }; if ( @@ -651,6 +781,7 @@ export class Http2ServerCallStream< } this.sendMetadata(); + this.emit('sendMessage'); return this.stream.write(chunk); } @@ -663,18 +794,36 @@ export class Http2ServerCallStream< call.cancelled = true; call.emit('cancelled', reason); }); + + this.once('callEnd', (status) => call.emit('callEnd', status)); } setupReadable( readable: | ServerReadableStream - | ServerDuplexStream + | ServerDuplexStream, + encoding: string ) { const decoder = new StreamDecoder(); + let readsDone = false; + + let pendingMessageProcessing = false; + + let pushedEnd = false; + + const maybePushEnd = async () => { + if (!pushedEnd && readsDone && !pendingMessageProcessing) { + pushedEnd = true; + await this.pushOrBufferMessage(readable, null); + } + }; + this.stream.on('data', async (data: Buffer) => { const messages = decoder.write(data); + pendingMessageProcessing = true; + this.stream.pause(); for (const message of messages) { if ( this.maxReceiveMessageSize !== -1 && @@ -686,12 +835,29 @@ export class Http2ServerCallStream< }); return; } - this.pushOrBufferMessage(readable, message); + this.emit('receiveMessage'); + + const compressed = message.readUInt8(0) === 1; + const compressedMessageEncoding = compressed ? encoding : 'identity'; + const decompressedMessage = await this.getDecompressedMessage( + message, + compressedMessageEncoding + ); + + // Encountered an error with decompression; it'll already have been propogated back + // Just return early + if (!decompressedMessage) return; + + await this.pushOrBufferMessage(readable, decompressedMessage); } + pendingMessageProcessing = false; + this.stream.resume(); + await maybePushEnd(); }); - this.stream.once('end', () => { - this.pushOrBufferMessage(readable, null); + this.stream.once('end', async () => { + readsDone = true; + await maybePushEnd(); }); } @@ -715,16 +881,16 @@ export class Http2ServerCallStream< return this.canPush; } - private pushOrBufferMessage( + private async pushOrBufferMessage( readable: | ServerReadableStream | ServerDuplexStream, messageBytes: Buffer | null - ): void { + ): Promise { if (this.isPushPending) { this.bufferedMessages.push(messageBytes); } else { - this.pushMessage(readable, messageBytes); + await this.pushMessage(readable, messageBytes); } } @@ -735,6 +901,7 @@ export class Http2ServerCallStream< messageBytes: Buffer | null ) { if (messageBytes === null) { + trace('Received end of stream'); if (this.canPush) { readable.push(null); } else { @@ -744,6 +911,8 @@ export class Http2ServerCallStream< return; } + trace('Received message of length ' + messageBytes.length); + this.isPushPending = true; try { @@ -760,27 +929,21 @@ export class Http2ServerCallStream< } catch (error) { // Ignore any remaining messages when errors occur. this.bufferedMessages.length = 0; - - if ( - !( - 'code' in error && - typeof error.code === 'number' && - Number.isInteger(error.code) && - error.code >= Status.OK && - error.code <= Status.UNAUTHENTICATED - ) - ) { - // The error code is not a valid gRPC code so its being overwritten. - error.code = Status.INTERNAL; + let code = getErrorCode(error); + if (code === null || code < Status.OK || code > Status.UNAUTHENTICATED) { + code = Status.INTERNAL } - readable.emit('error', error); + readable.emit('error', { + details: getErrorMessage(error), + code: code + }); } this.isPushPending = false; if (this.bufferedMessages.length > 0) { - this.pushMessage( + await this.pushMessage( readable, this.bufferedMessages.shift() as Buffer | null ); @@ -803,6 +966,10 @@ export class Http2ServerCallStream< getDeadline(): Deadline { return this.deadline; } + + getPath(): string { + return this.handler.path; + } } /* eslint-disable @typescript-eslint/no-explicit-any */ diff --git a/packages/grpc-js/src/server.ts b/packages/grpc-js/src/server.ts index 255e210b6..d19186a75 100644 --- a/packages/grpc-js/src/server.ts +++ b/packages/grpc-js/src/server.ts @@ -56,14 +56,22 @@ import { TcpSubchannelAddress, isTcpSubchannelAddress, subchannelAddressToString, -} from './subchannel'; + stringToSubchannelAddress, +} from './subchannel-address'; import { parseUri } from './uri-parser'; +import { ChannelzCallTracker, ChannelzChildrenTracker, ChannelzTrace, registerChannelzServer, registerChannelzSocket, ServerInfo, ServerRef, SocketInfo, SocketRef, TlsInfo, unregisterChannelzRef } from './channelz'; +import { CipherNameAndProtocol, TLSSocket } from 'tls'; +import { getErrorCode, getErrorMessage } from './error'; -const TRACER_NAME = 'server'; +const UNLIMITED_CONNECTION_AGE_MS = ~(1<<31); +const KEEPALIVE_MAX_TIME_MS = ~(1<<31); +const KEEPALIVE_TIMEOUT_MS = 20000; -function trace(text: string): void { - logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text); -} +const { + HTTP2_HEADER_PATH +} = http2.constants + +const TRACER_NAME = 'server'; interface BindResult { port: number; @@ -78,7 +86,6 @@ function getUnimplementedStatusResponse( return { code: Status.UNIMPLEMENTED, details: `The server does not implement the method ${methodName}`, - metadata: new Metadata(), }; } @@ -125,22 +132,119 @@ function getDefaultHandler(handlerType: HandlerType, methodName: string) { } } +interface ChannelzSessionInfo { + ref: SocketRef; + streamTracker: ChannelzCallTracker; + messagesSent: number; + messagesReceived: number; + lastMessageSentTimestamp: Date | null; + lastMessageReceivedTimestamp: Date | null; +} + +interface ChannelzListenerInfo { + ref: SocketRef; +} + export class Server { - private http2ServerList: (http2.Http2Server | http2.Http2SecureServer)[] = []; + private http2ServerList: { server: (http2.Http2Server | http2.Http2SecureServer), channelzRef: SocketRef }[] = []; private handlers: Map = new Map< string, UntypedHandler >(); - private sessions = new Set(); + private sessions = new Map(); private started = false; private options: ChannelOptions; + private serverAddressString: string = 'null' + + // Channelz Info + private readonly channelzEnabled: boolean = true; + private channelzRef: ServerRef; + private channelzTrace = new ChannelzTrace(); + private callTracker = new ChannelzCallTracker(); + private listenerChildrenTracker = new ChannelzChildrenTracker(); + private sessionChildrenTracker = new ChannelzChildrenTracker(); + + private readonly maxConnectionAgeMs: number; + private readonly maxConnectionAgeGraceMs: number; + + private readonly keepaliveTimeMs: number; + private readonly keepaliveTimeoutMs: number; constructor(options?: ChannelOptions) { this.options = options ?? {}; + if (this.options['grpc.enable_channelz'] === 0) { + this.channelzEnabled = false; + } + this.channelzRef = registerChannelzServer(() => this.getChannelzInfo(), this.channelzEnabled); + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Server created'); + } + this.maxConnectionAgeMs = this.options['grpc.max_connection_age_ms'] ?? UNLIMITED_CONNECTION_AGE_MS; + this.maxConnectionAgeGraceMs = this.options['grpc.max_connection_age_grace_ms'] ?? UNLIMITED_CONNECTION_AGE_MS; + this.keepaliveTimeMs = this.options['grpc.keepalive_time_ms'] ?? KEEPALIVE_MAX_TIME_MS; + this.keepaliveTimeoutMs = this.options['grpc.keepalive_timeout_ms'] ?? KEEPALIVE_TIMEOUT_MS; + this.trace('Server constructed'); + } + + private getChannelzInfo(): ServerInfo { + return { + trace: this.channelzTrace, + callTracker: this.callTracker, + listenerChildren: this.listenerChildrenTracker.getChildLists(), + sessionChildren: this.sessionChildrenTracker.getChildLists() + }; } - addProtoService(): void { + private getChannelzSessionInfoGetter(session: http2.ServerHttp2Session): () => SocketInfo { + return () => { + const sessionInfo = this.sessions.get(session)!; + const sessionSocket = session.socket; + const remoteAddress = sessionSocket.remoteAddress ? stringToSubchannelAddress(sessionSocket.remoteAddress, sessionSocket.remotePort) : null; + const localAddress = sessionSocket.localAddress ? stringToSubchannelAddress(sessionSocket.localAddress!, sessionSocket.localPort) : null; + let tlsInfo: TlsInfo | null; + if (session.encrypted) { + const tlsSocket: TLSSocket = sessionSocket as TLSSocket; + const cipherInfo: CipherNameAndProtocol & {standardName?: string} = tlsSocket.getCipher(); + const certificate = tlsSocket.getCertificate(); + const peerCertificate = tlsSocket.getPeerCertificate(); + tlsInfo = { + cipherSuiteStandardName: cipherInfo.standardName ?? null, + cipherSuiteOtherName: cipherInfo.standardName ? null : cipherInfo.name, + localCertificate: (certificate && 'raw' in certificate) ? certificate.raw : null, + remoteCertificate: (peerCertificate && 'raw' in peerCertificate) ? peerCertificate.raw : null + }; + } else { + tlsInfo = null; + } + const socketInfo: SocketInfo = { + remoteAddress: remoteAddress, + localAddress: localAddress, + security: tlsInfo, + remoteName: null, + streamsStarted: sessionInfo.streamTracker.callsStarted, + streamsSucceeded: sessionInfo.streamTracker.callsSucceeded, + streamsFailed: sessionInfo.streamTracker.callsFailed, + messagesSent: sessionInfo.messagesSent, + messagesReceived: sessionInfo.messagesReceived, + keepAlivesSent: 0, + lastLocalStreamCreatedTimestamp: null, + lastRemoteStreamCreatedTimestamp: sessionInfo.streamTracker.lastCallStartedTimestamp, + lastMessageSentTimestamp: sessionInfo.lastMessageSentTimestamp, + lastMessageReceivedTimestamp: sessionInfo.lastMessageReceivedTimestamp, + localFlowControlWindow: session.state.localWindowSize ?? null, + remoteFlowControlWindow: session.state.remoteWindowSize ?? null + }; + return socketInfo; + }; + } + + private trace(text: string): void { + logging.trace(LogVerbosity.DEBUG, TRACER_NAME, '(' + this.channelzRef.id + ') ' + text); + } + + + addProtoService(): never { throw new Error('Not implemented. Use addService() instead'); } @@ -209,10 +313,7 @@ export class Server { } removeService(service: ServiceDefinition): void { - if ( - service === null || - typeof service !== 'object' - ) { + if (service === null || typeof service !== 'object') { throw new Error('removeService() requires object as argument'); } @@ -223,7 +324,7 @@ export class Server { }); } - bind(port: string, creds: ServerCredentials): void { + bind(port: string, creds: ServerCredentials): never { throw new Error('Not implemented. Use bindAsync() instead'); } @@ -240,8 +341,8 @@ export class Server { throw new TypeError('port must be a string'); } - if (creds === null || typeof creds !== 'object') { - throw new TypeError('creds must be an object'); + if (creds === null || !(creds instanceof ServerCredentials)) { + throw new TypeError('creds must be a ServerCredentials object'); } if (typeof callback !== 'function') { @@ -258,10 +359,18 @@ export class Server { } const serverOptions: http2.ServerOptions = { - maxSendHeaderBlockLength: Number.MAX_SAFE_INTEGER + maxSendHeaderBlockLength: Number.MAX_SAFE_INTEGER, }; if ('grpc-node.max_session_memory' in this.options) { - serverOptions.maxSessionMemory = this.options['grpc-node.max_session_memory']; + serverOptions.maxSessionMemory = this.options[ + 'grpc-node.max_session_memory' + ]; + } else { + /* By default, set a very large max session memory limit, to effectively + * disable enforcement of the limit. Some testing indicates that Node's + * behavior degrades badly when this limit is reached, so we solve that + * by disabling the check entirely. */ + serverOptions.maxSessionMemory = Number.MAX_SAFE_INTEGER; } if ('grpc.max_concurrent_streams' in this.options) { serverOptions.settings = { @@ -269,6 +378,10 @@ export class Server { }; } + const deferredCallback = (error: Error | null, port: number) => { + process.nextTick(() => callback(error, port)); + } + const setupServer = (): http2.Http2Server | http2.Http2SecureServer => { let http2Server: http2.Http2Server | http2.Http2SecureServer; if (creds._isSecure()) { @@ -277,6 +390,13 @@ export class Server { creds._getSettings()! ); http2Server = http2.createSecureServer(secureServerOptions); + http2Server.on('secureConnection', (socket: TLSSocket) => { + /* These errors need to be handled by the user of Http2SecureServer, + * according to https://github.com/nodejs/node/issues/35824 */ + socket.on('error', (e: Error) => { + this.trace('An incoming TLS connection closed with error: ' + e.message); + }); + }); } else { http2Server = http2.createServer(serverOptions); } @@ -296,7 +416,7 @@ export class Server { } return Promise.all( addressList.map((address) => { - trace('Attempting to bind ' + subchannelAddressToString(address)); + this.trace('Attempting to bind ' + subchannelAddressToString(address)); let addr: SubchannelAddress; if (isTcpSubchannelAddress(address)) { addr = { @@ -309,21 +429,53 @@ export class Server { const http2Server = setupServer(); return new Promise((resolve, reject) => { - function onError(err: Error): void { + const onError = (err: Error) => { + this.trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message); resolve(err); } http2Server.once('error', onError); http2Server.listen(addr, () => { - trace('Successfully bound ' + subchannelAddressToString(address)); - this.http2ServerList.push(http2Server); const boundAddress = http2Server.address()!; + let boundSubchannelAddress: SubchannelAddress; if (typeof boundAddress === 'string') { - resolve(portNum); + boundSubchannelAddress = { + path: boundAddress + }; } else { - resolve(boundAddress.port); + boundSubchannelAddress = { + host: boundAddress.address, + port: boundAddress.port + } + } + let channelzRef: SocketRef; + channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => { + return { + localAddress: boundSubchannelAddress, + remoteAddress: null, + security: null, + remoteName: null, + streamsStarted: 0, + streamsSucceeded: 0, + streamsFailed: 0, + messagesSent: 0, + messagesReceived: 0, + keepAlivesSent: 0, + lastLocalStreamCreatedTimestamp: null, + lastRemoteStreamCreatedTimestamp: null, + lastMessageSentTimestamp: null, + lastMessageReceivedTimestamp: null, + localFlowControlWindow: null, + remoteFlowControlWindow: null + }; + }, this.channelzEnabled); + if (this.channelzEnabled) { + this.listenerChildrenTracker.refChild(channelzRef); } + this.http2ServerList.push({server: http2Server, channelzRef: channelzRef}); + this.trace('Successfully bound ' + subchannelAddressToString(boundSubchannelAddress)); + resolve('port' in boundSubchannelAddress ? boundSubchannelAddress.port : portNum); http2Server.removeListener('error', onError); }); }); @@ -356,18 +508,49 @@ export class Server { const address = addressList[0]; const http2Server = setupServer(); return new Promise((resolve, reject) => { - function onError(err: Error): void { + const onError = (err: Error) => { + this.trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message); resolve(bindWildcardPort(addressList.slice(1))); } http2Server.once('error', onError); http2Server.listen(address, () => { - this.http2ServerList.push(http2Server); + const boundAddress = http2Server.address() as AddressInfo; + const boundSubchannelAddress: SubchannelAddress = { + host: boundAddress.address, + port: boundAddress.port + }; + let channelzRef: SocketRef; + channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => { + return { + localAddress: boundSubchannelAddress, + remoteAddress: null, + security: null, + remoteName: null, + streamsStarted: 0, + streamsSucceeded: 0, + streamsFailed: 0, + messagesSent: 0, + messagesReceived: 0, + keepAlivesSent: 0, + lastLocalStreamCreatedTimestamp: null, + lastRemoteStreamCreatedTimestamp: null, + lastMessageSentTimestamp: null, + lastMessageReceivedTimestamp: null, + localFlowControlWindow: null, + remoteFlowControlWindow: null + }; + }, this.channelzEnabled); + if (this.channelzEnabled) { + this.listenerChildrenTracker.refChild(channelzRef); + } + this.http2ServerList.push({server: http2Server, channelzRef: channelzRef}); + this.trace('Successfully bound ' + subchannelAddressToString(boundSubchannelAddress)); resolve( bindSpecificPort( addressList.slice(1), - (http2Server.address() as AddressInfo).port, + boundAddress.port, 1 ) ); @@ -385,7 +568,7 @@ export class Server { // We only want one resolution result. Discard all future results resolverListener.onSuccessfulResolution = () => {}; if (addressList.length === 0) { - callback(new Error(`No addresses resolved for port ${port}`), 0); + deferredCallback(new Error(`No addresses resolved for port ${port}`), 0); return; } let bindResultPromise: Promise; @@ -408,7 +591,7 @@ export class Server { if (bindResult.count === 0) { const errorString = `No address added out of total ${addressList.length} resolved`; logging.log(LogVerbosity.ERROR, errorString); - callback(new Error(errorString), 0); + deferredCallback(new Error(errorString), 0); } else { if (bindResult.count < addressList.length) { logging.log( @@ -416,18 +599,18 @@ export class Server { `WARNING Only ${bindResult.count} addresses added out of total ${addressList.length} resolved` ); } - callback(null, bindResult.port); + deferredCallback(null, bindResult.port); } }, (error) => { const errorString = `No address added out of total ${addressList.length} resolved`; logging.log(LogVerbosity.ERROR, errorString); - callback(new Error(errorString), 0); + deferredCallback(new Error(errorString), 0); } ); }, onError: (error) => { - callback(new Error(error.details), 0); + deferredCallback(new Error(error.details), 0); }, }; @@ -438,9 +621,14 @@ export class Server { forceShutdown(): void { // Close the server if it is still running. - for (const http2Server of this.http2ServerList) { + for (const {server: http2Server, channelzRef: ref} of this.http2ServerList) { if (http2Server.listening) { - http2Server.close(); + http2Server.close(() => { + if (this.channelzEnabled) { + this.listenerChildrenTracker.unrefChild(ref); + unregisterChannelzRef(ref); + } + }); } } @@ -448,13 +636,16 @@ export class Server { // Always destroy any available sessions. It's possible that one or more // tryShutdown() calls are in progress. Don't wait on them to finish. - this.sessions.forEach((session) => { + this.sessions.forEach((channelzInfo, session) => { // Cast NGHTTP2_CANCEL to any because TypeScript doesn't seem to // recognize destroy(code) as a valid signature. // eslint-disable-next-line @typescript-eslint/no-explicit-any session.destroy(http2.constants.NGHTTP2_CANCEL as any); }); this.sessions.clear(); + if (this.channelzEnabled) { + unregisterChannelzRef(this.channelzRef); + } } register( @@ -486,7 +677,7 @@ export class Server { if ( this.http2ServerList.length === 0 || this.http2ServerList.every( - (http2Server) => http2Server.listening !== true + ({server: http2Server}) => http2Server.listening !== true ) ) { throw new Error('server must be bound in order to start'); @@ -495,197 +686,419 @@ export class Server { if (this.started === true) { throw new Error('server is already started'); } - + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Starting'); + } this.started = true; } tryShutdown(callback: (error?: Error) => void): void { + const wrappedCallback = (error?: Error) => { + if (this.channelzEnabled) { + unregisterChannelzRef(this.channelzRef); + } + callback(error); + }; let pendingChecks = 0; function maybeCallback(): void { pendingChecks--; if (pendingChecks === 0) { - callback(); + wrappedCallback(); } } // Close the server if necessary. this.started = false; - for (const http2Server of this.http2ServerList) { + for (const {server: http2Server, channelzRef: ref} of this.http2ServerList) { if (http2Server.listening) { pendingChecks++; - http2Server.close(maybeCallback); + http2Server.close(() => { + if (this.channelzEnabled) { + this.listenerChildrenTracker.unrefChild(ref); + unregisterChannelzRef(ref); + } + maybeCallback(); + }); } } - this.sessions.forEach((session) => { + this.sessions.forEach((channelzInfo, session) => { if (!session.closed) { pendingChecks += 1; session.close(maybeCallback); } }); if (pendingChecks === 0) { - callback(); + wrappedCallback(); } } - addHttp2Port(): void { + addHttp2Port(): never { throw new Error('Not yet implemented'); } - private _setupHandlers( - http2Server: http2.Http2Server | http2.Http2SecureServer - ): void { - if (http2Server === null) { - return; + /** + * Get the channelz reference object for this server. The returned value is + * garbage if channelz is disabled for this server. + * @returns + */ + getChannelzRef() { + return this.channelzRef; + } + + private _verifyContentType(stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders): boolean { + const contentType = headers[http2.constants.HTTP2_HEADER_CONTENT_TYPE]; + + if ( + typeof contentType !== 'string' || + !contentType.startsWith('application/grpc') + ) { + stream.respond( + { + [http2.constants.HTTP2_HEADER_STATUS]: + http2.constants.HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, + }, + { endStream: true } + ); + return false } - http2Server.on( - 'stream', - (stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders) => { - const contentType = headers[http2.constants.HTTP2_HEADER_CONTENT_TYPE]; - - if ( - typeof contentType !== 'string' || - !contentType.startsWith('application/grpc') - ) { - stream.respond( - { - [http2.constants.HTTP2_HEADER_STATUS]: - http2.constants.HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, - }, - { endStream: true } - ); - return; - } + return true + } - try { - const path = headers[http2.constants.HTTP2_HEADER_PATH] as string; - const serverAddress = http2Server.address(); - let serverAddressString = 'null'; - if (serverAddress) { - if (typeof serverAddress === 'string') { - serverAddressString = serverAddress; - } else { - serverAddressString = - serverAddress.address + ':' + serverAddress.port; - } - } - trace( - 'Received call to method ' + - path + - ' at address ' + - serverAddressString - ); - const handler = this.handlers.get(path); + private _retrieveHandler(headers: http2.IncomingHttpHeaders): Handler { + const path = headers[HTTP2_HEADER_PATH] as string - if (handler === undefined) { - trace( - 'No handler registered for method ' + - path + - '. Sending UNIMPLEMENTED status.' - ); - throw getUnimplementedStatusResponse(path); - } + this.trace( + 'Received call to method ' + + path + + ' at address ' + + this.serverAddressString + ); - const call = new Http2ServerCallStream(stream, handler, this.options); - const metadata: Metadata = call.receiveMetadata(headers) as Metadata; - switch (handler.type) { - case 'unary': - handleUnary(call, handler as UntypedUnaryHandler, metadata); - break; - case 'clientStream': - handleClientStreaming( - call, - handler as UntypedClientStreamingHandler, - metadata - ); - break; - case 'serverStream': - handleServerStreaming( - call, - handler as UntypedServerStreamingHandler, - metadata - ); - break; - case 'bidi': - handleBidiStreaming( - call, - handler as UntypedBidiStreamingHandler, - metadata - ); - break; - default: - throw new Error(`Unknown handler type: ${handler.type}`); - } - } catch (err) { - const call = new Http2ServerCallStream(stream, null!, this.options); + const handler = this.handlers.get(path); - if (err.code === undefined) { - err.code = Status.INTERNAL; - } + if (handler === undefined) { + this.trace( + 'No handler registered for method ' + + path + + '. Sending UNIMPLEMENTED status.' + ); + throw getUnimplementedStatusResponse(path); + } + + return handler + } + + private _respondWithError>( + err: T, + stream: http2.ServerHttp2Stream, + channelzSessionInfo: ChannelzSessionInfo | null = null + ) { + const call = new Http2ServerCallStream(stream, null!, this.options); + + if (err.code === undefined) { + err.code = Status.INTERNAL; + } + + if (this.channelzEnabled) { + this.callTracker.addCallFailed(); + channelzSessionInfo?.streamTracker.addCallFailed() + } + + call.sendError(err); + } + + private _channelzHandler(stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders) { + const channelzSessionInfo = this.sessions.get(stream.session as http2.ServerHttp2Session); + + this.callTracker.addCallStarted(); + channelzSessionInfo?.streamTracker.addCallStarted(); + + if (!this._verifyContentType(stream, headers)) { + this.callTracker.addCallFailed(); + channelzSessionInfo?.streamTracker.addCallFailed(); + return + } - call.sendError(err); + let handler: Handler + try { + handler = this._retrieveHandler(headers) + } catch (err) { + this._respondWithError({ + details: getErrorMessage(err), + code: getErrorCode(err) ?? undefined + }, stream, channelzSessionInfo) + return + } + + const call = new Http2ServerCallStream(stream, handler, this.options); + + call.once('callEnd', (code: Status) => { + if (code === Status.OK) { + this.callTracker.addCallSucceeded(); + } else { + this.callTracker.addCallFailed(); + } + }); + + if (channelzSessionInfo) { + call.once('streamEnd', (success: boolean) => { + if (success) { + channelzSessionInfo.streamTracker.addCallSucceeded(); + } else { + channelzSessionInfo.streamTracker.addCallFailed(); } + }); + call.on('sendMessage', () => { + channelzSessionInfo.messagesSent += 1; + channelzSessionInfo.lastMessageSentTimestamp = new Date(); + }); + call.on('receiveMessage', () => { + channelzSessionInfo.messagesReceived += 1; + channelzSessionInfo.lastMessageReceivedTimestamp = new Date(); + }); + } + + if (!this._runHandlerForCall(call, handler, headers)) { + this.callTracker.addCallFailed(); + channelzSessionInfo?.streamTracker.addCallFailed() + + call.sendError({ + code: Status.INTERNAL, + details: `Unknown handler type: ${handler.type}` + }); + } + } + + private _streamHandler(stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders) { + if (this._verifyContentType(stream, headers) !== true) { + return + } + + let handler: Handler + try { + handler = this._retrieveHandler(headers) + } catch (err) { + this._respondWithError({ + details: getErrorMessage(err), + code: getErrorCode(err) ?? undefined + }, stream, null) + return + } + + const call = new Http2ServerCallStream(stream, handler, this.options) + if (!this._runHandlerForCall(call, handler, headers)) { + call.sendError({ + code: Status.INTERNAL, + details: `Unknown handler type: ${handler.type}` + }); + } + } + + private _runHandlerForCall(call: Http2ServerCallStream, handler: Handler, headers: http2.IncomingHttpHeaders): boolean { + const metadata = call.receiveMetadata(headers); + const encoding = (metadata.get('grpc-encoding')[0] as string | undefined) ?? 'identity'; + metadata.remove('grpc-encoding'); + + const { type } = handler + if (type === 'unary') { + handleUnary(call, handler as UntypedUnaryHandler, metadata, encoding); + } else if (type === 'clientStream') { + handleClientStreaming( + call, + handler as UntypedClientStreamingHandler, + metadata, + encoding + ); + } else if (type === 'serverStream') { + handleServerStreaming( + call, + handler as UntypedServerStreamingHandler, + metadata, + encoding + ); + } else if (type === 'bidi') { + handleBidiStreaming( + call, + handler as UntypedBidiStreamingHandler, + metadata, + encoding + ); + } else { + return false + } + + return true + } + + private _setupHandlers( + http2Server: http2.Http2Server | http2.Http2SecureServer + ): void { + if (http2Server === null) { + return; + } + + const serverAddress = http2Server.address(); + let serverAddressString = 'null' + if (serverAddress) { + if (typeof serverAddress === 'string') { + serverAddressString = serverAddress + } else { + serverAddressString = + serverAddress.address + ':' + serverAddress.port } - ); + } + this.serverAddressString = serverAddressString + const handler = this.channelzEnabled + ? this._channelzHandler + : this._streamHandler + + http2Server.on('stream', handler.bind(this)) http2Server.on('session', (session) => { if (!this.started) { session.destroy(); return; } - this.sessions.add(session); + let channelzRef: SocketRef; + channelzRef = registerChannelzSocket(session.socket.remoteAddress ?? 'unknown', this.getChannelzSessionInfoGetter(session), this.channelzEnabled); + + const channelzSessionInfo: ChannelzSessionInfo = { + ref: channelzRef, + streamTracker: new ChannelzCallTracker(), + messagesSent: 0, + messagesReceived: 0, + lastMessageSentTimestamp: null, + lastMessageReceivedTimestamp: null + }; + this.sessions.set(session, channelzSessionInfo); + const clientAddress = session.socket.remoteAddress; + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Connection established by client ' + clientAddress); + this.sessionChildrenTracker.refChild(channelzRef); + } + let connectionAgeTimer: NodeJS.Timer | null = null; + let connectionAgeGraceTimer: NodeJS.Timer | null = null; + let sessionClosedByServer = false; + if (this.maxConnectionAgeMs !== UNLIMITED_CONNECTION_AGE_MS) { + // Apply a random jitter within a +/-10% range + const jitterMagnitude = this.maxConnectionAgeMs / 10; + const jitter = Math.random() * jitterMagnitude * 2 - jitterMagnitude; + connectionAgeTimer = setTimeout(() => { + sessionClosedByServer = true; + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Connection dropped by max connection age from ' + clientAddress); + } + try { + session.goaway(http2.constants.NGHTTP2_NO_ERROR, ~(1<<31), Buffer.from('max_age')); + } catch (e) { + // The goaway can't be sent because the session is already closed + session.destroy(); + return; + } + session.close(); + /* Allow a grace period after sending the GOAWAY before forcibly + * closing the connection. */ + if (this.maxConnectionAgeGraceMs !== UNLIMITED_CONNECTION_AGE_MS) { + connectionAgeGraceTimer = setTimeout(() => { + session.destroy(); + }, this.maxConnectionAgeGraceMs).unref?.(); + } + }, this.maxConnectionAgeMs + jitter).unref?.(); + } + const keeapliveTimeTimer: NodeJS.Timer | null = setInterval(() => { + const timeoutTImer = setTimeout(() => { + sessionClosedByServer = true; + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Connection dropped by keepalive timeout from ' + clientAddress); + } + session.close(); + }, this.keepaliveTimeoutMs).unref?.(); + try { + session.ping((err: Error | null, duration: number, payload: Buffer) => { + clearTimeout(timeoutTImer); + }); + } catch (e) { + // The ping can't be sent because the session is already closed + session.destroy(); + } + }, this.keepaliveTimeMs).unref?.(); session.on('close', () => { + if (this.channelzEnabled) { + if (!sessionClosedByServer) { + this.channelzTrace.addTrace('CT_INFO', 'Connection dropped by client ' + clientAddress); + } + this.sessionChildrenTracker.unrefChild(channelzRef); + unregisterChannelzRef(channelzRef); + } + if (connectionAgeTimer) { + clearTimeout(connectionAgeTimer); + } + if (connectionAgeGraceTimer) { + clearTimeout(connectionAgeGraceTimer); + } + if (keeapliveTimeTimer) { + clearTimeout(keeapliveTimeTimer); + } this.sessions.delete(session); }); }); } } -async function handleUnary( +function handleUnary( call: Http2ServerCallStream, handler: UnaryHandler, - metadata: Metadata -): Promise { - const request = await call.receiveUnaryMessage(); + metadata: Metadata, + encoding: string +): void { + call.receiveUnaryMessage(encoding, (err, request) => { + if (err) { + call.sendError(err) + return + } - if (request === undefined || call.cancelled) { - return; - } + if (request === undefined || call.cancelled) { + return; + } - const emitter = new ServerUnaryCallImpl( - call, - metadata, - request - ); + const emitter = new ServerUnaryCallImpl( + call, + metadata, + request + ); - handler.func( - emitter, - ( - err: ServerErrorResponse | ServerStatusResponse | null, - value?: ResponseType | null, - trailer?: Metadata, - flags?: number - ) => { - call.sendUnaryMessage(err, value, trailer, flags); - } - ); + handler.func( + emitter, + ( + err: ServerErrorResponse | ServerStatusResponse | null, + value?: ResponseType | null, + trailer?: Metadata, + flags?: number + ) => { + call.sendUnaryMessage(err, value, trailer, flags); + } + ); + }); } function handleClientStreaming( call: Http2ServerCallStream, handler: ClientStreamingHandler, - metadata: Metadata + metadata: Metadata, + encoding: string ): void { const stream = new ServerReadableStreamImpl( call, metadata, - handler.deserialize + handler.deserialize, + encoding ); function respond( @@ -706,37 +1119,45 @@ function handleClientStreaming( handler.func(stream, respond); } -async function handleServerStreaming( +function handleServerStreaming( call: Http2ServerCallStream, handler: ServerStreamingHandler, - metadata: Metadata -): Promise { - const request = await call.receiveUnaryMessage(); + metadata: Metadata, + encoding: string +): void { + call.receiveUnaryMessage(encoding, (err, request) => { + if (err) { + call.sendError(err) + return + } - if (request === undefined || call.cancelled) { - return; - } + if (request === undefined || call.cancelled) { + return; + } - const stream = new ServerWritableStreamImpl( - call, - metadata, - handler.serialize, - request - ); + const stream = new ServerWritableStreamImpl( + call, + metadata, + handler.serialize, + request + ); - handler.func(stream); + handler.func(stream); + }); } function handleBidiStreaming( call: Http2ServerCallStream, handler: BidiStreamingHandler, - metadata: Metadata + metadata: Metadata, + encoding: string ): void { const stream = new ServerDuplexStreamImpl( call, metadata, handler.serialize, - handler.deserialize + handler.deserialize, + encoding ); if (call.cancelled) { diff --git a/packages/grpc-js/src/service-config.ts b/packages/grpc-js/src/service-config.ts index ed225e087..201c0c648 100644 --- a/packages/grpc-js/src/service-config.ts +++ b/packages/grpc-js/src/service-config.ts @@ -27,25 +27,52 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import * as os from 'os'; -import { LoadBalancingConfig, validateLoadBalancingConfig } from './load-balancer'; +import { Status } from './constants'; +import { Duration } from './duration'; +import { + LoadBalancingConfig, + validateLoadBalancingConfig, +} from './load-balancer'; export interface MethodConfigName { service: string; method?: string; } +export interface RetryPolicy { + maxAttempts: number; + initialBackoff: string; + maxBackoff: string; + backoffMultiplier: number; + retryableStatusCodes: (Status | string)[]; +} + +export interface HedgingPolicy { + maxAttempts: number; + hedgingDelay?: string; + nonFatalStatusCodes?: (Status | string)[]; +} + export interface MethodConfig { name: MethodConfigName[]; waitForReady?: boolean; - timeout?: string; + timeout?: Duration; maxRequestBytes?: number; maxResponseBytes?: number; + retryPolicy?: RetryPolicy; + hedgingPolicy?: HedgingPolicy; +} + +export interface RetryThrottling { + maxTokens: number; + tokenRatio: number; } export interface ServiceConfig { loadBalancingPolicy?: string; loadBalancingConfig: LoadBalancingConfig[]; methodConfig: MethodConfig[]; + retryThrottling?: RetryThrottling; } export interface ServiceConfigCanaryConfig { @@ -59,7 +86,7 @@ export interface ServiceConfigCanaryConfig { * Recognizes a number with up to 9 digits after the decimal point, followed by * an "s", representing a number of seconds. */ -const TIMEOUT_REGEX = /^\d+(\.\d{1,9})?s$/; +const DURATION_REGEX = /^\d+(\.\d{1,9})?s$/; /** * Client language name used for determining whether this client matches a @@ -84,6 +111,81 @@ function validateName(obj: any): MethodConfigName { return result; } +function validateRetryPolicy(obj: any): RetryPolicy { + if (!('maxAttempts' in obj) || !Number.isInteger(obj.maxAttempts) || obj.maxAttempts < 2) { + throw new Error('Invalid method config retry policy: maxAttempts must be an integer at least 2'); + } + if (!('initialBackoff' in obj) || typeof obj.initialBackoff !== 'string' || !DURATION_REGEX.test(obj.initialBackoff)) { + throw new Error('Invalid method config retry policy: initialBackoff must be a string consisting of a positive integer followed by s'); + } + if (!('maxBackoff' in obj) || typeof obj.maxBackoff !== 'string' || !DURATION_REGEX.test(obj.maxBackoff)) { + throw new Error('Invalid method config retry policy: maxBackoff must be a string consisting of a positive integer followed by s'); + } + if (!('backoffMultiplier' in obj) || typeof obj.backoffMultiplier !== 'number' || obj.backoffMultiplier <= 0) { + throw new Error('Invalid method config retry policy: backoffMultiplier must be a number greater than 0'); + } + if (!(('retryableStatusCodes' in obj) && Array.isArray(obj.retryableStatusCodes))) { + throw new Error('Invalid method config retry policy: retryableStatusCodes is required'); + } + if (obj.retryableStatusCodes.length === 0) { + throw new Error('Invalid method config retry policy: retryableStatusCodes must be non-empty'); + } + for (const value of obj.retryableStatusCodes) { + if (typeof value === 'number') { + if (!Object.values(Status).includes(value)) { + throw new Error('Invalid method config retry policy: retryableStatusCodes value not in status code range'); + } + } else if (typeof value === 'string') { + if (!Object.values(Status).includes(value.toUpperCase())) { + throw new Error('Invalid method config retry policy: retryableStatusCodes value not a status code name'); + } + } else { + throw new Error('Invalid method config retry policy: retryableStatusCodes value must be a string or number'); + } + } + return { + maxAttempts: obj.maxAttempts, + initialBackoff: obj.initialBackoff, + maxBackoff: obj.maxBackoff, + backoffMultiplier: obj.backoffMultiplier, + retryableStatusCodes: obj.retryableStatusCodes + }; +} + +function validateHedgingPolicy(obj: any): HedgingPolicy { + if (!('maxAttempts' in obj) || !Number.isInteger(obj.maxAttempts) || obj.maxAttempts < 2) { + throw new Error('Invalid method config hedging policy: maxAttempts must be an integer at least 2'); + } + if (('hedgingDelay' in obj) && (typeof obj.hedgingDelay !== 'string' || !DURATION_REGEX.test(obj.hedgingDelay))) { + throw new Error('Invalid method config hedging policy: hedgingDelay must be a string consisting of a positive integer followed by s'); + } + if (('nonFatalStatusCodes' in obj) && Array.isArray(obj.nonFatalStatusCodes)) { + for (const value of obj.nonFatalStatusCodes) { + if (typeof value === 'number') { + if (!Object.values(Status).includes(value)) { + throw new Error('Invlid method config hedging policy: nonFatalStatusCodes value not in status code range'); + } + } else if (typeof value === 'string') { + if (!Object.values(Status).includes(value.toUpperCase())) { + throw new Error('Invlid method config hedging policy: nonFatalStatusCodes value not a status code name'); + } + } else { + throw new Error('Invlid method config hedging policy: nonFatalStatusCodes value must be a string or number'); + } + } + } + const result: HedgingPolicy = { + maxAttempts: obj.maxAttempts + } + if (obj.hedgingDelay) { + result.hedgingDelay = obj.hedgingDelay; + } + if (obj.nonFatalStatusCodes) { + result.nonFatalStatusCodes = obj.nonFatalStatusCodes; + } + return result; +} + function validateMethodConfig(obj: any): MethodConfig { const result: MethodConfig = { name: [], @@ -101,13 +203,34 @@ function validateMethodConfig(obj: any): MethodConfig { result.waitForReady = obj.waitForReady; } if ('timeout' in obj) { - if ( - !(typeof obj.timeout === 'string') || - !TIMEOUT_REGEX.test(obj.timeout) + if (typeof obj.timeout === 'object') { + if ( + !('seconds' in obj.timeout) || + !(typeof obj.timeout.seconds === 'number') + ) { + throw new Error('Invalid method config: invalid timeout.seconds'); + } + if ( + !('nanos' in obj.timeout) || + !(typeof obj.timeout.nanos === 'number') + ) { + throw new Error('Invalid method config: invalid timeout.nanos'); + } + result.timeout = obj.timeout; + } else if ( + typeof obj.timeout === 'string' && + DURATION_REGEX.test(obj.timeout) ) { + const timeoutParts = obj.timeout + .substring(0, obj.timeout.length - 1) + .split('.'); + result.timeout = { + seconds: timeoutParts[0] | 0, + nanos: (timeoutParts[1] ?? 0) | 0, + }; + } else { throw new Error('Invalid method config: invalid timeout'); } - result.timeout = obj.timeout; } if ('maxRequestBytes' in obj) { if (typeof obj.maxRequestBytes !== 'number') { @@ -121,9 +244,31 @@ function validateMethodConfig(obj: any): MethodConfig { } result.maxResponseBytes = obj.maxResponseBytes; } + if ('retryPolicy' in obj) { + if ('hedgingPolicy' in obj) { + throw new Error('Invalid method config: retryPolicy and hedgingPolicy cannot both be specified'); + } else { + result.retryPolicy = validateRetryPolicy(obj.retryPolicy); + } + } else if ('hedgingPolicy' in obj) { + result.hedgingPolicy = validateHedgingPolicy(obj.hedgingPolicy); + } return result; } +export function validateRetryThrottling(obj: any): RetryThrottling { + if (!('maxTokens' in obj) || typeof obj.maxTokens !== 'number' || obj.maxTokens <=0 || obj.maxTokens > 1000) { + throw new Error('Invalid retryThrottling: maxTokens must be a number in (0, 1000]'); + } + if (!('tokenRatio' in obj) || typeof obj.tokenRatio !== 'number' || obj.tokenRatio <= 0) { + throw new Error('Invalid retryThrottling: tokenRatio must be a number greater than 0'); + } + return { + maxTokens: +(obj.maxTokens as number).toFixed(3), + tokenRatio: +(obj.tokenRatio as number).toFixed(3) + }; +} + export function validateServiceConfig(obj: any): ServiceConfig { const result: ServiceConfig = { loadBalancingConfig: [], @@ -152,6 +297,9 @@ export function validateServiceConfig(obj: any): ServiceConfig { } } } + if ('retryThrottling' in obj) { + result.retryThrottling = validateRetryThrottling(obj.retryThrottling); + } // Validate method name uniqueness const seenMethodNames: MethodConfigName[] = []; for (const methodConfig of result.methodConfig) { diff --git a/packages/grpc-js/src/status-builder.ts b/packages/grpc-js/src/status-builder.ts index 1109af1ac..78e2ea310 100644 --- a/packages/grpc-js/src/status-builder.ts +++ b/packages/grpc-js/src/status-builder.ts @@ -15,7 +15,7 @@ * */ -import { StatusObject } from './call-stream'; +import { StatusObject } from './call-interface'; import { Status } from './constants'; import { Metadata } from './metadata'; diff --git a/packages/grpc-js/src/subchannel-address.ts b/packages/grpc-js/src/subchannel-address.ts new file mode 100644 index 000000000..e542e645e --- /dev/null +++ b/packages/grpc-js/src/subchannel-address.ts @@ -0,0 +1,85 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { isIP } from "net"; + +export interface TcpSubchannelAddress { + port: number; + host: string; +} + +export interface IpcSubchannelAddress { + path: string; +} +/** + * This represents a single backend address to connect to. This interface is a + * subset of net.SocketConnectOpts, i.e. the options described at + * https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener. + * Those are in turn a subset of the options that can be passed to http2.connect. + */ + +export type SubchannelAddress = TcpSubchannelAddress | IpcSubchannelAddress; + +export function isTcpSubchannelAddress( + address: SubchannelAddress +): address is TcpSubchannelAddress { + return 'port' in address; +} + +export function subchannelAddressEqual( + address1?: SubchannelAddress, + address2?: SubchannelAddress +): boolean { + if (!address1 && !address2) { + return true; + } + if (!address1 || !address2) { + return false; + } + if (isTcpSubchannelAddress(address1)) { + return ( + isTcpSubchannelAddress(address2) && + address1.host === address2.host && + address1.port === address2.port + ); + } else { + return !isTcpSubchannelAddress(address2) && address1.path === address2.path; + } +} + +export function subchannelAddressToString(address: SubchannelAddress): string { + if (isTcpSubchannelAddress(address)) { + return address.host + ':' + address.port; + } else { + return address.path; + } +} + +const DEFAULT_PORT = 443; + +export function stringToSubchannelAddress(addressString: string, port?: number): SubchannelAddress { + if (isIP(addressString)) { + return { + host: addressString, + port: port ?? DEFAULT_PORT + }; + } else { + return { + path: addressString + }; + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/subchannel-call.ts b/packages/grpc-js/src/subchannel-call.ts new file mode 100644 index 000000000..969282e19 --- /dev/null +++ b/packages/grpc-js/src/subchannel-call.ts @@ -0,0 +1,525 @@ +/* + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as http2 from 'http2'; +import * as os from 'os'; + +import { Status } from './constants'; +import { Metadata } from './metadata'; +import { StreamDecoder } from './stream-decoder'; +import * as logging from './logging'; +import { LogVerbosity } from './constants'; +import { ServerSurfaceCall } from './server-call'; +import { Deadline } from './deadline'; +import { InterceptingListener, MessageContext, StatusObject, WriteCallback } from './call-interface'; +import { CallEventTracker, Transport } from './transport'; + +const TRACER_NAME = 'subchannel_call'; + +const { + HTTP2_HEADER_STATUS, + HTTP2_HEADER_CONTENT_TYPE, + NGHTTP2_CANCEL, +} = http2.constants; + +/** + * https://nodejs.org/api/errors.html#errors_class_systemerror + */ +interface SystemError extends Error { + address?: string; + code: string; + dest?: string; + errno: number; + info?: object; + message: string; + path?: string; + port?: number; + syscall: string; +} + +/** + * Should do approximately the same thing as util.getSystemErrorName but the + * TypeScript types don't have that function for some reason so I just made my + * own. + * @param errno + */ +function getSystemErrorName(errno: number): string { + for (const [name, num] of Object.entries(os.constants.errno)) { + if (num === errno) { + return name; + } + } + return 'Unknown system error ' + errno; +} + +export interface SubchannelCall { + cancelWithStatus(status: Status, details: string): void; + getPeer(): string; + sendMessageWithContext(context: MessageContext, message: Buffer): void; + startRead(): void; + halfClose(): void; + getCallNumber(): number; +} + +export interface StatusObjectWithRstCode extends StatusObject { + rstCode?: number; +} + +export interface SubchannelCallInterceptingListener extends InterceptingListener { + onReceiveStatus(status: StatusObjectWithRstCode): void; +} + +export class Http2SubchannelCall implements SubchannelCall { + private decoder = new StreamDecoder(); + + private isReadFilterPending = false; + private isPushPending = false; + private canPush = false; + /** + * Indicates that an 'end' event has come from the http2 stream, so there + * will be no more data events. + */ + private readsClosed = false; + + private statusOutput = false; + + private unpushedReadMessages: Buffer[] = []; + + // Status code mapped from :status. To be used if grpc-status is not received + private mappedStatusCode: Status = Status.UNKNOWN; + + // This is populated (non-null) if and only if the call has ended + private finalStatus: StatusObject | null = null; + + private internalError: SystemError | null = null; + + constructor( + private readonly http2Stream: http2.ClientHttp2Stream, + private readonly callEventTracker: CallEventTracker, + private readonly listener: SubchannelCallInterceptingListener, + private readonly transport: Transport, + private readonly callId: number + ) { + http2Stream.on('response', (headers, flags) => { + let headersString = ''; + for (const header of Object.keys(headers)) { + headersString += '\t\t' + header + ': ' + headers[header] + '\n'; + } + this.trace('Received server headers:\n' + headersString); + switch (headers[':status']) { + // TODO(murgatroid99): handle 100 and 101 + case 400: + this.mappedStatusCode = Status.INTERNAL; + break; + case 401: + this.mappedStatusCode = Status.UNAUTHENTICATED; + break; + case 403: + this.mappedStatusCode = Status.PERMISSION_DENIED; + break; + case 404: + this.mappedStatusCode = Status.UNIMPLEMENTED; + break; + case 429: + case 502: + case 503: + case 504: + this.mappedStatusCode = Status.UNAVAILABLE; + break; + default: + this.mappedStatusCode = Status.UNKNOWN; + } + + if (flags & http2.constants.NGHTTP2_FLAG_END_STREAM) { + this.handleTrailers(headers); + } else { + let metadata: Metadata; + try { + metadata = Metadata.fromHttp2Headers(headers); + } catch (error) { + this.endCall({ + code: Status.UNKNOWN, + details: (error as Error).message, + metadata: new Metadata(), + }); + return; + } + this.listener.onReceiveMetadata(metadata); + } + }); + http2Stream.on('trailers', (headers: http2.IncomingHttpHeaders) => { + this.handleTrailers(headers); + }); + http2Stream.on('data', (data: Buffer) => { + /* If the status has already been output, allow the http2 stream to + * drain without processing the data. */ + if (this.statusOutput) { + return; + } + this.trace('receive HTTP/2 data frame of length ' + data.length); + const messages = this.decoder.write(data); + + for (const message of messages) { + this.trace('parsed message of length ' + message.length); + this.callEventTracker!.addMessageReceived(); + this.tryPush(message); + } + }); + http2Stream.on('end', () => { + this.readsClosed = true; + this.maybeOutputStatus(); + }); + http2Stream.on('close', () => { + /* Use process.next tick to ensure that this code happens after any + * "error" event that may be emitted at about the same time, so that + * we can bubble up the error message from that event. */ + process.nextTick(() => { + this.trace('HTTP/2 stream closed with code ' + http2Stream.rstCode); + /* If we have a final status with an OK status code, that means that + * we have received all of the messages and we have processed the + * trailers and the call completed successfully, so it doesn't matter + * how the stream ends after that */ + if (this.finalStatus?.code === Status.OK) { + return; + } + let code: Status; + let details = ''; + switch (http2Stream.rstCode) { + case http2.constants.NGHTTP2_NO_ERROR: + /* If we get a NO_ERROR code and we already have a status, the + * stream completed properly and we just haven't fully processed + * it yet */ + if (this.finalStatus !== null) { + return; + } + code = Status.INTERNAL; + details = `Received RST_STREAM with code ${http2Stream.rstCode}`; + break; + case http2.constants.NGHTTP2_REFUSED_STREAM: + code = Status.UNAVAILABLE; + details = 'Stream refused by server'; + break; + case http2.constants.NGHTTP2_CANCEL: + code = Status.CANCELLED; + details = 'Call cancelled'; + break; + case http2.constants.NGHTTP2_ENHANCE_YOUR_CALM: + code = Status.RESOURCE_EXHAUSTED; + details = 'Bandwidth exhausted or memory limit exceeded'; + break; + case http2.constants.NGHTTP2_INADEQUATE_SECURITY: + code = Status.PERMISSION_DENIED; + details = 'Protocol not secure enough'; + break; + case http2.constants.NGHTTP2_INTERNAL_ERROR: + code = Status.INTERNAL; + if (this.internalError === null) { + /* This error code was previously handled in the default case, and + * there are several instances of it online, so I wanted to + * preserve the original error message so that people find existing + * information in searches, but also include the more recognizable + * "Internal server error" message. */ + details = `Received RST_STREAM with code ${http2Stream.rstCode} (Internal server error)`; + } else { + if (this.internalError.code === 'ECONNRESET' || this.internalError.code === 'ETIMEDOUT') { + code = Status.UNAVAILABLE; + details = this.internalError.message; + } else { + /* The "Received RST_STREAM with code ..." error is preserved + * here for continuity with errors reported online, but the + * error message at the end will probably be more relevant in + * most cases. */ + details = `Received RST_STREAM with code ${http2Stream.rstCode} triggered by internal client error: ${this.internalError.message}`; + } + } + break; + default: + code = Status.INTERNAL; + details = `Received RST_STREAM with code ${http2Stream.rstCode}`; + } + // This is a no-op if trailers were received at all. + // This is OK, because status codes emitted here correspond to more + // catastrophic issues that prevent us from receiving trailers in the + // first place. + this.endCall({ code, details, metadata: new Metadata(), rstCode: http2Stream.rstCode }); + }); + }); + http2Stream.on('error', (err: SystemError) => { + /* We need an error handler here to stop "Uncaught Error" exceptions + * from bubbling up. However, errors here should all correspond to + * "close" events, where we will handle the error more granularly */ + /* Specifically looking for stream errors that were *not* constructed + * from a RST_STREAM response here: + * https://github.com/nodejs/node/blob/8b8620d580314050175983402dfddf2674e8e22a/lib/internal/http2/core.js#L2267 + */ + if (err.code !== 'ERR_HTTP2_STREAM_ERROR') { + this.trace( + 'Node error event: message=' + + err.message + + ' code=' + + err.code + + ' errno=' + + getSystemErrorName(err.errno) + + ' syscall=' + + err.syscall + ); + this.internalError = err; + } + this.callEventTracker.onStreamEnd(false); + }); + } + + public onDisconnect() { + this.endCall({ + code: Status.UNAVAILABLE, + details: 'Connection dropped', + metadata: new Metadata(), + }); + } + + private outputStatus() { + /* Precondition: this.finalStatus !== null */ + if (!this.statusOutput) { + this.statusOutput = true; + this.trace( + 'ended with status: code=' + + this.finalStatus!.code + + ' details="' + + this.finalStatus!.details + + '"' + ); + this.callEventTracker.onCallEnd(this.finalStatus!); + /* We delay the actual action of bubbling up the status to insulate the + * cleanup code in this class from any errors that may be thrown in the + * upper layers as a result of bubbling up the status. In particular, + * if the status is not OK, the "error" event may be emitted + * synchronously at the top level, which will result in a thrown error if + * the user does not handle that event. */ + process.nextTick(() => { + this.listener.onReceiveStatus(this.finalStatus!); + }); + /* Leave the http2 stream in flowing state to drain incoming messages, to + * ensure that the stream closure completes. The call stream already does + * not push more messages after the status is output, so the messages go + * nowhere either way. */ + this.http2Stream.resume(); + } + } + + private trace(text: string): void { + logging.trace( + LogVerbosity.DEBUG, + TRACER_NAME, + '[' + this.callId + '] ' + text + ); + } + + /** + * On first call, emits a 'status' event with the given StatusObject. + * Subsequent calls are no-ops. + * @param status The status of the call. + */ + private endCall(status: StatusObjectWithRstCode): void { + /* If the status is OK and a new status comes in (e.g. from a + * deserialization failure), that new status takes priority */ + if (this.finalStatus === null || this.finalStatus.code === Status.OK) { + this.finalStatus = status; + this.maybeOutputStatus(); + } + this.destroyHttp2Stream(); + } + + private maybeOutputStatus() { + if (this.finalStatus !== null) { + /* The combination check of readsClosed and that the two message buffer + * arrays are empty checks that there all incoming data has been fully + * processed */ + if ( + this.finalStatus.code !== Status.OK || + (this.readsClosed && + this.unpushedReadMessages.length === 0 && + !this.isReadFilterPending && + !this.isPushPending) + ) { + this.outputStatus(); + } + } + } + + private push(message: Buffer): void { + this.trace( + 'pushing to reader message of length ' + + (message instanceof Buffer ? message.length : null) + ); + this.canPush = false; + this.isPushPending = true; + process.nextTick(() => { + this.isPushPending = false; + /* If we have already output the status any later messages should be + * ignored, and can cause out-of-order operation errors higher up in the + * stack. Checking as late as possible here to avoid any race conditions. + */ + if (this.statusOutput) { + return; + } + this.listener.onReceiveMessage(message); + this.maybeOutputStatus(); + }); + } + + private tryPush(messageBytes: Buffer): void { + if (this.canPush) { + this.http2Stream!.pause(); + this.push(messageBytes); + } else { + this.trace( + 'unpushedReadMessages.push message of length ' + messageBytes.length + ); + this.unpushedReadMessages.push(messageBytes); + } + } + + private handleTrailers(headers: http2.IncomingHttpHeaders) { + this.callEventTracker.onStreamEnd(true); + let headersString = ''; + for (const header of Object.keys(headers)) { + headersString += '\t\t' + header + ': ' + headers[header] + '\n'; + } + this.trace('Received server trailers:\n' + headersString); + let metadata: Metadata; + try { + metadata = Metadata.fromHttp2Headers(headers); + } catch (e) { + metadata = new Metadata(); + } + const metadataMap = metadata.getMap(); + let code: Status = this.mappedStatusCode; + if ( + code === Status.UNKNOWN && + typeof metadataMap['grpc-status'] === 'string' + ) { + const receivedStatus = Number(metadataMap['grpc-status']); + if (receivedStatus in Status) { + code = receivedStatus; + this.trace('received status code ' + receivedStatus + ' from server'); + } + metadata.remove('grpc-status'); + } + let details = ''; + if (typeof metadataMap['grpc-message'] === 'string') { + try { + details = decodeURI(metadataMap['grpc-message']); + } catch (e) { + details = metadataMap['grpc-message']; + } + metadata.remove('grpc-message'); + this.trace( + 'received status details string "' + details + '" from server' + ); + } + const status: StatusObject = { code, details, metadata }; + // This is a no-op if the call was already ended when handling headers. + this.endCall(status); + } + + private destroyHttp2Stream() { + // The http2 stream could already have been destroyed if cancelWithStatus + // is called in response to an internal http2 error. + if (!this.http2Stream.destroyed) { + /* If the call has ended with an OK status, communicate that when closing + * the stream, partly to avoid a situation in which we detect an error + * RST_STREAM as a result after we have the status */ + let code: number; + if (this.finalStatus?.code === Status.OK) { + code = http2.constants.NGHTTP2_NO_ERROR; + } else { + code = http2.constants.NGHTTP2_CANCEL; + } + this.trace('close http2 stream with code ' + code); + this.http2Stream.close(code); + } + } + + cancelWithStatus(status: Status, details: string): void { + this.trace( + 'cancelWithStatus code: ' + status + ' details: "' + details + '"' + ); + this.endCall({ code: status, details, metadata: new Metadata() }); + } + + getStatus(): StatusObject | null { + return this.finalStatus; + } + + getPeer(): string { + return this.transport.getPeerName(); + } + + getCallNumber(): number { + return this.callId; + } + + startRead() { + /* If the stream has ended with an error, we should not emit any more + * messages and we should communicate that the stream has ended */ + if (this.finalStatus !== null && this.finalStatus.code !== Status.OK) { + this.readsClosed = true; + this.maybeOutputStatus(); + return; + } + this.canPush = true; + if (this.unpushedReadMessages.length > 0) { + const nextMessage: Buffer = this.unpushedReadMessages.shift()!; + this.push(nextMessage); + return; + } + /* Only resume reading from the http2Stream if we don't have any pending + * messages to emit */ + this.http2Stream.resume(); + } + + sendMessageWithContext(context: MessageContext, message: Buffer) { + this.trace('write() called with message of length ' + message.length); + const cb: WriteCallback = (error?: Error | null) => { + let code: Status = Status.UNAVAILABLE; + if ((error as NodeJS.ErrnoException)?.code === 'ERR_STREAM_WRITE_AFTER_END') { + code = Status.INTERNAL; + } + if (error) { + this.cancelWithStatus(code, `Write error: ${error.message}`); + } + context.callback?.(); + }; + this.trace('sending data chunk of length ' + message.length); + this.callEventTracker.addMessageSent(); + try { + this.http2Stream!.write(message, cb); + } catch (error) { + this.endCall({ + code: Status.UNAVAILABLE, + details: `Write failed with error ${(error as Error).message}`, + metadata: new Metadata() + }); + } + } + + halfClose() { + this.trace('end() called'); + this.trace('calling end() on HTTP/2 stream'); + this.http2Stream.end(); + } +} diff --git a/packages/grpc-js/src/subchannel-interface.ts b/packages/grpc-js/src/subchannel-interface.ts new file mode 100644 index 000000000..165ebc3e1 --- /dev/null +++ b/packages/grpc-js/src/subchannel-interface.ts @@ -0,0 +1,87 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { SubchannelRef } from "./channelz"; +import { ConnectivityState } from "./connectivity-state"; +import { Subchannel } from "./subchannel"; + +export type ConnectivityStateListener = ( + subchannel: SubchannelInterface, + previousState: ConnectivityState, + newState: ConnectivityState, + keepaliveTime: number +) => void; + +/** + * This is an interface for load balancing policies to use to interact with + * subchannels. This allows load balancing policies to wrap and unwrap + * subchannels. + * + * Any load balancing policy that wraps subchannels must unwrap the subchannel + * in the picker, so that other load balancing policies consistently have + * access to their own wrapper objects. + */ +export interface SubchannelInterface { + getConnectivityState(): ConnectivityState; + addConnectivityStateListener(listener: ConnectivityStateListener): void; + removeConnectivityStateListener(listener: ConnectivityStateListener): void; + startConnecting(): void; + getAddress(): string; + throttleKeepalive(newKeepaliveTime: number): void; + ref(): void; + unref(): void; + getChannelzRef(): SubchannelRef; + /** + * If this is a wrapper, return the wrapped subchannel, otherwise return this + */ + getRealSubchannel(): Subchannel; +} + +export abstract class BaseSubchannelWrapper implements SubchannelInterface { + constructor(protected child: SubchannelInterface) {} + + getConnectivityState(): ConnectivityState { + return this.child.getConnectivityState(); + } + addConnectivityStateListener(listener: ConnectivityStateListener): void { + this.child.addConnectivityStateListener(listener); + } + removeConnectivityStateListener(listener: ConnectivityStateListener): void { + this.child.removeConnectivityStateListener(listener); + } + startConnecting(): void { + this.child.startConnecting(); + } + getAddress(): string { + return this.child.getAddress(); + } + throttleKeepalive(newKeepaliveTime: number): void { + this.child.throttleKeepalive(newKeepaliveTime); + } + ref(): void { + this.child.ref(); + } + unref(): void { + this.child.unref(); + } + getChannelzRef(): SubchannelRef { + return this.child.getChannelzRef(); + } + getRealSubchannel(): Subchannel { + return this.child.getRealSubchannel(); + } +} \ No newline at end of file diff --git a/packages/grpc-js/src/subchannel-pool.ts b/packages/grpc-js/src/subchannel-pool.ts index d28e3eac8..bbfbea02b 100644 --- a/packages/grpc-js/src/subchannel-pool.ts +++ b/packages/grpc-js/src/subchannel-pool.ts @@ -16,13 +16,14 @@ */ import { ChannelOptions, channelOptionsEqual } from './channel-options'; +import { Subchannel } from './subchannel'; import { - Subchannel, SubchannelAddress, subchannelAddressEqual, -} from './subchannel'; +} from './subchannel-address'; import { ChannelCredentials } from './channel-credentials'; import { GrpcUri, uriToString } from './uri-parser'; +import { Http2SubchannelConnector } from './transport'; // 10 seconds in milliseconds. This value is arbitrary. /** @@ -49,10 +50,8 @@ export class SubchannelPool { /** * A pool of subchannels use for making connections. Subchannels with the * exact same parameters will be reused. - * @param global If true, this is the global subchannel pool. Otherwise, it - * is the pool for a single channel. */ - constructor(private global: boolean) {} + constructor() {} /** * Unrefs all unused subchannels and cancels the cleanup task if all @@ -95,7 +94,7 @@ export class SubchannelPool { * Ensures that the cleanup task is spawned. */ ensureCleanupTask(): void { - if (this.global && this.cleanupTimer === null) { + if (this.cleanupTimer === null) { this.cleanupTimer = setInterval(() => { this.unrefUnusedSubchannels(); }, REF_CHECK_INTERVAL); @@ -145,7 +144,8 @@ export class SubchannelPool { channelTargetUri, subchannelTarget, channelArguments, - channelCredentials + channelCredentials, + new Http2SubchannelConnector(channelTargetUri) ); if (!(channelTarget in this.pool)) { this.pool[channelTarget] = []; @@ -156,14 +156,12 @@ export class SubchannelPool { channelCredentials, subchannel, }); - if (this.global) { - subchannel.ref(); - } + subchannel.ref(); return subchannel; } } -const globalSubchannelPool = new SubchannelPool(true); +const globalSubchannelPool = new SubchannelPool(); /** * Get either the global subchannel pool, or a new subchannel pool. @@ -173,6 +171,6 @@ export function getSubchannelPool(global: boolean): SubchannelPool { if (global) { return globalSubchannelPool; } else { - return new SubchannelPool(false); + return new SubchannelPool(); } } diff --git a/packages/grpc-js/src/subchannel.ts b/packages/grpc-js/src/subchannel.ts index cb1650dc1..307f6b81e 100644 --- a/packages/grpc-js/src/subchannel.ts +++ b/packages/grpc-js/src/subchannel.ts @@ -15,118 +15,30 @@ * */ -import * as http2 from 'http2'; import { ChannelCredentials } from './channel-credentials'; import { Metadata } from './metadata'; -import { Http2CallStream } from './call-stream'; import { ChannelOptions } from './channel-options'; -import { PeerCertificate, checkServerIdentity } from 'tls'; -import { ConnectivityState } from './channel'; +import { ConnectivityState } from './connectivity-state'; import { BackoffTimeout, BackoffOptions } from './backoff-timeout'; -import { getDefaultAuthority } from './resolver'; import * as logging from './logging'; -import { LogVerbosity } from './constants'; -import { getProxiedConnection, ProxyConnectionResult } from './http_proxy'; -import * as net from 'net'; -import { GrpcUri, parseUri, splitHostPort, uriToString } from './uri-parser'; -import { ConnectionOptions } from 'tls'; -import { FilterFactory, Filter } from './filter'; - -const clientVersion = require('../../package.json').version; +import { LogVerbosity, Status } from './constants'; +import { GrpcUri, uriToString } from './uri-parser'; +import { + SubchannelAddress, + subchannelAddressToString, +} from './subchannel-address'; +import { SubchannelRef, ChannelzTrace, ChannelzChildrenTracker, SubchannelInfo, registerChannelzSubchannel, ChannelzCallTracker, unregisterChannelzRef } from './channelz'; +import { ConnectivityStateListener } from './subchannel-interface'; +import { SubchannelCallInterceptingListener } from './subchannel-call'; +import { SubchannelCall } from './subchannel-call'; +import { CallEventTracker, SubchannelConnector, Transport } from './transport'; const TRACER_NAME = 'subchannel'; -function trace(text: string): void { - logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text); -} - -function refTrace(text: string): void { - logging.trace(LogVerbosity.DEBUG, 'subchannel_refcount', text); -} - -const MIN_CONNECT_TIMEOUT_MS = 20000; -const INITIAL_BACKOFF_MS = 1000; -const BACKOFF_MULTIPLIER = 1.6; -const MAX_BACKOFF_MS = 120000; -const BACKOFF_JITTER = 0.2; - /* setInterval and setTimeout only accept signed 32 bit integers. JS doesn't * have a constant for the max signed 32 bit integer, so this is a simple way * to calculate it */ const KEEPALIVE_MAX_TIME_MS = ~(1 << 31); -const KEEPALIVE_TIMEOUT_MS = 20000; - -export type ConnectivityStateListener = ( - subchannel: Subchannel, - previousState: ConnectivityState, - newState: ConnectivityState -) => void; - -const { - HTTP2_HEADER_AUTHORITY, - HTTP2_HEADER_CONTENT_TYPE, - HTTP2_HEADER_METHOD, - HTTP2_HEADER_PATH, - HTTP2_HEADER_TE, - HTTP2_HEADER_USER_AGENT, -} = http2.constants; - -/** - * Get a number uniformly at random in the range [min, max) - * @param min - * @param max - */ -function uniformRandom(min: number, max: number) { - return Math.random() * (max - min) + min; -} - -const tooManyPingsData: Buffer = Buffer.from('too_many_pings', 'ascii'); - -export interface TcpSubchannelAddress { - port: number; - host: string; -} - -export interface IpcSubchannelAddress { - path: string; -} - -/** - * This represents a single backend address to connect to. This interface is a - * subset of net.SocketConnectOpts, i.e. the options described at - * https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener. - * Those are in turn a subset of the options that can be passed to http2.connect. - */ -export type SubchannelAddress = TcpSubchannelAddress | IpcSubchannelAddress; - -export function isTcpSubchannelAddress( - address: SubchannelAddress -): address is TcpSubchannelAddress { - return 'port' in address; -} - -export function subchannelAddressEqual( - address1: SubchannelAddress, - address2: SubchannelAddress -): boolean { - if (isTcpSubchannelAddress(address1)) { - return ( - isTcpSubchannelAddress(address2) && - address1.host === address2.host && - address1.port === address2.port - ); - } else { - return !isTcpSubchannelAddress(address2) && address1.path === address2.path; - } -} - -export function subchannelAddressToString(address: SubchannelAddress): string { - if (isTcpSubchannelAddress(address)) { - return address.host + ':' + address.port; - } else { - return address.path; - } -} export class Subchannel { /** @@ -137,7 +49,7 @@ export class Subchannel { /** * The underlying http2 session used to make requests. */ - private session: http2.ClientHttp2Session | null = null; + private transport: Transport | null = null; /** * Indicates that the subchannel should transition from TRANSIENT_FAILURE to * CONNECTING instead of IDLE when the backoff timeout ends. @@ -148,47 +60,11 @@ export class Subchannel { * state changes. Will be modified by `addConnectivityStateListener` and * `removeConnectivityStateListener` */ - private stateListeners: ConnectivityStateListener[] = []; - - /** - * A list of listener functions that will be called when the underlying - * socket disconnects. Used for ending active calls with an UNAVAILABLE - * status. - */ - private disconnectListeners: Array<() => void> = []; + private stateListeners: Set = new Set(); private backoffTimeout: BackoffTimeout; - /** - * The complete user agent string constructed using channel args. - */ - private userAgent: string; - - /** - * The amount of time in between sending pings - */ - private keepaliveTimeMs: number = KEEPALIVE_MAX_TIME_MS; - /** - * The amount of time to wait for an acknowledgement after sending a ping - */ - private keepaliveTimeoutMs: number = KEEPALIVE_TIMEOUT_MS; - /** - * Timer reference for timeout that indicates when to send the next ping - */ - private keepaliveIntervalId: NodeJS.Timer; - /** - * Timer reference tracking when the most recent ping will be considered lost - */ - private keepaliveTimeoutId: NodeJS.Timer; - /** - * Indicates whether keepalive pings should be sent without any active calls - */ - private keepaliveWithoutCalls: boolean = false; - - /** - * Tracks calls with references to this subchannel - */ - private callRefcount = 0; + private keepaliveTime: number; /** * Tracks channels and subchannel pools with references to this subchannel */ @@ -199,6 +75,16 @@ export class Subchannel { */ private subchannelAddressString: string; + // Channelz info + private readonly channelzEnabled: boolean = true; + private channelzRef: SubchannelRef; + private channelzTrace: ChannelzTrace; + private callTracker = new ChannelzCallTracker(); + private childrenTracker = new ChannelzChildrenTracker(); + + // Channelz socket info + private streamTracker = new ChannelzCallTracker(); + /** * A class representing a connection to a single backend. * @param channelTarget The target string for the channel as a whole @@ -213,32 +99,9 @@ export class Subchannel { private channelTarget: GrpcUri, private subchannelAddress: SubchannelAddress, private options: ChannelOptions, - private credentials: ChannelCredentials + private credentials: ChannelCredentials, + private connector: SubchannelConnector ) { - // Build user-agent string. - this.userAgent = [ - options['grpc.primary_user_agent'], - `grpc-node-js/${clientVersion}`, - options['grpc.secondary_user_agent'], - ] - .filter((e) => e) - .join(' '); // remove falsey values first - - if ('grpc.keepalive_time_ms' in options) { - this.keepaliveTimeMs = options['grpc.keepalive_time_ms']!; - } - if ('grpc.keepalive_timeout_ms' in options) { - this.keepaliveTimeoutMs = options['grpc.keepalive_timeout_ms']!; - } - if ('grpc.keepalive_permit_without_calls' in options) { - this.keepaliveWithoutCalls = options['grpc.keepalive_permit_without_calls'] === 1; - } else { - this.keepaliveWithoutCalls = false; - } - this.keepaliveIntervalId = setTimeout(() => {}, 0); - clearTimeout(this.keepaliveIntervalId); - this.keepaliveTimeoutId = setTimeout(() => {}, 0); - clearTimeout(this.keepaliveTimeoutId); const backoffOptions: BackoffOptions = { initialDelay: options['grpc.initial_reconnect_backoff_ms'], maxDelay: options['grpc.max_reconnect_backoff_ms'], @@ -247,6 +110,36 @@ export class Subchannel { this.handleBackoffTimer(); }, backoffOptions); this.subchannelAddressString = subchannelAddressToString(subchannelAddress); + + this.keepaliveTime = options['grpc.keepalive_time_ms'] ?? -1; + + if (options['grpc.enable_channelz'] === 0) { + this.channelzEnabled = false; + } + this.channelzTrace = new ChannelzTrace(); + this.channelzRef = registerChannelzSubchannel(this.subchannelAddressString, () => this.getChannelzInfo(), this.channelzEnabled); + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Subchannel created'); + } + this.trace('Subchannel constructed with options ' + JSON.stringify(options, undefined, 2)); + } + + private getChannelzInfo(): SubchannelInfo { + return { + state: this.connectivityState, + trace: this.channelzTrace, + callTracker: this.callTracker, + children: this.childrenTracker.getChildLists(), + target: this.subchannelAddressString + }; + } + + private trace(text: string): void { + logging.trace(LogVerbosity.DEBUG, TRACER_NAME, '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); + } + + private refTrace(text: string): void { + logging.trace(LogVerbosity.DEBUG, 'subchannel_refcount', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); } private handleBackoffTimer() { @@ -275,251 +168,39 @@ export class Subchannel { this.backoffTimeout.reset(); } - private sendPing() { - logging.trace(LogVerbosity.DEBUG, 'keepalive', 'Sending ping to ' + this.subchannelAddressString); - this.keepaliveTimeoutId = setTimeout(() => { - this.transitionToState([ConnectivityState.READY], ConnectivityState.IDLE); - }, this.keepaliveTimeoutMs); - this.keepaliveTimeoutId.unref?.(); - this.session!.ping( - (err: Error | null, duration: number, payload: Buffer) => { - clearTimeout(this.keepaliveTimeoutId); - } - ); - } - - private startKeepalivePings() { - this.keepaliveIntervalId = setInterval(() => { - this.sendPing(); - }, this.keepaliveTimeMs); - this.keepaliveIntervalId.unref?.() - /* Don't send a ping immediately because whatever caused us to start - * sending pings should also involve some network activity. */ - } - - private stopKeepalivePings() { - clearInterval(this.keepaliveIntervalId); - clearTimeout(this.keepaliveTimeoutId); - } - - private createSession(proxyConnectionResult: ProxyConnectionResult) { - if (proxyConnectionResult.realTarget) { - trace(this.subchannelAddressString + ' creating HTTP/2 session through proxy to ' + proxyConnectionResult.realTarget); - } else { - trace(this.subchannelAddressString + ' creating HTTP/2 session'); - } - const targetAuthority = getDefaultAuthority( - proxyConnectionResult.realTarget ?? this.channelTarget - ); - let connectionOptions: http2.SecureClientSessionOptions = - this.credentials._getConnectionOptions() || {}; - connectionOptions.maxSendHeaderBlockLength = Number.MAX_SAFE_INTEGER; - if ('grpc-node.max_session_memory' in this.options) { - connectionOptions.maxSessionMemory = this.options['grpc-node.max_session_memory']; - } - let addressScheme = 'http://'; - if ('secureContext' in connectionOptions) { - addressScheme = 'https://'; - // If provided, the value of grpc.ssl_target_name_override should be used - // to override the target hostname when checking server identity. - // This option is used for testing only. - if (this.options['grpc.ssl_target_name_override']) { - const sslTargetNameOverride = this.options[ - 'grpc.ssl_target_name_override' - ]!; - connectionOptions.checkServerIdentity = ( - host: string, - cert: PeerCertificate - ): Error | undefined => { - return checkServerIdentity(sslTargetNameOverride, cert); - }; - connectionOptions.servername = sslTargetNameOverride; - } else { - const authorityHostname = - splitHostPort(targetAuthority)?.host ?? 'localhost'; - // We want to always set servername to support SNI - connectionOptions.servername = authorityHostname; - } - if (proxyConnectionResult.socket) { - /* This is part of the workaround for - * https://github.com/nodejs/node/issues/32922. Without that bug, - * proxyConnectionResult.socket would always be a plaintext socket and - * this would say - * connectionOptions.socket = proxyConnectionResult.socket; */ - connectionOptions.createConnection = (authority, option) => { - return proxyConnectionResult.socket!; - }; - } - } else { - /* In all but the most recent versions of Node, http2.connect does not use - * the options when establishing plaintext connections, so we need to - * establish that connection explicitly. */ - connectionOptions.createConnection = (authority, option) => { - if (proxyConnectionResult.socket) { - return proxyConnectionResult.socket; - } else { - /* net.NetConnectOpts is declared in a way that is more restrictive - * than what net.connect will actually accept, so we use the type - * assertion to work around that. */ - return net.connect(this.subchannelAddress); - } - }; + private startConnectingInternal() { + let options = this.options; + if (options['grpc.keepalive_time_ms']) { + const adjustedKeepaliveTime = Math.min(this.keepaliveTime, KEEPALIVE_MAX_TIME_MS); + options = {...options, 'grpc.keepalive_time_ms': adjustedKeepaliveTime}; } - - connectionOptions = { - ...connectionOptions, - ...this.subchannelAddress, - }; - - /* http2.connect uses the options here: - * https://github.com/nodejs/node/blob/70c32a6d190e2b5d7b9ff9d5b6a459d14e8b7d59/lib/internal/http2/core.js#L3028-L3036 - * The spread operator overides earlier values with later ones, so any port - * or host values in the options will be used rather than any values extracted - * from the first argument. In addition, the path overrides the host and port, - * as documented for plaintext connections here: - * https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener - * and for TLS connections here: - * https://nodejs.org/api/tls.html#tls_tls_connect_options_callback. In - * earlier versions of Node, http2.connect passes these options to - * tls.connect but not net.connect, so in the insecure case we still need - * to set the createConnection option above to create the connection - * explicitly. We cannot do that in the TLS case because http2.connect - * passes necessary additional options to tls.connect. - * The first argument just needs to be parseable as a URL and the scheme - * determines whether the connection will be established over TLS or not. - */ - const session = http2.connect( - addressScheme + targetAuthority, - connectionOptions - ); - this.session = session; - session.unref(); - /* For all of these events, check if the session at the time of the event - * is the same one currently attached to this subchannel, to ensure that - * old events from previous connection attempts cannot cause invalid state - * transitions. */ - session.once('connect', () => { - if (this.session === session) { - this.transitionToState( - [ConnectivityState.CONNECTING], - ConnectivityState.READY - ); - } - }); - session.once('close', () => { - if (this.session === session) { - trace(this.subchannelAddressString + ' connection closed'); - this.transitionToState( - [ConnectivityState.CONNECTING], - ConnectivityState.TRANSIENT_FAILURE - ); - /* Transitioning directly to IDLE here should be OK because we are not - * doing any backoff, because a connection was established at some - * point */ - this.transitionToState( - [ConnectivityState.READY], - ConnectivityState.IDLE - ); - } - }); - session.once( - 'goaway', - (errorCode: number, lastStreamID: number, opaqueData: Buffer) => { - if (this.session === session) { - /* See the last paragraph of - * https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md#basic-keepalive */ - if ( - errorCode === http2.constants.NGHTTP2_ENHANCE_YOUR_CALM && - opaqueData.equals(tooManyPingsData) - ) { - this.keepaliveTimeMs = Math.min( - 2 * this.keepaliveTimeMs, - KEEPALIVE_MAX_TIME_MS - ); - logging.log( - LogVerbosity.ERROR, - `Connection to ${uriToString(this.channelTarget)} at ${this.subchannelAddressString} rejected by server because of excess pings. Increasing ping interval to ${this.keepaliveTimeMs} ms` - ); + this.connector.connect(this.subchannelAddress, this.credentials, options).then( + transport => { + if (this.transitionToState([ConnectivityState.CONNECTING], ConnectivityState.READY)) { + this.transport = transport; + if (this.channelzEnabled) { + this.childrenTracker.refChild(transport.getChannelzRef()); } - trace( - this.subchannelAddressString + - ' connection closed by GOAWAY with code ' + - errorCode - ); - this.transitionToState( - [ConnectivityState.CONNECTING, ConnectivityState.READY], - ConnectivityState.IDLE - ); - } - } - ); - session.once('error', (error) => { - /* Do nothing here. Any error should also trigger a close event, which is - * where we want to handle that. */ - trace( - this.subchannelAddressString + - ' connection closed with error ' + - (error as Error).message - ); - }); - } - - private startConnectingInternal() { - /* Pass connection options through to the proxy so that it's able to - * upgrade it's connection to support tls if needed. - * This is a workaround for https://github.com/nodejs/node/issues/32922 - * See https://github.com/grpc/grpc-node/pull/1369 for more info. */ - const connectionOptions: ConnectionOptions = - this.credentials._getConnectionOptions() || {}; - - if ('secureContext' in connectionOptions) { - connectionOptions.ALPNProtocols = ['h2']; - // If provided, the value of grpc.ssl_target_name_override should be used - // to override the target hostname when checking server identity. - // This option is used for testing only. - if (this.options['grpc.ssl_target_name_override']) { - const sslTargetNameOverride = this.options[ - 'grpc.ssl_target_name_override' - ]!; - connectionOptions.checkServerIdentity = ( - host: string, - cert: PeerCertificate - ): Error | undefined => { - return checkServerIdentity(sslTargetNameOverride, cert); - }; - connectionOptions.servername = sslTargetNameOverride; - } else { - if ('grpc.http_connect_target' in this.options) { - /* This is more or less how servername will be set in createSession - * if a connection is successfully established through the proxy. - * If the proxy is not used, these connectionOptions are discarded - * anyway */ - const targetPath = getDefaultAuthority( - parseUri(this.options['grpc.http_connect_target'] as string) ?? { - path: 'localhost', + transport.addDisconnectListener((tooManyPings) => { + this.transitionToState([ConnectivityState.READY], ConnectivityState.IDLE); + if (tooManyPings && this.keepaliveTime > 0) { + this.keepaliveTime *= 2; + logging.log( + LogVerbosity.ERROR, + `Connection to ${uriToString(this.channelTarget)} at ${ + this.subchannelAddressString + } rejected by server because of excess pings. Increasing ping interval to ${ + this.keepaliveTime + } ms` + ); } - ); - const hostPort = splitHostPort(targetPath); - connectionOptions.servername = hostPort?.host ?? targetPath; + }); } - } - } - - getProxiedConnection( - this.subchannelAddress, - this.options, - connectionOptions - ).then( - (result) => { - this.createSession(result); }, - (reason) => { - this.transitionToState( - [ConnectivityState.CONNECTING], - ConnectivityState.TRANSIENT_FAILURE - ); + error => { + this.transitionToState([ConnectivityState.CONNECTING], ConnectivityState.TRANSIENT_FAILURE); } - ); + ) } /** @@ -536,26 +217,19 @@ export class Subchannel { if (oldStates.indexOf(this.connectivityState) === -1) { return false; } - trace( - this.subchannelAddressString + - ' ' + - ConnectivityState[this.connectivityState] + + this.trace( + ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[newState] ); + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[newState]); + } const previousState = this.connectivityState; this.connectivityState = newState; switch (newState) { case ConnectivityState.READY: this.stopBackoff(); - this.session!.socket.once('close', () => { - for (const listener of this.disconnectListeners) { - listener(); - } - }); - if (this.keepaliveWithoutCalls) { - this.startKeepalivePings(); - } break; case ConnectivityState.CONNECTING: this.startBackoff(); @@ -563,11 +237,11 @@ export class Subchannel { this.continueConnecting = false; break; case ConnectivityState.TRANSIENT_FAILURE: - if (this.session) { - this.session.close(); + if (this.channelzEnabled && this.transport) { + this.childrenTracker.unrefChild(this.transport.getChannelzRef()); } - this.session = null; - this.stopKeepalivePings(); + this.transport?.shutdown(); + this.transport = null; /* If the backoff timer has already ended by the time we get to the * TRANSIENT_FAILURE state, we want to immediately transition out of * TRANSIENT_FAILURE as though the backoff timer is ending right now */ @@ -578,86 +252,24 @@ export class Subchannel { } break; case ConnectivityState.IDLE: - if (this.session) { - this.session.close(); + if (this.channelzEnabled && this.transport) { + this.childrenTracker.unrefChild(this.transport.getChannelzRef()); } - this.session = null; - this.stopKeepalivePings(); + this.transport?.shutdown(); + this.transport = null; break; default: throw new Error(`Invalid state: unknown ConnectivityState ${newState}`); } - /* We use a shallow copy of the stateListeners array in case a listener - * is removed during this iteration */ - for (const listener of [...this.stateListeners]) { - listener(this, previousState, newState); + for (const listener of this.stateListeners) { + listener(this, previousState, newState, this.keepaliveTime); } return true; } - /** - * Check if the subchannel associated with zero calls and with zero channels. - * If so, shut it down. - */ - private checkBothRefcounts() { - /* If no calls, channels, or subchannel pools have any more references to - * this subchannel, we can be sure it will never be used again. */ - if (this.callRefcount === 0 && this.refcount === 0) { - this.transitionToState( - [ - ConnectivityState.CONNECTING, - ConnectivityState.READY, - ], - ConnectivityState.TRANSIENT_FAILURE - ); - } - } - - callRef() { - refTrace( - this.subchannelAddressString + - ' callRefcount ' + - this.callRefcount + - ' -> ' + - (this.callRefcount + 1) - ); - if (this.callRefcount === 0) { - if (this.session) { - this.session.ref(); - } - this.backoffTimeout.ref(); - if (!this.keepaliveWithoutCalls) { - this.startKeepalivePings(); - } - } - this.callRefcount += 1; - } - - callUnref() { - refTrace( - this.subchannelAddressString + - ' callRefcount ' + - this.callRefcount + - ' -> ' + - (this.callRefcount - 1) - ); - this.callRefcount -= 1; - if (this.callRefcount === 0) { - if (this.session) { - this.session.unref(); - } - this.backoffTimeout.unref(); - if (!this.keepaliveWithoutCalls) { - this.stopKeepalivePings(); - } - this.checkBothRefcounts(); - } - } - ref() { - refTrace( - this.subchannelAddressString + - ' refcount ' + + this.refTrace( + 'refcount ' + this.refcount + ' -> ' + (this.refcount + 1) @@ -666,15 +278,27 @@ export class Subchannel { } unref() { - refTrace( - this.subchannelAddressString + - ' refcount ' + + this.refTrace( + 'refcount ' + this.refcount + ' -> ' + (this.refcount - 1) ); this.refcount -= 1; - this.checkBothRefcounts(); + if (this.refcount === 0) { + if (this.channelzEnabled) { + this.channelzTrace.addTrace('CT_INFO', 'Shutting down'); + } + if (this.channelzEnabled) { + unregisterChannelzRef(this.channelzRef); + } + process.nextTick(() => { + this.transitionToState( + [ConnectivityState.CONNECTING, ConnectivityState.READY], + ConnectivityState.IDLE + ); + }); + } } unrefIfOneRef(): boolean { @@ -685,49 +309,27 @@ export class Subchannel { return false; } - /** - * Start a stream on the current session with the given `metadata` as headers - * and then attach it to the `callStream`. Must only be called if the - * subchannel's current connectivity state is READY. - * @param metadata - * @param callStream - */ - startCallStream( - metadata: Metadata, - callStream: Http2CallStream, - extraFilterFactory?: FilterFactory - ) { - const headers = metadata.toHttp2Headers(); - headers[HTTP2_HEADER_AUTHORITY] = callStream.getHost(); - headers[HTTP2_HEADER_USER_AGENT] = this.userAgent; - headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc'; - headers[HTTP2_HEADER_METHOD] = 'POST'; - headers[HTTP2_HEADER_PATH] = callStream.getMethod(); - headers[HTTP2_HEADER_TE] = 'trailers'; - let http2Stream: http2.ClientHttp2Stream; - /* In theory, if an error is thrown by session.request because session has - * become unusable (e.g. because it has received a goaway), this subchannel - * should soon see the corresponding close or goaway event anyway and leave - * READY. But we have seen reports that this does not happen - * (https://github.com/googleapis/nodejs-firestore/issues/1023#issuecomment-653204096) - * so for defense in depth, we just discard the session when we see an - * error here. - */ - try { - http2Stream = this.session!.request(headers); - } catch (e) { - this.transitionToState( - [ConnectivityState.READY], - ConnectivityState.TRANSIENT_FAILURE - ); - throw e; + createCall(metadata: Metadata, host: string, method: string, listener: SubchannelCallInterceptingListener): SubchannelCall { + if (!this.transport) { + throw new Error('Cannot create call, subchannel not READY'); } - let headersString = ''; - for (const header of Object.keys(headers)) { - headersString += '\t\t' + header + ': ' + headers[header] + '\n'; + let statsTracker: Partial; + if (this.channelzEnabled) { + this.callTracker.addCallStarted(); + this.streamTracker.addCallStarted(); + statsTracker = { + onCallEnd: status => { + if (status.code === Status.OK) { + this.callTracker.addCallSucceeded(); + } else { + this.callTracker.addCallFailed(); + } + } + } + } else { + statsTracker = {}; } - logging.trace(LogVerbosity.DEBUG, 'call_stream', 'Starting stream on subchannel ' + this.subchannelAddressString + ' with headers\n' + headersString); - callStream.attachHttp2Stream(http2Stream, this, extraFilterFactory); + return this.transport.createCall(metadata, host, method, listener, statsTracker); } /** @@ -737,20 +339,22 @@ export class Subchannel { * Otherwise, do nothing. */ startConnecting() { - /* First, try to transition from IDLE to connecting. If that doesn't happen - * because the state is not currently IDLE, check if it is - * TRANSIENT_FAILURE, and if so indicate that it should go back to - * connecting after the backoff timer ends. Otherwise do nothing */ - if ( - !this.transitionToState( - [ConnectivityState.IDLE], - ConnectivityState.CONNECTING - ) - ) { - if (this.connectivityState === ConnectivityState.TRANSIENT_FAILURE) { - this.continueConnecting = true; + process.nextTick(() => { + /* First, try to transition from IDLE to connecting. If that doesn't happen + * because the state is not currently IDLE, check if it is + * TRANSIENT_FAILURE, and if so indicate that it should go back to + * connecting after the backoff timer ends. Otherwise do nothing */ + if ( + !this.transitionToState( + [ConnectivityState.IDLE], + ConnectivityState.CONNECTING + ) + ) { + if (this.connectivityState === ConnectivityState.TRANSIENT_FAILURE) { + this.continueConnecting = true; + } } - } + }); } /** @@ -766,7 +370,7 @@ export class Subchannel { * @param listener */ addConnectivityStateListener(listener: ConnectivityStateListener) { - this.stateListeners.push(listener); + this.stateListeners.add(listener); } /** @@ -775,35 +379,37 @@ export class Subchannel { * `addConnectivityStateListener` */ removeConnectivityStateListener(listener: ConnectivityStateListener) { - const listenerIndex = this.stateListeners.indexOf(listener); - if (listenerIndex > -1) { - this.stateListeners.splice(listenerIndex, 1); - } - } - - addDisconnectListener(listener: () => void) { - this.disconnectListeners.push(listener); - } - - removeDisconnectListener(listener: () => void) { - const listenerIndex = this.disconnectListeners.indexOf(listener); - if (listenerIndex > -1) { - this.disconnectListeners.splice(listenerIndex, 1); - } + this.stateListeners.delete(listener); } /** * Reset the backoff timeout, and immediately start connecting if in backoff. */ resetBackoff() { - this.backoffTimeout.reset(); - this.transitionToState( - [ConnectivityState.TRANSIENT_FAILURE], - ConnectivityState.CONNECTING - ); + process.nextTick(() => { + this.backoffTimeout.reset(); + this.transitionToState( + [ConnectivityState.TRANSIENT_FAILURE], + ConnectivityState.CONNECTING + ); + }); } getAddress(): string { return this.subchannelAddressString; } + + getChannelzRef(): SubchannelRef { + return this.channelzRef; + } + + getRealSubchannel(): this { + return this; + } + + throttleKeepalive(newKeepaliveTime: number) { + if (newKeepaliveTime > this.keepaliveTime) { + this.keepaliveTime = newKeepaliveTime; + } + } } diff --git a/packages/grpc-js/src/transport.ts b/packages/grpc-js/src/transport.ts new file mode 100644 index 000000000..2f89d8f28 --- /dev/null +++ b/packages/grpc-js/src/transport.ts @@ -0,0 +1,669 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as http2 from 'http2'; +import { checkServerIdentity, CipherNameAndProtocol, ConnectionOptions, PeerCertificate, TLSSocket } from 'tls'; +import { StatusObject } from './call-interface'; +import { ChannelCredentials } from './channel-credentials'; +import { ChannelOptions } from './channel-options'; +import { ChannelzCallTracker, registerChannelzSocket, SocketInfo, SocketRef, TlsInfo, unregisterChannelzRef } from './channelz'; +import { LogVerbosity } from './constants'; +import { getProxiedConnection, ProxyConnectionResult } from './http_proxy'; +import * as logging from './logging'; +import { getDefaultAuthority } from './resolver'; +import { stringToSubchannelAddress, SubchannelAddress, subchannelAddressToString } from './subchannel-address'; +import { GrpcUri, parseUri, splitHostPort, uriToString } from './uri-parser'; +import * as net from 'net'; +import { Http2SubchannelCall, SubchannelCall, SubchannelCallInterceptingListener } from './subchannel-call'; +import { Metadata } from './metadata'; +import { getNextCallNumber } from './call-number'; + +const TRACER_NAME = 'transport'; +const FLOW_CONTROL_TRACER_NAME = 'transport_flowctrl'; + +const clientVersion = require('../../package.json').version; + +const { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_CONTENT_TYPE, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_TE, + HTTP2_HEADER_USER_AGENT, +} = http2.constants; + +/* setInterval and setTimeout only accept signed 32 bit integers. JS doesn't + * have a constant for the max signed 32 bit integer, so this is a simple way + * to calculate it */ +const KEEPALIVE_MAX_TIME_MS = ~(1 << 31); +const KEEPALIVE_TIMEOUT_MS = 20000; + +export interface CallEventTracker { + addMessageSent(): void; + addMessageReceived(): void; + onCallEnd(status: StatusObject): void; + onStreamEnd(success: boolean): void; +} + +export interface TransportDisconnectListener { + (tooManyPings: boolean): void; +} + +export interface Transport { + getChannelzRef(): SocketRef; + getPeerName(): string; + createCall(metadata: Metadata, host: string, method: string, listener: SubchannelCallInterceptingListener, subchannelCallStatsTracker: Partial): SubchannelCall; + addDisconnectListener(listener: TransportDisconnectListener): void; + shutdown(): void; +} + +const tooManyPingsData: Buffer = Buffer.from('too_many_pings', 'ascii'); + +class Http2Transport implements Transport { + /** + * The amount of time in between sending pings + */ + private keepaliveTimeMs: number = -1; + /** + * The amount of time to wait for an acknowledgement after sending a ping + */ + private keepaliveTimeoutMs: number = KEEPALIVE_TIMEOUT_MS; + /** + * Timer reference for timeout that indicates when to send the next ping + */ + private keepaliveIntervalId: NodeJS.Timer; + /** + * Timer reference tracking when the most recent ping will be considered lost + */ + private keepaliveTimeoutId: NodeJS.Timer | null = null; + /** + * Indicates whether keepalive pings should be sent without any active calls + */ + private keepaliveWithoutCalls = false; + + private userAgent: string; + + private activeCalls: Set = new Set(); + + private subchannelAddressString: string; + + private disconnectListeners: TransportDisconnectListener[] = []; + + private disconnectHandled = false; + + // Channelz info + private channelzRef: SocketRef; + private readonly channelzEnabled: boolean = true; + /** + * Name of the remote server, if it is not the same as the subchannel + * address, i.e. if connecting through an HTTP CONNECT proxy. + */ + private remoteName: string | null = null; + private streamTracker = new ChannelzCallTracker(); + private keepalivesSent = 0; + private messagesSent = 0; + private messagesReceived = 0; + private lastMessageSentTimestamp: Date | null = null; + private lastMessageReceivedTimestamp: Date | null = null; + + constructor( + private session: http2.ClientHttp2Session, + subchannelAddress: SubchannelAddress, + options: ChannelOptions + ) { + // Build user-agent string. + this.userAgent = [ + options['grpc.primary_user_agent'], + `grpc-node-js/${clientVersion}`, + options['grpc.secondary_user_agent'], + ] + .filter((e) => e) + .join(' '); // remove falsey values first + + if ('grpc.keepalive_time_ms' in options) { + this.keepaliveTimeMs = options['grpc.keepalive_time_ms']!; + } + if ('grpc.keepalive_timeout_ms' in options) { + this.keepaliveTimeoutMs = options['grpc.keepalive_timeout_ms']!; + } + if ('grpc.keepalive_permit_without_calls' in options) { + this.keepaliveWithoutCalls = + options['grpc.keepalive_permit_without_calls'] === 1; + } else { + this.keepaliveWithoutCalls = false; + } + this.keepaliveIntervalId = setTimeout(() => {}, 0); + clearTimeout(this.keepaliveIntervalId); + if (this.keepaliveWithoutCalls) { + this.startKeepalivePings(); + } + + this.subchannelAddressString = subchannelAddressToString(subchannelAddress); + + if (options['grpc.enable_channelz'] === 0) { + this.channelzEnabled = false; + } + this.channelzRef = registerChannelzSocket(this.subchannelAddressString, () => this.getChannelzInfo(), this.channelzEnabled); + + session.once('close', () => { + this.trace('session closed'); + this.stopKeepalivePings(); + this.handleDisconnect(); + }); + session.once('goaway', (errorCode: number, lastStreamID: number, opaqueData: Buffer) => { + let tooManyPings = false; + /* See the last paragraph of + * https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md#basic-keepalive */ + if ( + errorCode === http2.constants.NGHTTP2_ENHANCE_YOUR_CALM && + opaqueData.equals(tooManyPingsData) + ) { + tooManyPings = true; + } + this.trace( + 'connection closed by GOAWAY with code ' + + errorCode + ); + this.reportDisconnectToOwner(tooManyPings); + }); + session.once('error', error => { + /* Do nothing here. Any error should also trigger a close event, which is + * where we want to handle that. */ + this.trace( + 'connection closed with error ' + + (error as Error).message + ); + }); + if (logging.isTracerEnabled(TRACER_NAME)) { + session.on('remoteSettings', (settings: http2.Settings) => { + this.trace( + 'new settings received' + + (this.session !== session ? ' on the old connection' : '') + + ': ' + + JSON.stringify(settings) + ); + }); + session.on('localSettings', (settings: http2.Settings) => { + this.trace( + 'local settings acknowledged by remote' + + (this.session !== session ? ' on the old connection' : '') + + ': ' + + JSON.stringify(settings) + ); + }); + } + } + + private getChannelzInfo(): SocketInfo { + const sessionSocket = this.session.socket; + const remoteAddress = sessionSocket.remoteAddress ? stringToSubchannelAddress(sessionSocket.remoteAddress, sessionSocket.remotePort) : null; + const localAddress = sessionSocket.localAddress ? stringToSubchannelAddress(sessionSocket.localAddress, sessionSocket.localPort) : null; + let tlsInfo: TlsInfo | null; + if (this.session.encrypted) { + const tlsSocket: TLSSocket = sessionSocket as TLSSocket; + const cipherInfo: CipherNameAndProtocol & {standardName?: string} = tlsSocket.getCipher(); + const certificate = tlsSocket.getCertificate(); + const peerCertificate = tlsSocket.getPeerCertificate(); + tlsInfo = { + cipherSuiteStandardName: cipherInfo.standardName ?? null, + cipherSuiteOtherName: cipherInfo.standardName ? null : cipherInfo.name, + localCertificate: (certificate && 'raw' in certificate) ? certificate.raw : null, + remoteCertificate: (peerCertificate && 'raw' in peerCertificate) ? peerCertificate.raw : null + }; + } else { + tlsInfo = null; + } + const socketInfo: SocketInfo = { + remoteAddress: remoteAddress, + localAddress: localAddress, + security: tlsInfo, + remoteName: this.remoteName, + streamsStarted: this.streamTracker.callsStarted, + streamsSucceeded: this.streamTracker.callsSucceeded, + streamsFailed: this.streamTracker.callsFailed, + messagesSent: this.messagesSent, + messagesReceived: this.messagesReceived, + keepAlivesSent: this.keepalivesSent, + lastLocalStreamCreatedTimestamp: this.streamTracker.lastCallStartedTimestamp, + lastRemoteStreamCreatedTimestamp: null, + lastMessageSentTimestamp: this.lastMessageSentTimestamp, + lastMessageReceivedTimestamp: this.lastMessageReceivedTimestamp, + localFlowControlWindow: this.session.state.localWindowSize ?? null, + remoteFlowControlWindow: this.session.state.remoteWindowSize ?? null + }; + return socketInfo; + } + + private trace(text: string): void { + logging.trace(LogVerbosity.DEBUG, TRACER_NAME, '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); + } + + private keepaliveTrace(text: string): void { + logging.trace(LogVerbosity.DEBUG, 'keepalive', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); + } + + private flowControlTrace(text: string): void { + logging.trace(LogVerbosity.DEBUG, FLOW_CONTROL_TRACER_NAME, '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); + } + + private internalsTrace(text: string): void { + logging.trace(LogVerbosity.DEBUG, 'transport_internals', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); + } + + /** + * Indicate to the owner of this object that this transport should no longer + * be used. That happens if the connection drops, or if the server sends a + * GOAWAY. + * @param tooManyPings If true, this was triggered by a GOAWAY with data + * indicating that the session was closed becaues the client sent too many + * pings. + * @returns + */ + private reportDisconnectToOwner(tooManyPings: boolean) { + if (this.disconnectHandled) { + return; + } + this.disconnectHandled = true; + this.disconnectListeners.forEach(listener => listener(tooManyPings)); + } + + /** + * Handle connection drops, but not GOAWAYs. + */ + private handleDisconnect() { + this.reportDisconnectToOwner(false); + /* Give calls an event loop cycle to finish naturally before reporting the + * disconnnection to them. */ + setImmediate(() => { + for (const call of this.activeCalls) { + call.onDisconnect(); + } + }); + } + + addDisconnectListener(listener: TransportDisconnectListener): void { + this.disconnectListeners.push(listener); + } + + private clearKeepaliveTimeout() { + if (!this.keepaliveTimeoutId) { + return; + } + clearTimeout(this.keepaliveTimeoutId); + this.keepaliveTimeoutId = null; + } + + private sendPing() { + if (this.channelzEnabled) { + this.keepalivesSent += 1; + } + this.keepaliveTrace('Sending ping with timeout ' + this.keepaliveTimeoutMs + 'ms'); + if (!this.keepaliveTimeoutId) { + this.keepaliveTimeoutId = setTimeout(() => { + this.keepaliveTrace('Ping timeout passed without response'); + this.handleDisconnect(); + }, this.keepaliveTimeoutMs); + this.keepaliveTimeoutId.unref?.(); + } + try { + this.session!.ping( + (err: Error | null, duration: number, payload: Buffer) => { + this.keepaliveTrace('Received ping response'); + this.clearKeepaliveTimeout(); + } + ); + } catch (e) { + /* If we fail to send a ping, the connection is no longer functional, so + * we should discard it. */ + this.handleDisconnect(); + } + } + + private startKeepalivePings() { + if (this.keepaliveTimeMs < 0) { + return; + } + this.keepaliveIntervalId = setInterval(() => { + this.sendPing(); + }, this.keepaliveTimeMs); + this.keepaliveIntervalId.unref?.(); + /* Don't send a ping immediately because whatever caused us to start + * sending pings should also involve some network activity. */ + } + + /** + * Stop keepalive pings when terminating a connection. This discards the + * outstanding ping timeout, so it should not be called if the same + * connection will still be used. + */ + private stopKeepalivePings() { + clearInterval(this.keepaliveIntervalId); + this.clearKeepaliveTimeout(); + } + + private removeActiveCall(call: Http2SubchannelCall) { + this.activeCalls.delete(call); + if (this.activeCalls.size === 0) { + this.session.unref(); + if (!this.keepaliveWithoutCalls) { + this.stopKeepalivePings(); + } + } + } + + private addActiveCall(call: Http2SubchannelCall) { + if (this.activeCalls.size === 0) { + this.session.ref(); + if (!this.keepaliveWithoutCalls) { + this.startKeepalivePings(); + } + } + this.activeCalls.add(call); + } + + createCall(metadata: Metadata, host: string, method: string, listener: SubchannelCallInterceptingListener, subchannelCallStatsTracker: Partial): Http2SubchannelCall { + const headers = metadata.toHttp2Headers(); + headers[HTTP2_HEADER_AUTHORITY] = host; + headers[HTTP2_HEADER_USER_AGENT] = this.userAgent; + headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc'; + headers[HTTP2_HEADER_METHOD] = 'POST'; + headers[HTTP2_HEADER_PATH] = method; + headers[HTTP2_HEADER_TE] = 'trailers'; + let http2Stream: http2.ClientHttp2Stream; + /* In theory, if an error is thrown by session.request because session has + * become unusable (e.g. because it has received a goaway), this subchannel + * should soon see the corresponding close or goaway event anyway and leave + * READY. But we have seen reports that this does not happen + * (https://github.com/googleapis/nodejs-firestore/issues/1023#issuecomment-653204096) + * so for defense in depth, we just discard the session when we see an + * error here. + */ + try { + http2Stream = this.session!.request(headers); + } catch (e) { + this.handleDisconnect(); + throw e; + } + this.flowControlTrace( + 'local window size: ' + + this.session.state.localWindowSize + + ' remote window size: ' + + this.session.state.remoteWindowSize + ); + this.internalsTrace( + 'session.closed=' + + this.session.closed + + ' session.destroyed=' + + this.session.destroyed + + ' session.socket.destroyed=' + + this.session.socket.destroyed); + let eventTracker: CallEventTracker; + let call: Http2SubchannelCall; + if (this.channelzEnabled) { + this.streamTracker.addCallStarted(); + eventTracker = { + addMessageSent: () => { + this.messagesSent += 1; + this.lastMessageSentTimestamp = new Date(); + subchannelCallStatsTracker.addMessageSent?.(); + }, + addMessageReceived: () => { + this.messagesReceived += 1; + this.lastMessageReceivedTimestamp = new Date(); + subchannelCallStatsTracker.addMessageReceived?.(); + }, + onCallEnd: status => { + subchannelCallStatsTracker.onCallEnd?.(status); + this.removeActiveCall(call); + }, + onStreamEnd: success => { + if (success) { + this.streamTracker.addCallSucceeded(); + } else { + this.streamTracker.addCallFailed(); + } + subchannelCallStatsTracker.onStreamEnd?.(success); + } + } + } else { + eventTracker = { + addMessageSent: () => { + subchannelCallStatsTracker.addMessageSent?.(); + }, + addMessageReceived: () => { + subchannelCallStatsTracker.addMessageReceived?.(); + }, + onCallEnd: (status) => { + subchannelCallStatsTracker.onCallEnd?.(status); + this.removeActiveCall(call); + }, + onStreamEnd: (success) => { + subchannelCallStatsTracker.onStreamEnd?.(success); + } + } + } + call = new Http2SubchannelCall(http2Stream, eventTracker, listener, this, getNextCallNumber()); + this.addActiveCall(call); + return call; + } + + getChannelzRef(): SocketRef { + return this.channelzRef; + } + + getPeerName() { + return this.subchannelAddressString; + } + + shutdown() { + this.session.close(); + unregisterChannelzRef(this.channelzRef); + } +} + +export interface SubchannelConnector { + connect(address: SubchannelAddress, credentials: ChannelCredentials, options: ChannelOptions): Promise; + shutdown(): void; +} + +export class Http2SubchannelConnector implements SubchannelConnector { + private session: http2.ClientHttp2Session | null = null; + private isShutdown = false; + constructor(private channelTarget: GrpcUri) {} + private trace(text: string) { + logging.trace(LogVerbosity.DEBUG, TRACER_NAME, this.channelTarget + ' ' + text); + } + private createSession(address: SubchannelAddress, credentials: ChannelCredentials, options: ChannelOptions, proxyConnectionResult: ProxyConnectionResult): Promise { + if (this.isShutdown) { + return Promise.reject(); + } + return new Promise((resolve, reject) => { + let remoteName: string | null; + if (proxyConnectionResult.realTarget) { + remoteName = uriToString(proxyConnectionResult.realTarget); + this.trace('creating HTTP/2 session through proxy to ' + uriToString(proxyConnectionResult.realTarget)); + } else { + remoteName = null; + this.trace('creating HTTP/2 session to ' + subchannelAddressToString(address)); + } + const targetAuthority = getDefaultAuthority( + proxyConnectionResult.realTarget ?? this.channelTarget + ); + let connectionOptions: http2.SecureClientSessionOptions = + credentials._getConnectionOptions() || {}; + connectionOptions.maxSendHeaderBlockLength = Number.MAX_SAFE_INTEGER; + if ('grpc-node.max_session_memory' in options) { + connectionOptions.maxSessionMemory = options[ + 'grpc-node.max_session_memory' + ]; + } else { + /* By default, set a very large max session memory limit, to effectively + * disable enforcement of the limit. Some testing indicates that Node's + * behavior degrades badly when this limit is reached, so we solve that + * by disabling the check entirely. */ + connectionOptions.maxSessionMemory = Number.MAX_SAFE_INTEGER; + } + let addressScheme = 'http://'; + if ('secureContext' in connectionOptions) { + addressScheme = 'https://'; + // If provided, the value of grpc.ssl_target_name_override should be used + // to override the target hostname when checking server identity. + // This option is used for testing only. + if (options['grpc.ssl_target_name_override']) { + const sslTargetNameOverride = options[ + 'grpc.ssl_target_name_override' + ]!; + connectionOptions.checkServerIdentity = ( + host: string, + cert: PeerCertificate + ): Error | undefined => { + return checkServerIdentity(sslTargetNameOverride, cert); + }; + connectionOptions.servername = sslTargetNameOverride; + } else { + const authorityHostname = + splitHostPort(targetAuthority)?.host ?? 'localhost'; + // We want to always set servername to support SNI + connectionOptions.servername = authorityHostname; + } + if (proxyConnectionResult.socket) { + /* This is part of the workaround for + * https://github.com/nodejs/node/issues/32922. Without that bug, + * proxyConnectionResult.socket would always be a plaintext socket and + * this would say + * connectionOptions.socket = proxyConnectionResult.socket; */ + connectionOptions.createConnection = (authority, option) => { + return proxyConnectionResult.socket!; + }; + } + } else { + /* In all but the most recent versions of Node, http2.connect does not use + * the options when establishing plaintext connections, so we need to + * establish that connection explicitly. */ + connectionOptions.createConnection = (authority, option) => { + if (proxyConnectionResult.socket) { + return proxyConnectionResult.socket; + } else { + /* net.NetConnectOpts is declared in a way that is more restrictive + * than what net.connect will actually accept, so we use the type + * assertion to work around that. */ + return net.connect(address); + } + }; + } + + connectionOptions = { + ...connectionOptions, + ...address, + }; + + /* http2.connect uses the options here: + * https://github.com/nodejs/node/blob/70c32a6d190e2b5d7b9ff9d5b6a459d14e8b7d59/lib/internal/http2/core.js#L3028-L3036 + * The spread operator overides earlier values with later ones, so any port + * or host values in the options will be used rather than any values extracted + * from the first argument. In addition, the path overrides the host and port, + * as documented for plaintext connections here: + * https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener + * and for TLS connections here: + * https://nodejs.org/api/tls.html#tls_tls_connect_options_callback. In + * earlier versions of Node, http2.connect passes these options to + * tls.connect but not net.connect, so in the insecure case we still need + * to set the createConnection option above to create the connection + * explicitly. We cannot do that in the TLS case because http2.connect + * passes necessary additional options to tls.connect. + * The first argument just needs to be parseable as a URL and the scheme + * determines whether the connection will be established over TLS or not. + */ + const session = http2.connect( + addressScheme + targetAuthority, + connectionOptions + ); + this.session = session; + session.unref(); + session.once('connect', () => { + session.removeAllListeners(); + resolve(new Http2Transport(session, address, options)); + this.session = null; + }); + session.once('close', () => { + this.session = null; + reject(); + }); + session.once('error', error => { + this.trace('connection failed with error ' + (error as Error).message) + }); + }); + } + connect(address: SubchannelAddress, credentials: ChannelCredentials, options: ChannelOptions): Promise { + if (this.isShutdown) { + return Promise.reject(); + } + /* Pass connection options through to the proxy so that it's able to + * upgrade it's connection to support tls if needed. + * This is a workaround for https://github.com/nodejs/node/issues/32922 + * See https://github.com/grpc/grpc-node/pull/1369 for more info. */ + const connectionOptions: ConnectionOptions = + credentials._getConnectionOptions() || {}; + + if ('secureContext' in connectionOptions) { + connectionOptions.ALPNProtocols = ['h2']; + // If provided, the value of grpc.ssl_target_name_override should be used + // to override the target hostname when checking server identity. + // This option is used for testing only. + if (options['grpc.ssl_target_name_override']) { + const sslTargetNameOverride = options[ + 'grpc.ssl_target_name_override' + ]!; + connectionOptions.checkServerIdentity = ( + host: string, + cert: PeerCertificate + ): Error | undefined => { + return checkServerIdentity(sslTargetNameOverride, cert); + }; + connectionOptions.servername = sslTargetNameOverride; + } else { + if ('grpc.http_connect_target' in options) { + /* This is more or less how servername will be set in createSession + * if a connection is successfully established through the proxy. + * If the proxy is not used, these connectionOptions are discarded + * anyway */ + const targetPath = getDefaultAuthority( + parseUri(options['grpc.http_connect_target'] as string) ?? { + path: 'localhost', + } + ); + const hostPort = splitHostPort(targetPath); + connectionOptions.servername = hostPort?.host ?? targetPath; + } + } + } + + return getProxiedConnection( + address, + options, + connectionOptions + ).then( + result => this.createSession(address, credentials, options, result) + ); + } + + shutdown(): void { + this.isShutdown = true; + this.session?.close(); + this.session = null; + } +} \ No newline at end of file diff --git a/packages/grpc-js/test/fixtures/test_service.proto b/packages/grpc-js/test/fixtures/test_service.proto index f99393d14..64ce0d378 100644 --- a/packages/grpc-js/test/fixtures/test_service.proto +++ b/packages/grpc-js/test/fixtures/test_service.proto @@ -25,6 +25,7 @@ message Request { message Response { int32 count = 1; + string message = 2; } service TestService { diff --git a/packages/grpc-js/test/generated/Request.ts b/packages/grpc-js/test/generated/Request.ts new file mode 100644 index 000000000..d64ebb6ea --- /dev/null +++ b/packages/grpc-js/test/generated/Request.ts @@ -0,0 +1,14 @@ +// Original file: test/fixtures/test_service.proto + + +export interface Request { + 'error'?: (boolean); + 'message'?: (string); + 'errorAfter'?: (number); +} + +export interface Request__Output { + 'error': (boolean); + 'message': (string); + 'errorAfter': (number); +} diff --git a/packages/grpc-js/test/generated/Response.ts b/packages/grpc-js/test/generated/Response.ts new file mode 100644 index 000000000..465ab7203 --- /dev/null +++ b/packages/grpc-js/test/generated/Response.ts @@ -0,0 +1,12 @@ +// Original file: test/fixtures/test_service.proto + + +export interface Response { + 'count'?: (number); + 'message'?: (string); +} + +export interface Response__Output { + 'count': (number); + 'message': (string); +} diff --git a/packages/grpc-js/test/generated/TestService.ts b/packages/grpc-js/test/generated/TestService.ts new file mode 100644 index 000000000..e477c99b5 --- /dev/null +++ b/packages/grpc-js/test/generated/TestService.ts @@ -0,0 +1,55 @@ +// Original file: test/fixtures/test_service.proto + +import type * as grpc from './../../src/index' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { Request as _Request, Request__Output as _Request__Output } from './Request'; +import type { Response as _Response, Response__Output as _Response__Output } from './Response'; + +export interface TestServiceClient extends grpc.Client { + BidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_Request, _Response__Output>; + BidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_Request, _Response__Output>; + bidiStream(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_Request, _Response__Output>; + bidiStream(options?: grpc.CallOptions): grpc.ClientDuplexStream<_Request, _Response__Output>; + + ClientStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + ClientStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + ClientStream(options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + ClientStream(callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + clientStream(callback: grpc.requestCallback<_Response__Output>): grpc.ClientWritableStream<_Request>; + + ServerStream(argument: _Request, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; + ServerStream(argument: _Request, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; + serverStream(argument: _Request, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; + serverStream(argument: _Request, options?: grpc.CallOptions): grpc.ClientReadableStream<_Response__Output>; + + Unary(argument: _Request, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + Unary(argument: _Request, metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + Unary(argument: _Request, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + Unary(argument: _Request, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, metadata: grpc.Metadata, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, options: grpc.CallOptions, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + unary(argument: _Request, callback: grpc.requestCallback<_Response__Output>): grpc.ClientUnaryCall; + +} + +export interface TestServiceHandlers extends grpc.UntypedServiceImplementation { + BidiStream: grpc.handleBidiStreamingCall<_Request__Output, _Response>; + + ClientStream: grpc.handleClientStreamingCall<_Request__Output, _Response>; + + ServerStream: grpc.handleServerStreamingCall<_Request__Output, _Response>; + + Unary: grpc.handleUnaryCall<_Request__Output, _Response>; + +} + +export interface TestServiceDefinition extends grpc.ServiceDefinition { + BidiStream: MethodDefinition<_Request, _Response, _Request__Output, _Response__Output> + ClientStream: MethodDefinition<_Request, _Response, _Request__Output, _Response__Output> + ServerStream: MethodDefinition<_Request, _Response, _Request__Output, _Response__Output> + Unary: MethodDefinition<_Request, _Response, _Request__Output, _Response__Output> +} diff --git a/packages/grpc-js/test/generated/test_service.ts b/packages/grpc-js/test/generated/test_service.ts new file mode 100644 index 000000000..364acddeb --- /dev/null +++ b/packages/grpc-js/test/generated/test_service.ts @@ -0,0 +1,15 @@ +import type * as grpc from '../../src/index'; +import type { MessageTypeDefinition } from '@grpc/proto-loader'; + +import type { TestServiceClient as _TestServiceClient, TestServiceDefinition as _TestServiceDefinition } from './TestService'; + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + Request: MessageTypeDefinition + Response: MessageTypeDefinition + TestService: SubtypeConstructor & { service: _TestServiceDefinition } +} + diff --git a/packages/grpc-js/test/test-channel-credentials.ts b/packages/grpc-js/test/test-channel-credentials.ts index d6028f469..2b537ac97 100644 --- a/packages/grpc-js/test/test-channel-credentials.ts +++ b/packages/grpc-js/test/test-channel-credentials.ts @@ -17,12 +17,22 @@ import * as assert from 'assert'; import * as fs from 'fs'; +import * as path from 'path'; import { promisify } from 'util'; +import * as protoLoader from '@grpc/proto-loader'; import { CallCredentials } from '../src/call-credentials'; import { ChannelCredentials } from '../src/channel-credentials'; +import * as grpc from '../src'; +import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; +import { TestServiceClient, TestServiceHandlers } from './generated/TestService'; +import { ProtoGrpcType as TestServiceGrpcType } from './generated/test_service'; -import { assert2, mockFunction } from './common'; +import { assert2, loadProtoFile, mockFunction } from './common'; +import { sendUnaryData, ServerUnaryCall, ServiceError } from '../src'; + +const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); +const echoService = loadProtoFile(protoFile).EchoService as ServiceClientConstructor; class CallCredentialsMock implements CallCredentials { child: CallCredentialsMock | null = null; @@ -138,3 +148,65 @@ describe('ChannelCredentials Implementation', () => { }); }); }); + +describe('ChannelCredentials usage', () => { + let client: ServiceClient; + let server: grpc.Server; + before(async () => { + const {ca, key, cert} = await pFixtures; + const serverCreds = grpc.ServerCredentials.createSsl(null, [{private_key: key, cert_chain: cert}]); + const channelCreds = ChannelCredentials.createSsl(ca); + const callCreds = CallCredentials.createFromMetadataGenerator((options, cb) => { + const metadata = new grpc.Metadata(); + metadata.set('test-key', 'test-value'); + cb(null, metadata); + }); + const combinedCreds = channelCreds.compose(callCreds); + return new Promise((resolve, reject) => { + + server = new grpc.Server(); + server.addService(echoService.service, { + echo(call: ServerUnaryCall, callback: sendUnaryData) { + call.sendMetadata(call.metadata); + callback(null, call.request); + }, + }); + + server.bindAsync( + 'localhost:0', + serverCreds, + (err, port) => { + if (err) { + reject(err); + return; + } + client = new echoService( + `localhost:${port}`, + combinedCreds, + {'grpc.ssl_target_name_override': 'foo.test.google.fr', 'grpc.default_authority': 'foo.test.google.fr'} + ); + server.start(); + resolve(); + } + ); + }); + }); + after(() => { + server.forceShutdown(); + }); + + it('Should send the metadata from call credentials attached to channel credentials', (done) => { + const call = client.echo( + { value: 'test value', value2: 3 }, + assert2.mustCall((error: ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + }) + ); + call.on('metadata', assert2.mustCall((metadata: grpc.Metadata) => { + assert.deepStrictEqual(metadata.get('test-key'), ['test-value']); + + })); + assert2.afterMustCallsSatisfied(done); + }); +}); \ No newline at end of file diff --git a/packages/grpc-js/test/test-channelz.ts b/packages/grpc-js/test/test-channelz.ts new file mode 100644 index 000000000..f14145c37 --- /dev/null +++ b/packages/grpc-js/test/test-channelz.ts @@ -0,0 +1,321 @@ +/* + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as assert from 'assert'; +import * as protoLoader from '@grpc/proto-loader'; +import * as grpc from '../src'; + +import { ProtoGrpcType } from '../src/generated/channelz' +import { ChannelzClient } from '../src/generated/grpc/channelz/v1/Channelz'; +import { Channel__Output } from '../src/generated/grpc/channelz/v1/Channel'; +import { Server__Output } from '../src/generated/grpc/channelz/v1/Server'; +import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; +import { loadProtoFile } from './common'; + +const loadedChannelzProto = protoLoader.loadSync('channelz.proto', { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + includeDirs: [ + `${__dirname}/../../proto` + ] +}); +const channelzGrpcObject = grpc.loadPackageDefinition(loadedChannelzProto) as unknown as ProtoGrpcType; + +const TestServiceClient = loadProtoFile(`${__dirname}/fixtures/test_service.proto`).TestService as ServiceClientConstructor; + +const testServiceImpl: grpc.UntypedServiceImplementation = { + unary(call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData) { + if (call.request.error) { + setTimeout(() => { + callback({ + code: grpc.status.INVALID_ARGUMENT, + details: call.request.message + }); + }, call.request.errorAfter) + } else { + callback(null, {count: 1}); + } + } +} + +describe('Channelz', () => { + let channelzServer: grpc.Server; + let channelzClient: ChannelzClient; + let testServer: grpc.Server; + let testClient: ServiceClient; + + before((done) => { + channelzServer = new grpc.Server(); + channelzServer.addService(grpc.getChannelzServiceDefinition(), grpc.getChannelzHandlers()); + channelzServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { + if (error) { + done(error); + return; + } + channelzServer.start(); + channelzClient = new channelzGrpcObject.grpc.channelz.v1.Channelz(`localhost:${port}`, grpc.credentials.createInsecure()); + done(); + }); + }); + + after(() => { + channelzClient.close(); + channelzServer.forceShutdown(); + }); + + beforeEach((done) => { + testServer = new grpc.Server(); + testServer.addService(TestServiceClient.service, testServiceImpl); + testServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { + if (error) { + done(error); + return; + } + testServer.start(); + testClient = new TestServiceClient(`localhost:${port}`, grpc.credentials.createInsecure()); + done(); + }); + }); + + afterEach(() => { + testClient.close(); + testServer.forceShutdown(); + }); + + it('should see a newly created channel', (done) => { + // Test that the specific test client channel info can be retrieved + channelzClient.GetChannel({channel_id: testClient.getChannel().getChannelzRef().id}, (error, result) => { + assert.ifError(error); + assert(result); + assert(result.channel); + assert(result.channel.ref); + assert.strictEqual(+result.channel.ref.channel_id, testClient.getChannel().getChannelzRef().id); + // Test that the channel is in the list of top channels + channelzClient.getTopChannels({start_channel_id: testClient.getChannel().getChannelzRef().id, max_results:1}, (error, result) => { + assert.ifError(error); + assert(result); + assert.strictEqual(result.channel.length, 1); + assert(result.channel[0].ref); + assert.strictEqual(+result.channel[0].ref.channel_id, testClient.getChannel().getChannelzRef().id); + done(); + }); + }); + }); + + it('should see a newly created server', (done) => { + // Test that the specific test server info can be retrieved + channelzClient.getServer({server_id: testServer.getChannelzRef().id}, (error, result) => { + assert.ifError(error); + assert(result); + assert(result.server); + assert(result.server.ref); + assert.strictEqual(+result.server.ref.server_id, testServer.getChannelzRef().id); + // Test that the server is in the list of servers + channelzClient.getServers({start_server_id: testServer.getChannelzRef().id, max_results: 1}, (error, result) => { + assert.ifError(error); + assert(result); + assert.strictEqual(result.server.length, 1); + assert(result.server[0].ref); + assert.strictEqual(+result.server[0].ref.server_id, testServer.getChannelzRef().id); + done(); + }); + }); + }); + + it('should count successful calls', (done) => { + testClient.unary({}, (error: grpc.ServiceError, value: unknown) => { + assert.ifError(error); + // Channel data tests + channelzClient.GetChannel({channel_id: testClient.getChannel().getChannelzRef().id}, (error, channelResult) => { + assert.ifError(error); + assert(channelResult); + assert(channelResult.channel); + assert(channelResult.channel.ref); + assert(channelResult.channel.data); + assert.strictEqual(+channelResult.channel.data.calls_started, 1); + assert.strictEqual(+channelResult.channel.data.calls_succeeded, 1); + assert.strictEqual(+channelResult.channel.data.calls_failed, 0); + assert.strictEqual(channelResult.channel.subchannel_ref.length, 1); + channelzClient.getSubchannel({subchannel_id: channelResult.channel.subchannel_ref[0].subchannel_id}, (error, subchannelResult) => { + assert.ifError(error); + assert(subchannelResult); + assert(subchannelResult.subchannel); + assert(subchannelResult.subchannel.ref); + assert(subchannelResult.subchannel.data); + assert.strictEqual(subchannelResult.subchannel.ref.subchannel_id, channelResult.channel!.subchannel_ref[0].subchannel_id); + assert.strictEqual(+subchannelResult.subchannel.data.calls_started, 1); + assert.strictEqual(+subchannelResult.subchannel.data.calls_succeeded, 1); + assert.strictEqual(+subchannelResult.subchannel.data.calls_failed, 0); + assert.strictEqual(subchannelResult.subchannel.socket_ref.length, 1); + channelzClient.getSocket({socket_id: subchannelResult.subchannel.socket_ref[0].socket_id}, (error, socketResult) => { + assert.ifError(error); + assert(socketResult); + assert(socketResult.socket); + assert(socketResult.socket.ref); + assert(socketResult.socket.data); + assert.strictEqual(socketResult.socket.ref.socket_id, subchannelResult.subchannel!.socket_ref[0].socket_id); + assert.strictEqual(+socketResult.socket.data.streams_started, 1); + assert.strictEqual(+socketResult.socket.data.streams_succeeded, 1); + assert.strictEqual(+socketResult.socket.data.streams_failed, 0); + assert.strictEqual(+socketResult.socket.data.messages_received, 1); + assert.strictEqual(+socketResult.socket.data.messages_sent, 1); + // Server data tests + channelzClient.getServer({server_id: testServer.getChannelzRef().id}, (error, serverResult) => { + assert.ifError(error); + assert(serverResult); + assert(serverResult.server); + assert(serverResult.server.ref); + assert(serverResult.server.data); + assert.strictEqual(+serverResult.server.ref.server_id, testServer.getChannelzRef().id); + assert.strictEqual(+serverResult.server.data.calls_started, 1); + assert.strictEqual(+serverResult.server.data.calls_succeeded, 1); + assert.strictEqual(+serverResult.server.data.calls_failed, 0); + channelzClient.getServerSockets({server_id: testServer.getChannelzRef().id}, (error, socketsResult) => { + assert.ifError(error); + assert(socketsResult); + assert.strictEqual(socketsResult.socket_ref.length, 1); + channelzClient.getSocket({socket_id: socketsResult.socket_ref[0].socket_id}, (error, serverSocketResult) => { + assert.ifError(error); + assert(serverSocketResult); + assert(serverSocketResult.socket); + assert(serverSocketResult.socket.ref); + assert(serverSocketResult.socket.data); + assert.strictEqual(serverSocketResult.socket.ref.socket_id, socketsResult.socket_ref[0].socket_id); + assert.strictEqual(+serverSocketResult.socket.data.streams_started, 1); + assert.strictEqual(+serverSocketResult.socket.data.streams_succeeded, 1); + assert.strictEqual(+serverSocketResult.socket.data.streams_failed, 0); + assert.strictEqual(+serverSocketResult.socket.data.messages_received, 1); + assert.strictEqual(+serverSocketResult.socket.data.messages_sent, 1); + done(); + }); + }); + }); + }); + }); + }); + }); + }); + + it('should count failed calls', (done) => { + testClient.unary({error: true}, (error: grpc.ServiceError, value: unknown) => { + assert(error); + // Channel data tests + channelzClient.GetChannel({channel_id: testClient.getChannel().getChannelzRef().id}, (error, channelResult) => { + assert.ifError(error); + assert(channelResult); + assert(channelResult.channel); + assert(channelResult.channel.ref); + assert(channelResult.channel.data); + assert.strictEqual(+channelResult.channel.data.calls_started, 1); + assert.strictEqual(+channelResult.channel.data.calls_succeeded, 0); + assert.strictEqual(+channelResult.channel.data.calls_failed, 1); + assert.strictEqual(channelResult.channel.subchannel_ref.length, 1); + channelzClient.getSubchannel({subchannel_id: channelResult.channel.subchannel_ref[0].subchannel_id}, (error, subchannelResult) => { + assert.ifError(error); + assert(subchannelResult); + assert(subchannelResult.subchannel); + assert(subchannelResult.subchannel.ref); + assert(subchannelResult.subchannel.data); + assert.strictEqual(subchannelResult.subchannel.ref.subchannel_id, channelResult.channel!.subchannel_ref[0].subchannel_id); + assert.strictEqual(+subchannelResult.subchannel.data.calls_started, 1); + assert.strictEqual(+subchannelResult.subchannel.data.calls_succeeded, 0); + assert.strictEqual(+subchannelResult.subchannel.data.calls_failed, 1); + assert.strictEqual(subchannelResult.subchannel.socket_ref.length, 1); + channelzClient.getSocket({socket_id: subchannelResult.subchannel.socket_ref[0].socket_id}, (error, socketResult) => { + assert.ifError(error); + assert(socketResult); + assert(socketResult.socket); + assert(socketResult.socket.ref); + assert(socketResult.socket.data); + assert.strictEqual(socketResult.socket.ref.socket_id, subchannelResult.subchannel!.socket_ref[0].socket_id); + assert.strictEqual(+socketResult.socket.data.streams_started, 1); + assert.strictEqual(+socketResult.socket.data.streams_succeeded, 1); + assert.strictEqual(+socketResult.socket.data.streams_failed, 0); + assert.strictEqual(+socketResult.socket.data.messages_received, 0); + assert.strictEqual(+socketResult.socket.data.messages_sent, 1); + // Server data tests + channelzClient.getServer({server_id: testServer.getChannelzRef().id}, (error, serverResult) => { + assert.ifError(error); + assert(serverResult); + assert(serverResult.server); + assert(serverResult.server.ref); + assert(serverResult.server.data); + assert.strictEqual(+serverResult.server.ref.server_id, testServer.getChannelzRef().id); + assert.strictEqual(+serverResult.server.data.calls_started, 1); + assert.strictEqual(+serverResult.server.data.calls_succeeded, 0); + assert.strictEqual(+serverResult.server.data.calls_failed, 1); + channelzClient.getServerSockets({server_id: testServer.getChannelzRef().id}, (error, socketsResult) => { + assert.ifError(error); + assert(socketsResult); + assert.strictEqual(socketsResult.socket_ref.length, 1); + channelzClient.getSocket({socket_id: socketsResult.socket_ref[0].socket_id}, (error, serverSocketResult) => { + assert.ifError(error); + assert(serverSocketResult); + assert(serverSocketResult.socket); + assert(serverSocketResult.socket.ref); + assert(serverSocketResult.socket.data); + assert.strictEqual(serverSocketResult.socket.ref.socket_id, socketsResult.socket_ref[0].socket_id); + assert.strictEqual(+serverSocketResult.socket.data.streams_started, 1); + assert.strictEqual(+serverSocketResult.socket.data.streams_succeeded, 0); + assert.strictEqual(+serverSocketResult.socket.data.streams_failed, 1); + assert.strictEqual(+serverSocketResult.socket.data.messages_received, 1); + assert.strictEqual(+serverSocketResult.socket.data.messages_sent, 0); + done(); + }); + }); + }); + }); + }); + }); + }); + }); +}); + +describe('Disabling channelz', () => { + let testServer: grpc.Server; + let testClient: ServiceClient; + beforeEach((done) => { + testServer = new grpc.Server({'grpc.enable_channelz': 0}); + testServer.addService(TestServiceClient.service, testServiceImpl); + testServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { + if (error) { + done(error); + return; + } + testServer.start(); + testClient = new TestServiceClient(`localhost:${port}`, grpc.credentials.createInsecure(), {'grpc.enable_channelz': 0}); + done(); + }); + }); + + afterEach(() => { + testClient.close(); + testServer.forceShutdown(); + }); + + it('Should still work', (done) => { + const deadline = new Date(); + deadline.setSeconds(deadline.getSeconds() + 1); + testClient.unary({}, {deadline}, (error: grpc.ServiceError, value: unknown) => { + assert.ifError(error); + done(); + }); + }); +}); \ No newline at end of file diff --git a/packages/grpc-js/test/test-client.ts b/packages/grpc-js/test/test-client.ts index 0d2878cbc..21dad99f1 100644 --- a/packages/grpc-js/test/test-client.ts +++ b/packages/grpc-js/test/test-client.ts @@ -20,7 +20,7 @@ import * as assert from 'assert'; import * as grpc from '../src'; import { Server, ServerCredentials } from '../src'; import { Client } from '../src'; -import { ConnectivityState } from '../src/channel'; +import { ConnectivityState } from "../src/connectivity-state"; const clientInsecureCreds = grpc.credentials.createInsecure(); const serverInsecureCreds = ServerCredentials.createInsecure(); @@ -79,7 +79,32 @@ describe('Client without a server', () => { after(() => { client.close(); }); - it('should fail multiple calls to the nonexistent server', done => { + it('should fail multiple calls to the nonexistent server', function(done) { + this.timeout(5000); + // Regression test for https://github.com/grpc/grpc-node/issues/1411 + client.makeUnaryRequest('/service/method', x => x, x => x, Buffer.from([]), (error, value) => { + assert(error); + assert.strictEqual(error?.code, grpc.status.UNAVAILABLE); + client.makeUnaryRequest('/service/method', x => x, x => x, Buffer.from([]), (error, value) => { + assert(error); + assert.strictEqual(error?.code, grpc.status.UNAVAILABLE); + done(); + }); + }); + }); +}); + +describe('Client with a nonexistent target domain', () => { + let client: Client; + before(() => { + // DNS name that does not exist per RFC 6761 section 6.4 + client = new Client('host.invalid', clientInsecureCreds); + }); + after(() => { + client.close(); + }); + it('should fail multiple calls', function(done) { + this.timeout(5000); // Regression test for https://github.com/grpc/grpc-node/issues/1411 client.makeUnaryRequest('/service/method', x => x, x => x, Buffer.from([]), (error, value) => { assert(error); diff --git a/packages/grpc-js/test/test-deadline.ts b/packages/grpc-js/test/test-deadline.ts new file mode 100644 index 000000000..bb6b3ba9b --- /dev/null +++ b/packages/grpc-js/test/test-deadline.ts @@ -0,0 +1,90 @@ +/* + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as assert from 'assert'; + +import * as grpc from '../src'; +import { experimental } from '../src'; +import { ServerCredentials } from '../src'; +import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; +import { loadProtoFile } from './common'; +import ServiceConfig = experimental.ServiceConfig; + +const clientInsecureCreds = grpc.credentials.createInsecure(); +const serverInsecureCreds = ServerCredentials.createInsecure(); + +const TIMEOUT_SERVICE_CONFIG: ServiceConfig = { + loadBalancingConfig: [], + methodConfig: [{ + name: [ + {service: 'TestService'} + ], + timeout: { + seconds: 1, + nanos: 0 + } + }] +}; + +describe('Client with configured timeout', () => { + let server: grpc.Server; + let Client: ServiceClientConstructor; + let client: ServiceClient; + + before(done => { + Client = loadProtoFile(__dirname + '/fixtures/test_service.proto').TestService as ServiceClientConstructor; + server = new grpc.Server(); + server.addService(Client.service, { + unary: () => {}, + clientStream: () => {}, + serverStream: () => {}, + bidiStream: () => {} + }); + server.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { + if (error) { + done(error); + return; + } + server.start(); + client = new Client(`localhost:${port}`, grpc.credentials.createInsecure(), {'grpc.service_config': JSON.stringify(TIMEOUT_SERVICE_CONFIG)}); + done(); + }); + }); + + after(done => { + client.close(); + server.tryShutdown(done); + }); + + it('Should end calls without explicit deadline with DEADLINE_EXCEEDED', done => { + client.unary({}, (error: grpc.ServiceError, value: unknown) =>{ + assert(error); + assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED); + done(); + }); + }); + + it('Should end calls with a long explicit deadline with DEADLINE_EXCEEDED', done => { + const deadline = new Date(); + deadline.setSeconds(deadline.getSeconds() + 20); + client.unary({}, (error: grpc.ServiceError, value: unknown) =>{ + assert(error); + assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED); + done(); + }); + }); +}); \ No newline at end of file diff --git a/packages/grpc-js/test/test-global-subchannel-pool.ts b/packages/grpc-js/test/test-global-subchannel-pool.ts new file mode 100644 index 000000000..999a11bf7 --- /dev/null +++ b/packages/grpc-js/test/test-global-subchannel-pool.ts @@ -0,0 +1,130 @@ +/* + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as assert from 'assert'; +import * as path from 'path'; + +import * as grpc from '../src'; +import {sendUnaryData, Server, ServerCredentials, ServerUnaryCall, ServiceClientConstructor, ServiceError} from '../src'; + +import {loadProtoFile} from './common'; + +const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); +const echoService = + loadProtoFile(protoFile).EchoService as ServiceClientConstructor; + +describe('Global subchannel pool', () => { + let server: Server; + let serverPort: number; + + let client1: InstanceType; + let client2: InstanceType; + + let promises: Promise[]; + + before(done => { + server = new Server(); + server.addService(echoService.service, { + echo(call: ServerUnaryCall, callback: sendUnaryData) { + callback(null, call.request); + }, + }); + + server.bindAsync( + 'localhost:0', ServerCredentials.createInsecure(), (err, port) => { + assert.ifError(err); + serverPort = port; + server.start(); + done(); + }); + }); + + beforeEach(() => { + promises = []; + }) + + after(done => { + server.tryShutdown(done); + }); + + function callService(client: InstanceType) { + return new Promise((resolve) => { + const request = {value: 'test value', value2: 3}; + + client.echo(request, (error: ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, request); + resolve(); + }); + }) + } + + function connect() { + const grpcOptions = { + 'grpc.use_local_subchannel_pool': 0, + } + + client1 = new echoService( + `127.0.0.1:${serverPort}`, grpc.credentials.createInsecure(), + grpcOptions); + + client2 = new echoService( + `127.0.0.1:${serverPort}`, grpc.credentials.createInsecure(), + grpcOptions); + } + + /* This is a regression test for a bug where client1.close in the + * waitForReady callback would cause the subchannel to transition to IDLE + * even though client2 is also using it. */ + it('Should handle client.close calls in waitForReady', + done => { + connect(); + + promises.push(new Promise((resolve) => { + client1.waitForReady(Date.now() + 50, (error) => { + assert.ifError(error); + client1.close(); + resolve(); + }); + })) + + promises.push(new Promise((resolve) => { + client2.waitForReady(Date.now() + 50, (error) => { + assert.ifError(error); + resolve(); + }); + })) + + Promise.all(promises).then(() => {done()}); + }) + + it('Call the service', done => { + promises.push(callService(client2)); + + Promise.all(promises).then(() => { + done(); + }); + }) + + it('Should complete the client lifecycle without error', done => { + setTimeout(() => { + client1.close(); + client2.close(); + done() + }, 500); + }); +}); diff --git a/packages/grpc-js/test/test-local-subchannel-pool.ts b/packages/grpc-js/test/test-local-subchannel-pool.ts new file mode 100644 index 000000000..081b2d3dc --- /dev/null +++ b/packages/grpc-js/test/test-local-subchannel-pool.ts @@ -0,0 +1,73 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as assert from 'assert'; +import * as path from 'path'; +import * as grpc from '../src'; +import { sendUnaryData, Server, ServerCredentials, ServerUnaryCall, ServiceClientConstructor, ServiceError } from "../src"; +import { loadProtoFile } from './common'; + +const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); +const echoService = loadProtoFile(protoFile) + .EchoService as ServiceClientConstructor; + +describe('Local subchannel pool', () => { + let server: Server; + let serverPort: number; + + before(done => { + + server = new Server(); + server.addService(echoService.service, { + echo(call: ServerUnaryCall, callback: sendUnaryData) { + callback(null, call.request); + }, + }); + + server.bindAsync( + 'localhost:0', + ServerCredentials.createInsecure(), + (err, port) => { + assert.ifError(err); + serverPort = port; + server.start(); + done(); + } + ); + }); + + after(done => { + server.tryShutdown(done); + }); + + it('should complete the client lifecycle without error', done => { + const client = new echoService( + `localhost:${serverPort}`, + grpc.credentials.createInsecure(), + {'grpc.use_local_subchannel_pool': 1} + ); + client.echo( + { value: 'test value', value2: 3 }, + (error: ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + client.close(); + done(); + } + ); + }); +}); \ No newline at end of file diff --git a/packages/grpc-js/test/test-logging.ts b/packages/grpc-js/test/test-logging.ts index c1601cbc5..d275158cf 100644 --- a/packages/grpc-js/test/test-logging.ts +++ b/packages/grpc-js/test/test-logging.ts @@ -27,10 +27,6 @@ describe('Logging', () => { grpc.setLogVerbosity(grpc.logVerbosity.DEBUG); }); - it('logger defaults to console', () => { - assert.strictEqual(logging.getLogger(), console); - }); - it('sets the logger to a new value', () => { const logger: Partial = {}; diff --git a/packages/grpc-js/test/test-outlier-detection.ts b/packages/grpc-js/test/test-outlier-detection.ts new file mode 100644 index 000000000..d51ccf3fd --- /dev/null +++ b/packages/grpc-js/test/test-outlier-detection.ts @@ -0,0 +1,546 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as assert from 'assert'; +import * as path from 'path'; +import * as grpc from '../src'; +import { loadProtoFile } from './common'; +import { OutlierDetectionLoadBalancingConfig } from '../src/load-balancer-outlier-detection' +import { ServiceClient } from '../src/make-client'; + +function multiDone(done: Mocha.Done, target: number) { + let count = 0; + return (error?: any) => { + if (error) { + done(error); + } + count++; + if (count >= target) { + done(); + } + } +} + +const defaultOutlierDetectionServiceConfig = { + methodConfig: [], + loadBalancingConfig: [ + { + outlier_detection: { + success_rate_ejection: {}, + failure_percentage_ejection: {}, + child_policy: [{round_robin: {}}] + } + } + ] +}; + +const defaultOutlierDetectionServiceConfigString = JSON.stringify(defaultOutlierDetectionServiceConfig); + +const successRateOutlierDetectionServiceConfig = { + methodConfig: [], + loadBalancingConfig: [ + { + outlier_detection: { + interval: { + seconds: 1, + nanos: 0 + }, + base_ejection_time: { + seconds: 3, + nanos: 0 + }, + success_rate_ejection: { + request_volume: 5 + }, + child_policy: [{round_robin: {}}] + } + } + ] +}; + +const successRateOutlierDetectionServiceConfigString = JSON.stringify(successRateOutlierDetectionServiceConfig); + +const failurePercentageOutlierDetectionServiceConfig = { + methodConfig: [], + loadBalancingConfig: [ + { + outlier_detection: { + interval: { + seconds: 1, + nanos: 0 + }, + base_ejection_time: { + seconds: 3, + nanos: 0 + }, + failure_percentage_ejection: { + request_volume: 5 + }, + child_policy: [{round_robin: {}}] + } + } + ] +}; + +const falurePercentageOutlierDetectionServiceConfigString = JSON.stringify(failurePercentageOutlierDetectionServiceConfig); + +const goodService = { + echo: (call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData) => { + callback(null, call.request) + } +}; + +const badService = { + echo: (call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData) => { + callback({ + code: grpc.status.PERMISSION_DENIED, + details: 'Permission denied' + }) + } +} + +const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); +const EchoService = loadProtoFile(protoFile) + .EchoService as grpc.ServiceClientConstructor; + +describe('Outlier detection config validation', () => { + describe('interval', () => { + it('Should reject a negative interval', () => { + const loadBalancingConfig = { + interval: { + seconds: -1, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large interval', () => { + const loadBalancingConfig = { + interval: { + seconds: 1e12, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a negative interval.nanos', () => { + const loadBalancingConfig = { + interval: { + seconds: 0, + nanos: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large interval.nanos', () => { + const loadBalancingConfig = { + interval: { + seconds: 0, + nanos: 1e12 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /interval parse error: values out of range for non-negative Duaration/); + }); + }); + describe('base_ejection_time', () => { + it('Should reject a negative base_ejection_time', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: -1, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large base_ejection_time', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: 1e12, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a negative base_ejection_time.nanos', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: 0, + nanos: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large base_ejection_time.nanos', () => { + const loadBalancingConfig = { + base_ejection_time: { + seconds: 0, + nanos: 1e12 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /base_ejection_time parse error: values out of range for non-negative Duaration/); + }); + }); + describe('max_ejection_time', () => { + it('Should reject a negative max_ejection_time', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: -1, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large max_ejection_time', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: 1e12, + nanos: 0 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a negative max_ejection_time.nanos', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: 0, + nanos: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + it('Should reject a large max_ejection_time.nanos', () => { + const loadBalancingConfig = { + max_ejection_time: { + seconds: 0, + nanos: 1e12 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_time parse error: values out of range for non-negative Duaration/); + }); + }); + describe('max_ejection_percent', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + max_ejection_percent: 101, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_percent parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + max_ejection_percent: -1, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /max_ejection_percent parse error: value out of range for percentage/); + }); + }); + describe('success_rate_ejection.enforcement_percentage', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + success_rate_ejection: { + enforcement_percentage: 101 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /success_rate_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + success_rate_ejection: { + enforcement_percentage: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /success_rate_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + }); + describe('failure_percentage_ejection.threshold', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + threshold: 101 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.threshold parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + threshold: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.threshold parse error: value out of range for percentage/); + }); + }); + describe('failure_percentage_ejection.enforcement_percentage', () => { + it('Should reject a value above 100', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + enforcement_percentage: 101 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + it('Should reject a negative value', () => { + const loadBalancingConfig = { + failure_percentage_ejection: { + enforcement_percentage: -1 + }, + child_policy: [{round_robin: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /failure_percentage_ejection\.enforcement_percentage parse error: value out of range for percentage/); + }); + }); + describe('child_policy', () => { + it('Should reject a pick_first child_policy', () => { + const loadBalancingConfig = { + child_policy: [{pick_first: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /outlier_detection LB policy cannot have a pick_first child policy/); + }); + }); +}); + +describe('Outlier detection', () => { + const GOOD_PORTS = 4; + let goodServer: grpc.Server; + let badServer: grpc.Server; + const goodPorts: number[] = []; + let badPort: number; + before(done => { + const eachDone = multiDone(() => { + goodServer.start(); + badServer.start(); + done(); + }, GOOD_PORTS + 1); + goodServer = new grpc.Server(); + goodServer.addService(EchoService.service, goodService); + for (let i = 0; i < GOOD_PORTS; i++) { + goodServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { + if (error) { + eachDone(error); + return; + } + goodPorts.push(port); + eachDone(); + }); + } + badServer = new grpc.Server(); + badServer.addService(EchoService.service, badService); + badServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { + if (error) { + eachDone(error); + return; + } + badPort = port; + eachDone(); + }); + }); + after(() => { + goodServer.forceShutdown(); + badServer.forceShutdown(); + }); + + function makeManyRequests(makeOneRequest: (callback: (error?: Error) => void) => void, total: number, callback: (error?: Error) => void) { + if (total === 0) { + callback(); + return; + } + makeOneRequest(error => { + if (error) { + callback(error); + return; + } + makeManyRequests(makeOneRequest, total - 1, callback); + }); + } + + it('Should allow normal operation with one server', done => { + const client = new EchoService(`localhost:${goodPorts[0]}`, grpc.credentials.createInsecure(), {'grpc.service_config': defaultOutlierDetectionServiceConfigString}); + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + done(); + } + ); + }); + describe('Success rate', () => { + let makeCheckedRequest: (callback: () => void) => void; + let makeUncheckedRequest:(callback: (error?: Error) => void) => void; + before(() => { + const target = 'ipv4:///' + goodPorts.map(port => `127.0.0.1:${port}`).join(',') + `,127.0.0.1:${badPort}`; + const client = new EchoService(target, grpc.credentials.createInsecure(), {'grpc.service_config': successRateOutlierDetectionServiceConfigString}); + makeUncheckedRequest = (callback: () => void) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + callback(); + } + ); + }; + makeCheckedRequest = (callback: (error?: Error) => void) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + callback(error); + } + ); + }; + }); + it('Should eject a server if it is failing requests', done => { + // Make a large volume of requests + makeManyRequests(makeUncheckedRequest, 50, () => { + // Give outlier detection time to run ejection checks + setTimeout(() => { + // Make enough requests to go around all servers + makeManyRequests(makeCheckedRequest, 10, done); + }, 1000); + }); + }); + it('Should uneject a server after the ejection period', function(done) { + this.timeout(5000); + makeManyRequests(makeUncheckedRequest, 50, () => { + setTimeout(() => { + makeManyRequests(makeCheckedRequest, 10, error => { + if (error) { + done(error); + return; + } + setTimeout(() => { + makeManyRequests(makeCheckedRequest, 10, error => { + assert(error); + done(); + }); + }, 3000); + }); + }, 1000); + }) + }); + }); + describe('Failure percentage', () => { + let makeCheckedRequest: (callback: () => void) => void; + let makeUncheckedRequest:(callback: (error?: Error) => void) => void; + before(() => { + const target = 'ipv4:///' + goodPorts.map(port => `127.0.0.1:${port}`).join(',') + `,127.0.0.1:${badPort}`; + const client = new EchoService(target, grpc.credentials.createInsecure(), {'grpc.service_config': falurePercentageOutlierDetectionServiceConfigString}); + makeUncheckedRequest = (callback: () => void) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + callback(); + } + ); + }; + makeCheckedRequest = (callback: (error?: Error) => void) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + callback(error); + } + ); + }; + }); + it('Should eject a server if it is failing requests', done => { + // Make a large volume of requests + makeManyRequests(makeUncheckedRequest, 50, () => { + // Give outlier detection time to run ejection checks + setTimeout(() => { + // Make enough requests to go around all servers + makeManyRequests(makeCheckedRequest, 10, done); + }, 1000); + }); + }); + it('Should uneject a server after the ejection period', function(done) { + this.timeout(5000); + makeManyRequests(makeUncheckedRequest, 50, () => { + setTimeout(() => { + makeManyRequests(makeCheckedRequest, 10, error => { + if (error) { + done(error); + return; + } + setTimeout(() => { + makeManyRequests(makeCheckedRequest, 10, error => { + assert(error); + done(); + }); + }, 3000); + }); + }, 1000); + }) + }); + }); +}); diff --git a/packages/grpc-js/test/test-resolver.ts b/packages/grpc-js/test/test-resolver.ts index 756d234ca..1d458125b 100644 --- a/packages/grpc-js/test/test-resolver.ts +++ b/packages/grpc-js/test/test-resolver.ts @@ -19,18 +19,23 @@ // tslint:disable no-any import * as assert from 'assert'; import * as resolverManager from '../src/resolver'; +import * as resolver_dns from '../src/resolver-dns'; +import * as resolver_uds from '../src/resolver-uds'; +import * as resolver_ip from '../src/resolver-ip'; import { ServiceConfig } from '../src/service-config'; -import { StatusObject } from '../src/call-stream'; -import { SubchannelAddress, isTcpSubchannelAddress } from '../src/subchannel'; +import { StatusObject } from '../src/call-interface'; +import { SubchannelAddress, isTcpSubchannelAddress, subchannelAddressToString } from "../src/subchannel-address"; import { parseUri, GrpcUri } from '../src/uri-parser'; describe('Name Resolver', () => { + before(() => { + resolver_dns.setup(); + resolver_uds.setup(); + resolver_ip.setup(); + }); describe('DNS Names', function() { // For some reason DNS queries sometimes take a long time on Windows this.timeout(4000); - before(() => { - resolverManager.registerAll(); - }); it('Should resolve localhost properly', done => { const target = resolverManager.mapUriDefaultScheme(parseUri('localhost:50051')!)!; const listener: resolverManager.ResolverListener = { @@ -202,7 +207,73 @@ describe('Name Resolver', () => { const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); - it('Should resolve a name with multiple dots', done => { + // Created DNS TXT record using TXT sample from https://github.com/grpc/proposal/blob/master/A2-service-configs-in-dns.md + // "grpc_config=[{\"serviceConfig\":{\"loadBalancingPolicy\":\"round_robin\",\"methodConfig\":[{\"name\":[{\"service\":\"MyService\",\"method\":\"Foo\"}],\"waitForReady\":true}]}}]" + it.skip('Should resolve a name with TXT service config', done => { + const target = resolverManager.mapUriDefaultScheme(parseUri('grpctest.kleinsch.com')!)!; + const listener: resolverManager.ResolverListener = { + onSuccessfulResolution: ( + addressList: SubchannelAddress[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + if (serviceConfig !== null) { + assert( + serviceConfig.loadBalancingPolicy === 'round_robin', + 'Should have found round robin LB policy' + ); + done(); + } + }, + onError: (error: StatusObject) => { + done(new Error(`Failed with status ${error.details}`)); + }, + }; + const resolver = resolverManager.createResolver(target, listener, {}); + resolver.updateResolution(); + }); + it.skip( + 'Should not resolve TXT service config if we disabled service config', + (done) => { + const target = resolverManager.mapUriDefaultScheme( + parseUri('grpctest.kleinsch.com')! + )!; + let count = 0; + const listener: resolverManager.ResolverListener = { + onSuccessfulResolution: ( + addressList: SubchannelAddress[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert( + serviceConfig === null, + 'Should not have found service config' + ); + count++; + }, + onError: (error: StatusObject) => { + done(new Error(`Failed with status ${error.details}`)); + }, + }; + const resolver = resolverManager.createResolver(target, listener, { + 'grpc.service_config_disable_resolution': 1, + }); + resolver.updateResolution(); + setTimeout(() => { + assert(count === 1, 'Should have only resolved once'); + done(); + }, 2_000); + } + ); + /* The DNS entry for loopback4.unittest.grpc.io only has a single A record + * with the address 127.0.0.1, but the Mac DNS resolver appears to use + * NAT64 to create an IPv6 address in that case, so it instead returns + * 64:ff9b::7f00:1. Handling that kind of translation is outside of the + * scope of this test, so we are skipping it. The test primarily exists + * as a regression test for https://github.com/grpc/grpc-node/issues/1044, + * and the test 'Should resolve gRPC interop servers' tests the same thing. + */ + it.skip('Should resolve a name with multiple dots', done => { const target = resolverManager.mapUriDefaultScheme(parseUri('loopback4.unittest.grpc.io')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( @@ -218,7 +289,7 @@ describe('Name Resolver', () => { isTcpSubchannelAddress(addr) && addr.host === '127.0.0.1' && addr.port === 443 - ) + ), `None of [${addressList.map(addr => subchannelAddressToString(addr))}] matched '127.0.0.1:443'` ); done(); }, @@ -258,7 +329,10 @@ describe('Name Resolver', () => { const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); - it('Should resolve a DNS name to IPv4 and IPv6 addresses', done => { + /* This DNS name resolves to only the IPv4 address on Windows, and only the + * IPv6 address on Mac. There is no result that we can consistently test + * for here. */ + it.skip('Should resolve a DNS name to IPv4 and IPv6 addresses', done => { const target = resolverManager.mapUriDefaultScheme(parseUri('loopback46.unittest.grpc.io')!)!; const listener: resolverManager.ResolverListener = { onSuccessfulResolution: ( @@ -274,7 +348,7 @@ describe('Name Resolver', () => { isTcpSubchannelAddress(addr) && addr.host === '127.0.0.1' && addr.port === 443 - ) + ), `None of [${addressList.map(addr => subchannelAddressToString(addr))}] matched '127.0.0.1:443'` ); /* TODO(murgatroid99): check for IPv6 result, once we can get that * consistently */ @@ -309,6 +383,10 @@ describe('Name Resolver', () => { const resolver = resolverManager.createResolver(target, listener, {}); resolver.updateResolution(); }); + /* This test also serves as a regression test for + * https://github.com/grpc/grpc-node/issues/1044, specifically handling + * hyphens and multiple periods in a DNS name. It should not be skipped + * unless there is another test for the same issue. */ it('Should resolve gRPC interop servers', done => { let completeCount = 0; const target1 = resolverManager.mapUriDefaultScheme(parseUri('grpc-test.sandbox.googleapis.com')!)!; @@ -336,6 +414,70 @@ describe('Name Resolver', () => { const resolver2 = resolverManager.createResolver(target2, listener, {}); resolver2.updateResolution(); }); + it('should not keep repeating successful resolutions', done => { + const target = resolverManager.mapUriDefaultScheme(parseUri('localhost')!)!; + let resultCount = 0; + const resolver = resolverManager.createResolver(target, { + onSuccessfulResolution: ( + addressList: SubchannelAddress[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert( + addressList.some( + addr => + isTcpSubchannelAddress(addr) && + addr.host === '127.0.0.1' && + addr.port === 443 + ) + ); + assert( + addressList.some( + addr => + isTcpSubchannelAddress(addr) && + addr.host === '::1' && + addr.port === 443 + ) + ); + resultCount += 1; + if (resultCount === 1) { + process.nextTick(() => resolver.updateResolution()); + } + }, + onError: (error: StatusObject) => { + assert.ifError(error); + }, + }, {'grpc.dns_min_time_between_resolutions_ms': 2000}); + resolver.updateResolution(); + setTimeout(() => { + assert.strictEqual(resultCount, 2, `resultCount ${resultCount} !== 2`); + done(); + }, 10_000); + }).timeout(15_000); + it('should not keep repeating failed resolutions', done => { + const target = resolverManager.mapUriDefaultScheme(parseUri('host.invalid')!)!; + let resultCount = 0; + const resolver = resolverManager.createResolver(target, { + onSuccessfulResolution: ( + addressList: SubchannelAddress[], + serviceConfig: ServiceConfig | null, + serviceConfigError: StatusObject | null + ) => { + assert.fail('Resolution succeeded unexpectedly'); + }, + onError: (error: StatusObject) => { + resultCount += 1; + if (resultCount === 1) { + process.nextTick(() => resolver.updateResolution()); + } + }, + }, {}); + resolver.updateResolution(); + setTimeout(() => { + assert.strictEqual(resultCount, 2, `resultCount ${resultCount} !== 2`); + done(); + }, 10_000); + }).timeout(15_000); }); describe('UDS Names', () => { it('Should handle a relative Unix Domain Socket name', done => { diff --git a/packages/grpc-js/test/test-retry-config.ts b/packages/grpc-js/test/test-retry-config.ts new file mode 100644 index 000000000..e27f236e2 --- /dev/null +++ b/packages/grpc-js/test/test-retry-config.ts @@ -0,0 +1,292 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import assert = require("assert"); +import { validateServiceConfig } from "../src/service-config"; + +function createRetryServiceConfig(retryConfig: object): object { + return { + loadBalancingConfig: [], + methodConfig: [ + { + name: [{ + service: 'A', + method: 'B' + }], + + retryPolicy: retryConfig + } + ] + }; +} + +function createHedgingServiceConfig(hedgingConfig: object): object { + return { + loadBalancingConfig: [], + methodConfig: [ + { + name: [{ + service: 'A', + method: 'B' + }], + + hedgingPolicy: hedgingConfig + } + ] + }; +} + +function createThrottlingServiceConfig(retryThrottling: object): object { + return { + loadBalancingConfig: [], + methodConfig: [], + retryThrottling: retryThrottling + }; +} + +interface TestCase { + description: string; + config: object; + error: RegExp; +} + +const validRetryConfig = { + maxAttempts: 2, + initialBackoff: '1s', + maxBackoff: '1s', + backoffMultiplier: 1, + retryableStatusCodes: [14, 'RESOURCE_EXHAUSTED'] +}; + +const RETRY_TEST_CASES: TestCase[] = [ + { + description: 'omitted maxAttempts', + config: { + initialBackoff: '1s', + maxBackoff: '1s', + backoffMultiplier: 1, + retryableStatusCodes: [14] + }, + error: /retry policy: maxAttempts must be an integer at least 2/ + }, + { + description: 'a low maxAttempts', + config: {...validRetryConfig, maxAttempts: 1}, + error: /retry policy: maxAttempts must be an integer at least 2/ + }, + { + description: 'omitted initialBackoff', + config: { + maxAttempts: 2, + maxBackoff: '1s', + backoffMultiplier: 1, + retryableStatusCodes: [14] + }, + error: /retry policy: initialBackoff must be a string consisting of a positive integer followed by s/ + }, + { + description: 'a non-numeric initialBackoff', + config: {...validRetryConfig, initialBackoff: 'abcs'}, + error: /retry policy: initialBackoff must be a string consisting of a positive integer followed by s/ + }, + { + description: 'an initialBackoff without an s', + config: {...validRetryConfig, initialBackoff: '123'}, + error: /retry policy: initialBackoff must be a string consisting of a positive integer followed by s/ + }, + { + description: 'omitted maxBackoff', + config: { + maxAttempts: 2, + initialBackoff: '1s', + backoffMultiplier: 1, + retryableStatusCodes: [14] + }, + error: /retry policy: maxBackoff must be a string consisting of a positive integer followed by s/ + }, + { + description: 'a non-numeric maxBackoff', + config: {...validRetryConfig, maxBackoff: 'abcs'}, + error: /retry policy: maxBackoff must be a string consisting of a positive integer followed by s/ + }, + { + description: 'an maxBackoff without an s', + config: {...validRetryConfig, maxBackoff: '123'}, + error: /retry policy: maxBackoff must be a string consisting of a positive integer followed by s/ + }, + { + description: 'omitted backoffMultiplier', + config: { + maxAttempts: 2, + initialBackoff: '1s', + maxBackoff: '1s', + retryableStatusCodes: [14] + }, + error: /retry policy: backoffMultiplier must be a number greater than 0/ + }, + { + description: 'a negative backoffMultiplier', + config: {...validRetryConfig, backoffMultiplier: -1}, + error: /retry policy: backoffMultiplier must be a number greater than 0/ + }, + { + description: 'omitted retryableStatusCodes', + config: { + maxAttempts: 2, + initialBackoff: '1s', + maxBackoff: '1s', + backoffMultiplier: 1 + }, + error: /retry policy: retryableStatusCodes is required/ + }, + { + description: 'empty retryableStatusCodes', + config: {...validRetryConfig, retryableStatusCodes: []}, + error: /retry policy: retryableStatusCodes must be non-empty/ + }, + { + description: 'unknown status code name', + config: {...validRetryConfig, retryableStatusCodes: ['abcd']}, + error: /retry policy: retryableStatusCodes value not a status code name/ + }, + { + description: 'out of range status code number', + config: {...validRetryConfig, retryableStatusCodes: [12345]}, + error: /retry policy: retryableStatusCodes value not in status code range/ + } +]; + +const validHedgingConfig = { + maxAttempts: 2 +}; + +const HEDGING_TEST_CASES: TestCase[] = [ + { + description: 'omitted maxAttempts', + config: {}, + error: /hedging policy: maxAttempts must be an integer at least 2/ + }, + { + description: 'a low maxAttempts', + config: {...validHedgingConfig, maxAttempts: 1}, + error: /hedging policy: maxAttempts must be an integer at least 2/ + }, + { + description: 'a non-numeric hedgingDelay', + config: {...validHedgingConfig, hedgingDelay: 'abcs'}, + error: /hedging policy: hedgingDelay must be a string consisting of a positive integer followed by s/ + }, + { + description: 'a hedgingDelay without an s', + config: {...validHedgingConfig, hedgingDelay: '123'}, + error: /hedging policy: hedgingDelay must be a string consisting of a positive integer followed by s/ + }, + { + description: 'unknown status code name', + config: {...validHedgingConfig, nonFatalStatusCodes: ['abcd']}, + error: /hedging policy: nonFatalStatusCodes value not a status code name/ + }, + { + description: 'out of range status code number', + config: {...validHedgingConfig, nonFatalStatusCodes: [12345]}, + error: /hedging policy: nonFatalStatusCodes value not in status code range/ + } +]; + +const validThrottlingConfig = { + maxTokens: 100, + tokenRatio: 0.1 +}; + +const THROTTLING_TEST_CASES: TestCase[] = [ + { + description: 'omitted maxTokens', + config: {tokenRatio: 0.1}, + error: /retryThrottling: maxTokens must be a number in \(0, 1000\]/ + }, + { + description: 'a large maxTokens', + config: {...validThrottlingConfig, maxTokens: 1001}, + error: /retryThrottling: maxTokens must be a number in \(0, 1000\]/ + }, + { + description: 'zero maxTokens', + config: {...validThrottlingConfig, maxTokens: 0}, + error: /retryThrottling: maxTokens must be a number in \(0, 1000\]/ + }, + { + description: 'omitted tokenRatio', + config: {maxTokens: 100}, + error: /retryThrottling: tokenRatio must be a number greater than 0/ + }, + { + description: 'zero tokenRatio', + config: {...validThrottlingConfig, tokenRatio: 0}, + error: /retryThrottling: tokenRatio must be a number greater than 0/ + } +]; + +describe('Retry configs', () => { + describe('Retry', () => { + it('Should accept a valid config', () => { + assert.doesNotThrow(() => { + validateServiceConfig(createRetryServiceConfig(validRetryConfig)); + }); + }); + for (const testCase of RETRY_TEST_CASES) { + it(`Should reject ${testCase.description}`, () => { + assert.throws(() => { + validateServiceConfig(createRetryServiceConfig(testCase.config)); + }, testCase.error); + }); + } + }); + describe('Hedging', () => { + it('Should accept valid configs', () => { + assert.doesNotThrow(() => { + validateServiceConfig(createHedgingServiceConfig(validHedgingConfig)); + }); + assert.doesNotThrow(() => { + validateServiceConfig(createHedgingServiceConfig({...validHedgingConfig, hedgingDelay: '1s'})); + }); + assert.doesNotThrow(() => { + validateServiceConfig(createHedgingServiceConfig({...validHedgingConfig, nonFatalStatusCodes: [14, 'RESOURCE_EXHAUSTED']})); + }); + }); + for (const testCase of HEDGING_TEST_CASES) { + it(`Should reject ${testCase.description}`, () => { + assert.throws(() => { + validateServiceConfig(createHedgingServiceConfig(testCase.config)); + }, testCase.error); + }); + } + }); + describe('Throttling', () => { + it('Should accept a valid config', () => { + assert.doesNotThrow(() => { + validateServiceConfig(createThrottlingServiceConfig(validThrottlingConfig)); + }); + }); + for (const testCase of THROTTLING_TEST_CASES) { + it(`Should reject ${testCase.description}`, () => { + assert.throws(() => { + validateServiceConfig(createThrottlingServiceConfig(testCase.config)); + }, testCase.error); + }); + } + }); +}); \ No newline at end of file diff --git a/packages/grpc-js/test/test-retry.ts b/packages/grpc-js/test/test-retry.ts new file mode 100644 index 000000000..66c0f7941 --- /dev/null +++ b/packages/grpc-js/test/test-retry.ts @@ -0,0 +1,364 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import * as assert from 'assert'; +import * as path from 'path'; +import * as grpc from '../src'; +import { loadProtoFile } from './common'; + +const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); +const EchoService = loadProtoFile(protoFile) + .EchoService as grpc.ServiceClientConstructor; + +const serviceImpl = { + echo: (call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData) => { + const succeedOnRetryAttempt = call.metadata.get('succeed-on-retry-attempt'); + const previousAttempts = call.metadata.get('grpc-previous-rpc-attempts'); + if (succeedOnRetryAttempt.length === 0 || (previousAttempts.length > 0 && previousAttempts[0] === succeedOnRetryAttempt[0])) { + callback(null, call.request); + } else { + const statusCode = call.metadata.get('respond-with-status'); + const code = statusCode[0] ? Number.parseInt(statusCode[0] as string) : grpc.status.UNKNOWN; + callback({ + code: code, + details: `Failed on retry ${previousAttempts[0] ?? 0}` + }); + } + } +} + +describe('Retries', () => { + let server: grpc.Server; + let port: number; + before((done) => { + server = new grpc.Server(); + server.addService(EchoService.service, serviceImpl); + server.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, portNumber) => { + if (error) { + done(error); + return; + } + port = portNumber; + server.start(); + done(); + }); + }); + + after(() => { + server.forceShutdown(); + }); + + describe('Client with retries disabled', () => { + let client: InstanceType; + before(() => { + client = new EchoService(`localhost:${port}`, grpc.credentials.createInsecure(), {'grpc.enable_retries': 0}); + }); + + after(() =>{ + client.close(); + }); + + it('Should be able to make a basic request', (done) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + done(); + } + ); + }); + + it('Should fail if the server fails the first request', (done) =>{ + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '1'); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert.strictEqual(error.details, 'Failed on retry 0'); + done(); + } + ); + }); + }); + + describe('Client with retries enabled but not configured', () => { + let client: InstanceType; + before(() => { + client = new EchoService(`localhost:${port}`, grpc.credentials.createInsecure()); + }); + + after(() =>{ + client.close(); + }); + + it('Should be able to make a basic request', (done) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + done(); + } + ); + }); + + it('Should fail if the server fails the first request', (done) =>{ + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '1'); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert.strictEqual(error.details, 'Failed on retry 0'); + done(); + } + ); + }); + }); + + describe('Client with retries configured', () => { + let client: InstanceType; + before(() => { + const serviceConfig = { + loadBalancingConfig: [], + methodConfig: [ + { + name: [{ + service: 'EchoService' + }], + retryPolicy: { + maxAttempts: 3, + initialBackoff: '0.1s', + maxBackoff: '10s', + backoffMultiplier: 1.2, + retryableStatusCodes: [14, 'RESOURCE_EXHAUSTED'] + } + } + ] + } + client = new EchoService(`localhost:${port}`, grpc.credentials.createInsecure(), {'grpc.service_config': JSON.stringify(serviceConfig)}); + }); + + after(() =>{ + client.close(); + }); + + it('Should be able to make a basic request', (done) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + done(); + } + ); + }); + + it('Should succeed with few required attempts', (done) => { + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '2'); + metadata.set('respond-with-status', `${grpc.status.RESOURCE_EXHAUSTED}`); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + done(); + } + ); + }); + + it('Should fail with many required attempts', (done) => { + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '4'); + metadata.set('respond-with-status', `${grpc.status.RESOURCE_EXHAUSTED}`); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert.strictEqual(error.details, 'Failed on retry 2'); + done(); + } + ); + }); + + it('Should fail with a fatal status code', (done) => { + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '2'); + metadata.set('respond-with-status', `${grpc.status.NOT_FOUND}`); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert.strictEqual(error.details, 'Failed on retry 0'); + done(); + } + ); + }); + + it('Should not be able to make more than 5 attempts', (done) => { + const serviceConfig = { + loadBalancingConfig: [], + methodConfig: [ + { + name: [{ + service: 'EchoService' + }], + retryPolicy: { + maxAttempts: 10, + initialBackoff: '0.1s', + maxBackoff: '10s', + backoffMultiplier: 1.2, + retryableStatusCodes: [14, 'RESOURCE_EXHAUSTED'] + } + } + ] + } + const client2 = new EchoService(`localhost:${port}`, grpc.credentials.createInsecure(), {'grpc.service_config': JSON.stringify(serviceConfig)}); + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '6'); + metadata.set('respond-with-status', `${grpc.status.RESOURCE_EXHAUSTED}`); + client2.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert.strictEqual(error.details, 'Failed on retry 4'); + done(); + } + ); + }) + }); + + describe('Client with hedging configured', () => { + let client: InstanceType; + before(() => { + const serviceConfig = { + loadBalancingConfig: [], + methodConfig: [ + { + name: [{ + service: 'EchoService' + }], + hedgingPolicy: { + maxAttempts: 3, + nonFatalStatusCodes: [14, 'RESOURCE_EXHAUSTED'] + } + } + ] + } + client = new EchoService(`localhost:${port}`, grpc.credentials.createInsecure(), {'grpc.service_config': JSON.stringify(serviceConfig)}); + }); + + after(() =>{ + client.close(); + }); + + it('Should be able to make a basic request', (done) => { + client.echo( + { value: 'test value', value2: 3 }, + (error: grpc.ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + done(); + } + ); + }); + + it('Should succeed with few required attempts', (done) => { + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '2'); + metadata.set('respond-with-status', `${grpc.status.RESOURCE_EXHAUSTED}`); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert.ifError(error); + assert.deepStrictEqual(response, { value: 'test value', value2: 3 }); + done(); + } + ); + }); + + it('Should fail with many required attempts', (done) => { + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '4'); + metadata.set('respond-with-status', `${grpc.status.RESOURCE_EXHAUSTED}`); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert(error.details.startsWith('Failed on retry')); + done(); + } + ); + }); + + it('Should fail with a fatal status code', (done) => { + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '2'); + metadata.set('respond-with-status', `${grpc.status.NOT_FOUND}`); + client.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert(error.details.startsWith('Failed on retry')); + done(); + } + ); + }); + + it('Should not be able to make more than 5 attempts', (done) => { + const serviceConfig = { + loadBalancingConfig: [], + methodConfig: [ + { + name: [{ + service: 'EchoService' + }], + hedgingPolicy: { + maxAttempts: 10, + nonFatalStatusCodes: [14, 'RESOURCE_EXHAUSTED'] + } + } + ] + } + const client2 = new EchoService(`localhost:${port}`, grpc.credentials.createInsecure(), {'grpc.service_config': JSON.stringify(serviceConfig)}); + const metadata = new grpc.Metadata(); + metadata.set('succeed-on-retry-attempt', '6'); + metadata.set('respond-with-status', `${grpc.status.RESOURCE_EXHAUSTED}`); + client2.echo( + { value: 'test value', value2: 3 }, + metadata, + (error: grpc.ServiceError, response: any) => { + assert(error); + assert(error.details.startsWith('Failed on retry')); + done(); + } + ); + }) + }); +}); \ No newline at end of file diff --git a/packages/grpc-js/test/test-server.ts b/packages/grpc-js/test/test-server.ts index 58b102883..c67ebc4d6 100644 --- a/packages/grpc-js/test/test-server.ts +++ b/packages/grpc-js/test/test-server.ts @@ -21,14 +21,29 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as http2 from 'http2'; import * as path from 'path'; +import * as protoLoader from '@grpc/proto-loader'; import * as grpc from '../src'; import { Server, ServerCredentials } from '../src'; import { ServiceError } from '../src/call'; import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; -import { sendUnaryData, ServerUnaryCall } from '../src/server-call'; +import { sendUnaryData, ServerUnaryCall, ServerDuplexStream } from '../src/server-call'; + +import { assert2, loadProtoFile } from './common'; +import { TestServiceClient, TestServiceHandlers } from './generated/TestService'; +import { ProtoGrpcType as TestServiceGrpcType } from './generated/test_service'; +import { Request__Output } from './generated/Request'; +import { CompressionAlgorithms } from '../src/compression-algorithms'; + +const loadedTestServiceProto = protoLoader.loadSync(path.join(__dirname, 'fixtures/test_service.proto'), { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true +}); -import { loadProtoFile } from './common'; +const testServiceGrpcObject = grpc.loadPackageDefinition(loadedTestServiceProto) as unknown as TestServiceGrpcType; const ca = fs.readFileSync(path.join(__dirname, 'fixtures', 'ca.pem')); const key = fs.readFileSync(path.join(__dirname, 'fixtures', 'server1.key')); @@ -116,7 +131,11 @@ describe('Server', () => { assert.throws(() => { server.bindAsync('localhost:0', null as any, noop); - }, /creds must be an object/); + }, /creds must be a ServerCredentials object/); + + assert.throws(() => { + server.bindAsync('localhost:0', grpc.credentials.createInsecure() as any, noop); + }, /creds must be a ServerCredentials object/); assert.throws(() => { server.bindAsync( @@ -439,18 +458,28 @@ describe('Server', () => { describe('Echo service', () => { let server: Server; let client: ServiceClient; + const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); + const echoService = loadProtoFile(protoFile) + .EchoService as ServiceClientConstructor; + + const serviceImplementation = { + echo(call: ServerUnaryCall, callback: sendUnaryData) { + callback(null, call.request); + }, + echoBidiStream(call: ServerDuplexStream) { + call.on('data', data => { + call.write(data); + }); + call.on('end', () => { + call.end(); + }); + } + }; before(done => { - const protoFile = path.join(__dirname, 'fixtures', 'echo_service.proto'); - const echoService = loadProtoFile(protoFile) - .EchoService as ServiceClientConstructor; server = new Server(); - server.addService(echoService.service, { - echo(call: ServerUnaryCall, callback: sendUnaryData) { - callback(null, call.request); - }, - }); + server.addService(echoService.service, serviceImplementation); server.bindAsync( 'localhost:0', @@ -482,6 +511,43 @@ describe('Echo service', () => { } ); }); + + /* This test passes on Node 18 but fails on Node 16. The failure appears to + * be caused by https://github.com/nodejs/node/issues/42713 */ + it.skip('should continue a stream after server shutdown', done => { + const server2 = new Server(); + server2.addService(echoService.service, serviceImplementation); + server2.bindAsync('localhost:0', ServerCredentials.createInsecure(), (err, port) => { + if (err) { + done(err); + return; + } + const client2 = new echoService(`localhost:${port}`, grpc.credentials.createInsecure()); + server2.start(); + const stream = client2.echoBidiStream(); + const totalMessages = 5; + let messagesSent = 0; + stream.write({ value: 'test value', value2: messagesSent}); + messagesSent += 1; + stream.on('data', () => { + if (messagesSent === 1) { + server2.tryShutdown(assert2.mustCall(() => {})); + } + if (messagesSent >= totalMessages) { + stream.end(); + } else { + stream.write({ value: 'test value', value2: messagesSent}); + messagesSent += 1; + } + }); + stream.on('status', assert2.mustCall((status: grpc.StatusObject) => { + assert.strictEqual(status.code, grpc.status.OK); + assert.strictEqual(messagesSent, totalMessages); + })); + stream.on('error', () => {}); + assert2.afterMustCallsSatisfied(done); + }); + }); }); describe('Generic client and server', () => { @@ -600,3 +666,277 @@ describe('Generic client and server', () => { }); }); }); + +describe('Compressed requests', () => { + const testServiceHandlers: TestServiceHandlers = { + Unary(call, callback) { + callback(null, { count: 500000, message: call.request.message }); + }, + + ClientStream(call, callback) { + let timesCalled = 0; + + call.on('data', () => { + timesCalled += 1; + }); + + call.on('end', () => { + callback(null, { count: timesCalled }); + }); + }, + + ServerStream(call) { + const { metadata, request } = call; + + for (let i = 0; i < 5; i++) { + call.write({ count: request.message.length }); + } + + call.end(); + }, + + BidiStream(call) { + call.on('data', (data: Request__Output) => { + call.write({ count: data.message.length }); + }); + + call.on('end', () => { + call.end(); + }); + } + }; + + describe('Test service client and server with deflate', () => { + let client: TestServiceClient; + let server: Server; + let assignedPort: number; + + before(done => { + server = new Server(); + server.addService( + testServiceGrpcObject.TestService.service, + testServiceHandlers + ); + server.bindAsync( + 'localhost:0', + ServerCredentials.createInsecure(), + (err, port) => { + assert.ifError(err); + server.start(); + assignedPort = port; + client = new testServiceGrpcObject.TestService( + `localhost:${assignedPort}`, + grpc.credentials.createInsecure(), + { + 'grpc.default_compression_algorithm': CompressionAlgorithms.deflate + } + ); + done(); + } + ); + }); + + after(done => { + client.close(); + server.tryShutdown(done); + }); + + it('Should compress and decompress when performing unary call', done => { + client.unary({ message: 'foo' }, (err, response) => { + assert.ifError(err); + done(); + }); + }); + + it('Should compress and decompress when performing client stream', done => { + const clientStream = client.clientStream((err, res) => { + assert.ifError(err); + assert.equal(res?.count, 3); + done(); + }); + + clientStream.write({ message: 'foo' }, () => { + clientStream.write({ message: 'bar' }, () => { + clientStream.write({ message: 'baz' }, () => { + setTimeout(() => clientStream.end(), 10); + }); + }); + }); + }); + + it('Should compress and decompress when performing server stream', done => { + const serverStream = client.serverStream({ message: 'foobar' }); + let timesResponded = 0; + + serverStream.on('data', () => { + timesResponded += 1; + }); + + serverStream.on('error', (err) => { + assert.ifError(err); + done(); + }); + + serverStream.on('end', () => { + assert.equal(timesResponded, 5); + done(); + }); + }); + + it('Should compress and decompress when performing bidi stream', done => { + const bidiStream = client.bidiStream(); + let timesRequested = 0; + let timesResponded = 0; + + bidiStream.on('data', () => { + timesResponded += 1; + }); + + bidiStream.on('error', (err) => { + assert.ifError(err); + done(); + }); + + bidiStream.on('end', () => { + assert.equal(timesResponded, timesRequested); + done(); + }); + + bidiStream.write({ message: 'foo' }, () => { + timesRequested += 1; + bidiStream.write({ message: 'bar' }, () => { + timesRequested += 1; + bidiStream.write({ message: 'baz' }, () => { + timesRequested += 1; + setTimeout(() => bidiStream.end(), 10); + }) + }) + }); + }); + + it('Should compress and decompress with gzip', done => { + client = new testServiceGrpcObject.TestService( + `localhost:${assignedPort}`, + grpc.credentials.createInsecure(), + { + 'grpc.default_compression_algorithm': CompressionAlgorithms.gzip + } + ); + + client.unary({ message: 'foo' }, (err, response) => { + assert.ifError(err); + done(); + }); + }); + + it('Should compress and decompress when performing client stream', done => { + const clientStream = client.clientStream((err, res) => { + assert.ifError(err); + assert.equal(res?.count, 3); + done(); + }); + + clientStream.write({ message: 'foo' }, () => { + clientStream.write({ message: 'bar' }, () => { + clientStream.write({ message: 'baz' }, () => { + setTimeout(() => clientStream.end(), 10); + }); + }); + }); + }); + + it('Should compress and decompress when performing server stream', done => { + const serverStream = client.serverStream({ message: 'foobar' }); + let timesResponded = 0; + + serverStream.on('data', () => { + timesResponded += 1; + }); + + serverStream.on('error', (err) => { + assert.ifError(err); + done(); + }); + + serverStream.on('end', () => { + assert.equal(timesResponded, 5); + done(); + }); + }); + + it('Should compress and decompress when performing bidi stream', done => { + const bidiStream = client.bidiStream(); + let timesRequested = 0; + let timesResponded = 0; + + bidiStream.on('data', () => { + timesResponded += 1; + }); + + bidiStream.on('error', (err) => { + assert.ifError(err); + done(); + }); + + bidiStream.on('end', () => { + assert.equal(timesResponded, timesRequested); + done(); + }); + + bidiStream.write({ message: 'foo' }, () => { + timesRequested += 1; + bidiStream.write({ message: 'bar' }, () => { + timesRequested += 1; + bidiStream.write({ message: 'baz' }, () => { + timesRequested += 1; + setTimeout(() => bidiStream.end(), 10); + }) + }) + }); + }); + + it('Should handle large messages', done => { + let longMessage = ''; + for (let i = 0; i < 400000; i++) { + const letter = 'abcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 26)]; + longMessage = longMessage + letter.repeat(10); + } + + client.unary({message: longMessage}, (err, response) => { + assert.ifError(err); + assert.strictEqual(response?.message, longMessage); + done(); + }) + }) + + /* As of Node 16, Writable and Duplex streams validate the encoding + * argument to write, and the flags values we are passing there are not + * valid. We don't currently have an alternative way to pass that flag + * down, so for now this feature is not supported. */ + it.skip('Should not compress requests when the NoCompress write flag is used', done => { + const bidiStream = client.bidiStream(); + let timesRequested = 0; + let timesResponded = 0; + + bidiStream.on('data', () => { + timesResponded += 1; + }); + + bidiStream.on('error', (err) => { + assert.ifError(err); + done(); + }); + + bidiStream.on('end', () => { + assert.equal(timesResponded, timesRequested); + done(); + }); + + bidiStream.write({ message: 'foo' }, '2', (err: any) => { + assert.ifError(err); + timesRequested += 1; + setTimeout(() => bidiStream.end(), 10); + }); + }); + }); +}); diff --git a/packages/grpc-js/tsconfig.json b/packages/grpc-js/tsconfig.json index ba675db78..310b633c7 100644 --- a/packages/grpc-js/tsconfig.json +++ b/packages/grpc-js/tsconfig.json @@ -6,7 +6,8 @@ "target": "es2017", "module": "commonjs", "resolveJsonModule": true, - "incremental": true + "incremental": true, + "types": ["mocha"] }, "include": [ "src/**/*.ts", diff --git a/packages/grpc-tools/CMakeLists.txt b/packages/grpc-tools/CMakeLists.txt index 9d6690ba7..60dcdb675 100644 --- a/packages/grpc-tools/CMakeLists.txt +++ b/packages/grpc-tools/CMakeLists.txt @@ -1,17 +1,22 @@ -cmake_minimum_required(VERSION 3.6) +cmake_minimum_required(VERSION 3.7) +set(CMAKE_OSX_DEPLOYMENT_TARGET "11.7" CACHE STRING "Minimum OS X deployment version" FORCE) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) +# MSVC runtime library flags are selected by an abstraction. +if(COMMAND cmake_policy AND POLICY CMP0091) + cmake_policy(SET CMP0091 NEW) +endif() + set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -set(PROTOBUF_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/protobuf) -add_subdirectory(${PROTOBUF_ROOT_DIR}/cmake deps/protobuf) - set(protobuf_BUILD_TESTS OFF CACHE BOOL "Build protobuf tests") set(protobuf_WITH_ZLIB OFF CACHE BOOL "Build protobuf with zlib.") +set(PROTOBUF_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/protobuf) +add_subdirectory(${PROTOBUF_ROOT_DIR}/cmake deps/protobuf) set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-stack-protector") @@ -22,8 +27,21 @@ add_executable(grpc_node_plugin ) if (MSVC) - add_definitions(/MTd) -endif (MSVC) + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.15) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>) + else () + foreach (flag_var + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if (${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif (${flag_var} MATCHES "/MD") + endforeach (flag_var) + endif () +endif (MVC) target_include_directories(grpc_node_plugin PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} @@ -34,4 +52,4 @@ target_include_directories(grpc_node_plugin target_link_libraries(grpc_node_plugin libprotoc libprotobuf -) \ No newline at end of file +) diff --git a/packages/grpc-tools/build_binaries.sh b/packages/grpc-tools/build_binaries.sh index b26946afa..d22bbc4ff 100755 --- a/packages/grpc-tools/build_binaries.sh +++ b/packages/grpc-tools/build_binaries.sh @@ -27,38 +27,52 @@ tools_version=$(jq '.version' < package.json | tr -d '"') out_dir=$base/../../artifacts/grpc-tools/v$tools_version mkdir -p "$out_dir" -case $(uname -s) in - Linux) - platform=linux - arch_list=( ia32 x64 ) - ;; - Darwin) - platform=darwin - arch_list=( x64 ) - ;; -esac +build () { + cmake_flag=$* -for arch in "${arch_list[@]}"; do - case $arch in - ia32) - toolchain_flag=-DCMAKE_TOOLCHAIN_FILE=linux_32bit.toolchain.cmake - ;; - *) - toolchain_flag=-DCMAKE_TOOLCHAIN_FILE=linux_64bit.toolchain.cmake - ;; - esac - rm -f $base/build/bin/protoc - rm -f $base/build/bin/grpc_node_plugin + rm -rf $base/build/bin rm -f $base/CMakeCache.txt rm -rf $base/CMakeFiles rm -f $protobuf_base/CMakeCache.txt rm -rf $protobuf_base/CMakeFiles - cmake $toolchain_flag . && cmake --build . --target clean && cmake --build . -- -j 12 - mkdir -p "$base/build/bin" + cmake $cmake_flag . && cmake --build . --target clean && cmake --build . -- -j 12 + mkdir -p $base/build/bin cp -L $protobuf_base/protoc $base/build/bin/protoc cp $base/grpc_node_plugin $base/build/bin/ file $base/build/bin/* - cd $base/build - tar -czf "$out_dir/$platform-$arch.tar.gz" bin/ - cd $base -done \ No newline at end of file +} + +artifacts() { + platform=$1 + arch=$2 + dir=$3 + case $(uname -s) in + Linux) + tar -czf $out_dir/$platform-$arch.tar.gz -C $(dirname $dir) $(basename $dir) + ;; + Darwin) + tar --format=gnutar -czf $out_dir/$platform-$arch.tar.gz -C $(dirname $dir) $(basename $dir) + ;; + esac +} + +case $(uname -s) in + Linux) + build -DCMAKE_TOOLCHAIN_FILE=linux_32bit.toolchain.cmake + artifacts linux ia32 $base/build/bin + build -DCMAKE_TOOLCHAIN_FILE=linux_64bit.toolchain.cmake + artifacts linux x64 $base/build/bin + ;; + Darwin) + build -DCMAKE_TOOLCHAIN_FILE=linux_64bit.toolchain.cmake -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" + + for arch in "x64" "arm64"; do + mkdir $base/build/bin/$arch + for bin in protoc grpc_node_plugin; do + lipo -extract x86_64 $base/build/bin/$bin -o $base/build/bin/$arch/$bin + otool -l $base/build/bin/$arch/$bin | grep minos + done + artifacts darwin $arch $base/build/bin/$arch/ + done + ;; +esac diff --git a/packages/grpc-tools/deps/protobuf b/packages/grpc-tools/deps/protobuf index 6aa539bf0..7c40b2df1 160000 --- a/packages/grpc-tools/deps/protobuf +++ b/packages/grpc-tools/deps/protobuf @@ -1 +1 @@ -Subproject commit 6aa539bf0195f188ff86efe6fb8bfa2b676cdd46 +Subproject commit 7c40b2df1fdf6f414c1c18c789715a9c948a0725 diff --git a/packages/grpc-tools/package.json b/packages/grpc-tools/package.json index b1f83ce45..d4ac74ea1 100644 --- a/packages/grpc-tools/package.json +++ b/packages/grpc-tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "1.11.1", + "version": "1.12.3", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "https://grpc.io/", @@ -24,7 +24,7 @@ "prepublishOnly": "git submodule update --init --recursive && node copy_well_known_protos.js" }, "dependencies": { - "node-pre-gyp": "^0.15.0" + "@mapbox/node-pre-gyp": "^1.0.5" }, "binary": { "module_name": "grpc_tools", diff --git a/packages/proto-loader/README.md b/packages/proto-loader/README.md index 123fad111..2a7af61e3 100644 --- a/packages/proto-loader/README.md +++ b/packages/proto-loader/README.md @@ -88,6 +88,16 @@ Options: -O, --outDir Directory in which to output files [string] [required] --grpcLib The gRPC implementation library that these types will be used with [string] [required] + --inputTemplate Template for mapping input or "permissive" type names + [string] [default: "%s"] + --outputTemplate Template for mapping output or "restricted" type names + [string] [default: "%s__Output"] + --inputBranded Output property for branded type for "permissive" + types with fullName of the Message as its value + [boolean] [default: false] + --outputBranded Output property for branded type for "restricted" + types with fullName of the Message as its value + [boolean] [default: false] ``` ### Example Usage diff --git a/packages/proto-loader/bin/proto-loader-gen-types.ts b/packages/proto-loader/bin/proto-loader-gen-types.ts index 04717f3fb..f75822084 100644 --- a/packages/proto-loader/bin/proto-loader-gen-types.ts +++ b/packages/proto-loader/bin/proto-loader-gen-types.ts @@ -26,12 +26,27 @@ import * as yargs from 'yargs'; import camelCase = require('lodash.camelcase'); import { loadProtosWithOptions, addCommonProtos } from '../src/util'; +const templateStr = "%s"; +const useNameFmter = ({outputTemplate, inputTemplate}: GeneratorOptions) => { + if (outputTemplate === inputTemplate) { + throw new Error('inputTemplate and outputTemplate must differ') + } + return { + outputName: (n: string) => outputTemplate.replace(templateStr, n), + inputName: (n: string) => inputTemplate.replace(templateStr, n) + }; +} + type GeneratorOptions = Protobuf.IParseOptions & Protobuf.IConversionOptions & { includeDirs?: string[]; grpcLib: string; outDir: string; verbose?: boolean; includeComments?: boolean; + inputTemplate: string; + outputTemplate: string; + inputBranded: boolean; + outputBranded: boolean; } class TextFormatter { @@ -114,27 +129,24 @@ function getTypeInterfaceName(type: Protobuf.Type | Protobuf.Enum | Protobuf.Ser return type.fullName.replace(/\./g, '_'); } -function getImportLine(dependency: Protobuf.Type | Protobuf.Enum | Protobuf.Service, from?: Protobuf.Type | Protobuf.Service) { +function getImportLine(dependency: Protobuf.Type | Protobuf.Enum | Protobuf.Service, from: Protobuf.Type | Protobuf.Service | undefined, options: GeneratorOptions) { const filePath = from === undefined ? './' + getImportPath(dependency) : getRelativeImportPath(from, dependency); + const {outputName, inputName} = useNameFmter(options); const typeInterfaceName = getTypeInterfaceName(dependency); let importedTypes: string; /* If the dependency is defined within a message, it will be generated in that * message's file and exported using its typeInterfaceName. */ if (dependency.parent instanceof Protobuf.Type) { - if (dependency instanceof Protobuf.Type) { - importedTypes = `${typeInterfaceName}, ${typeInterfaceName}__Output`; - } else if (dependency instanceof Protobuf.Enum) { - importedTypes = `${typeInterfaceName}`; + if (dependency instanceof Protobuf.Type || dependency instanceof Protobuf.Enum) { + importedTypes = `${inputName(typeInterfaceName)}, ${outputName(typeInterfaceName)}`; } else if (dependency instanceof Protobuf.Service) { importedTypes = `${typeInterfaceName}Client, ${typeInterfaceName}Definition`; } else { throw new Error('Invalid object passed to getImportLine'); } } else { - if (dependency instanceof Protobuf.Type) { - importedTypes = `${dependency.name} as ${typeInterfaceName}, ${dependency.name}__Output as ${typeInterfaceName}__Output`; - } else if (dependency instanceof Protobuf.Enum) { - importedTypes = `${dependency.name} as ${typeInterfaceName}`; + if (dependency instanceof Protobuf.Type || dependency instanceof Protobuf.Enum) { + importedTypes = `${inputName(dependency.name)} as ${inputName(typeInterfaceName)}, ${outputName(dependency.name)} as ${outputName(typeInterfaceName)}`; } else if (dependency instanceof Protobuf.Service) { importedTypes = `${dependency.name}Client as ${typeInterfaceName}Client, ${dependency.name}Definition as ${typeInterfaceName}Definition`; } else { @@ -168,9 +180,18 @@ function formatComment(formatter: TextFormatter, comment?: string | null) { formatter.writeLine(' */'); } +const typeBrandHint = `This field is a type brand and is not populated at runtime. Instances of this type should be created using type assertions. +https://github.com/grpc/grpc-node/pull/2281`; + +function formatTypeBrand(formatter: TextFormatter, messageType: Protobuf.Type) { + formatComment(formatter, typeBrandHint); + formatter.writeLine(`__type: '${messageType.fullName}'`); +} + // GENERATOR FUNCTIONS -function getTypeNamePermissive(fieldType: string, resolvedType: Protobuf.Type | Protobuf.Enum | null, repeated: boolean, map: boolean): string { +function getTypeNamePermissive(fieldType: string, resolvedType: Protobuf.Type | Protobuf.Enum | null, repeated: boolean, map: boolean, options: GeneratorOptions): string { + const {inputName} = useNameFmter(options); switch (fieldType) { case 'double': case 'float': @@ -200,18 +221,19 @@ function getTypeNamePermissive(fieldType: string, resolvedType: Protobuf.Type | const typeInterfaceName = getTypeInterfaceName(resolvedType); if (resolvedType instanceof Protobuf.Type) { if (repeated || map) { - return typeInterfaceName; + return inputName(typeInterfaceName); } else { - return `${typeInterfaceName} | null`; + return `${inputName(typeInterfaceName)} | null`; } } else { - return `${typeInterfaceName} | keyof typeof ${typeInterfaceName}`; + // Enum + return inputName(typeInterfaceName); } } } -function getFieldTypePermissive(field: Protobuf.FieldBase): string { - const valueType = getTypeNamePermissive(field.type, field.resolvedType, field.repeated, field.map); +function getFieldTypePermissive(field: Protobuf.FieldBase, options: GeneratorOptions): string { + const valueType = getTypeNamePermissive(field.type, field.resolvedType, field.repeated, field.map, options); if (field instanceof Protobuf.MapField) { const keyType = field.keyType === 'string' ? 'string' : 'number'; return `{[key: ${keyType}]: ${valueType}}`; @@ -221,23 +243,24 @@ function getFieldTypePermissive(field: Protobuf.FieldBase): string { } function generatePermissiveMessageInterface(formatter: TextFormatter, messageType: Protobuf.Type, options: GeneratorOptions, nameOverride?: string) { + const {inputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, messageType.comment); } if (messageType.fullName === '.google.protobuf.Any') { /* This describes the behavior of the Protobuf.js Any wrapper fromObject * replacement function */ - formatter.writeLine('export type Any = AnyExtension | {'); + formatter.writeLine(`export type ${inputName('Any')} = AnyExtension | {`); formatter.writeLine(' type_url: string;'); formatter.writeLine(' value: Buffer | Uint8Array | string;'); formatter.writeLine('}'); return; } - formatter.writeLine(`export interface ${nameOverride ?? messageType.name} {`); + formatter.writeLine(`export interface ${inputName(nameOverride ?? messageType.name)} {`); formatter.indent(); for (const field of messageType.fieldsArray) { const repeatedString = field.repeated ? '[]' : ''; - const type: string = getFieldTypePermissive(field); + const type: string = getFieldTypePermissive(field, options); if (options.includeComments) { formatComment(formatter, field.comment); } @@ -250,11 +273,15 @@ function generatePermissiveMessageInterface(formatter: TextFormatter, messageTyp } formatter.writeLine(`'${oneof.name}'?: ${typeString};`); } + if (options.inputBranded) { + formatTypeBrand(formatter, messageType); + } formatter.unindent(); formatter.writeLine('}'); } function getTypeNameRestricted(fieldType: string, resolvedType: Protobuf.Type | Protobuf.Enum | null, repeated: boolean, map: boolean, options: GeneratorOptions): string { + const {outputName} = useNameFmter(options); switch (fieldType) { case 'double': case 'float': @@ -302,16 +329,13 @@ function getTypeNameRestricted(fieldType: string, resolvedType: Protobuf.Type | /* null is only used to represent absent message values if the defaults * option is set, and only for non-repeated, non-map fields. */ if (options.defaults && !repeated && !map) { - return `${typeInterfaceName}__Output | null`; + return `${outputName(typeInterfaceName)} | null`; } else { - return `${typeInterfaceName}__Output`; + return `${outputName(typeInterfaceName)}`; } } else { - if (options.enums == String) { - return `keyof typeof ${typeInterfaceName}`; - } else { - return typeInterfaceName; - } + // Enum + return outputName(typeInterfaceName); } } } @@ -327,6 +351,7 @@ function getFieldTypeRestricted(field: Protobuf.FieldBase, options: GeneratorOpt } function generateRestrictedMessageInterface(formatter: TextFormatter, messageType: Protobuf.Type, options: GeneratorOptions, nameOverride?: string) { + const {outputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, messageType.comment); } @@ -334,13 +359,13 @@ function generateRestrictedMessageInterface(formatter: TextFormatter, messageTyp /* This describes the behavior of the Protobuf.js Any wrapper toObject * replacement function */ let optionalString = options.defaults ? '' : '?'; - formatter.writeLine('export type Any__Output = AnyExtension | {'); + formatter.writeLine(`export type ${outputName('Any')} = AnyExtension | {`); formatter.writeLine(` type_url${optionalString}: string;`); formatter.writeLine(` value${optionalString}: ${getTypeNameRestricted('bytes', null, false, false, options)};`); formatter.writeLine('}'); return; } - formatter.writeLine(`export interface ${nameOverride ?? messageType.name}__Output {`); + formatter.writeLine(`export interface ${outputName(nameOverride ?? messageType.name)} {`); formatter.indent(); for (const field of messageType.fieldsArray) { let fieldGuaranteed: boolean; @@ -371,6 +396,9 @@ function generateRestrictedMessageInterface(formatter: TextFormatter, messageTyp formatter.writeLine(`'${oneof.name}': ${typeString};`); } } + if (options.outputBranded) { + formatTypeBrand(formatter, messageType); + } formatter.unindent(); formatter.writeLine('}'); } @@ -379,7 +407,7 @@ function generateMessageInterfaces(formatter: TextFormatter, messageType: Protob let usesLong: boolean = false; let seenDeps: Set = new Set(); const childTypes = getChildMessagesAndEnums(messageType); - formatter.writeLine(`// Original file: ${messageType.filename}`); + formatter.writeLine(`// Original file: ${(messageType.filename ?? 'null')?.replace(/\\/g, '/')}`); formatter.writeLine(''); messageType.fieldsArray.sort((fieldA, fieldB) => fieldA.id - fieldB.id); for (const field of messageType.fieldsArray) { @@ -389,7 +417,7 @@ function generateMessageInterfaces(formatter: TextFormatter, messageType: Protob continue; } seenDeps.add(dependency.fullName); - formatter.writeLine(getImportLine(dependency, messageType)); + formatter.writeLine(getImportLine(dependency, messageType, options)); } if (field.type.indexOf('64') >= 0) { usesLong = true; @@ -404,7 +432,7 @@ function generateMessageInterfaces(formatter: TextFormatter, messageType: Protob continue; } seenDeps.add(dependency.fullName); - formatter.writeLine(getImportLine(dependency, messageType)); + formatter.writeLine(getImportLine(dependency, messageType, options)); } if (field.type.indexOf('64') >= 0) { usesLong = true; @@ -437,24 +465,82 @@ function generateMessageInterfaces(formatter: TextFormatter, messageType: Protob } function generateEnumInterface(formatter: TextFormatter, enumType: Protobuf.Enum, options: GeneratorOptions, nameOverride?: string) { - formatter.writeLine(`// Original file: ${enumType.filename}`); + const {inputName, outputName} = useNameFmter(options); + const name = nameOverride ?? enumType.name; + formatter.writeLine(`// Original file: ${(enumType.filename ?? 'null')?.replace(/\\/g, '/')}`); formatter.writeLine(''); if (options.includeComments) { formatComment(formatter, enumType.comment); } - formatter.writeLine(`export enum ${nameOverride ?? enumType.name} {`); + formatter.writeLine(`export const ${name} = {`); formatter.indent(); for (const key of Object.keys(enumType.values)) { if (options.includeComments) { formatComment(formatter, enumType.comments[key]); } - formatter.writeLine(`${key} = ${enumType.values[key]},`); + formatter.writeLine(`${key}: ${options.enums == String ? `'${key}'` : enumType.values[key]},`); } formatter.unindent(); - formatter.writeLine('}'); + formatter.writeLine('} as const;'); + + // Permissive Type + formatter.writeLine(''); + if (options.includeComments) { + formatComment(formatter, enumType.comment); + } + formatter.writeLine(`export type ${inputName(name)} =`) + formatter.indent(); + for (const key of Object.keys(enumType.values)) { + if (options.includeComments) { + formatComment(formatter, enumType.comments[key]); + } + formatter.writeLine(`| '${key}'`); + formatter.writeLine(`| ${enumType.values[key]}`); + } + formatter.unindent(); + + // Restrictive Type + formatter.writeLine(''); + if (options.includeComments) { + formatComment(formatter, enumType.comment); + } + formatter.writeLine(`export type ${outputName(name)} = typeof ${name}[keyof typeof ${name}]`) } +/** + * This is a list of methods that are exist in the generic Client class in the + * gRPC libraries. TypeScript has a problem with methods in subclasses with the + * same names as methods in the superclass, but with mismatched APIs. So, we + * avoid generating methods with these names in the service client interfaces. + * We always generate two service client methods per service method: one camel + * cased, and one with the original casing. So we will still generate one + * service client method for any conflicting name. + * + * Technically, at runtime conflicting name in the service client method + * actually shadows the original method, but TypeScript does not have a good + * way to represent that. So this change is not 100% accurate, but it gets the + * generated code to compile. + * + * This is just a list of the methods in the Client class definitions in + * grpc@1.24.11 and @grpc/grpc-js@1.4.0. + */ +const CLIENT_RESERVED_METHOD_NAMES = new Set([ + 'close', + 'getChannel', + 'waitForReady', + 'makeUnaryRequest', + 'makeClientStreamRequest', + 'makeServerStreamRequest', + 'makeBidiStreamRequest', + 'resolveCallInterceptors', + /* These methods are private, but TypeScript is not happy with overriding even + * private methods with mismatched APIs. */ + 'checkOptionalUnaryResponseArguments', + 'checkMetadataAndOptions' +]); + function generateServiceClientInterface(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) { + const {outputName, inputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, serviceType.comment); } @@ -463,12 +549,15 @@ function generateServiceClientInterface(formatter: TextFormatter, serviceType: P for (const methodName of Object.keys(serviceType.methods).sort()) { const method = serviceType.methods[methodName]; for (const name of [methodName, camelCase(methodName)]) { + if (CLIENT_RESERVED_METHOD_NAMES.has(name)) { + continue; + } if (options.includeComments) { formatComment(formatter, method.comment); } - const requestType = getTypeInterfaceName(method.resolvedRequestType!); - const responseType = getTypeInterfaceName(method.resolvedResponseType!) + '__Output'; - const callbackType = `(error?: grpc.ServiceError, result?: ${responseType}) => void`; + const requestType = inputName(getTypeInterfaceName(method.resolvedRequestType!)); + const responseType = outputName(getTypeInterfaceName(method.resolvedResponseType!)); + const callbackType = `grpc.requestCallback<${responseType}>`; if (method.requestStream) { if (method.responseStream) { // Bidi streaming @@ -506,6 +595,7 @@ function generateServiceClientInterface(formatter: TextFormatter, serviceType: P } function generateServiceHandlerInterface(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) { + const {inputName, outputName} = useNameFmter(options); if (options.includeComments) { formatComment(formatter, serviceType.comment); } @@ -516,8 +606,8 @@ function generateServiceHandlerInterface(formatter: TextFormatter, serviceType: if (options.includeComments) { formatComment(formatter, method.comment); } - const requestType = getTypeInterfaceName(method.resolvedRequestType!) + '__Output'; - const responseType = getTypeInterfaceName(method.resolvedResponseType!); + const requestType = outputName(getTypeInterfaceName(method.resolvedRequestType!)); + const responseType = inputName(getTypeInterfaceName(method.resolvedResponseType!)); if (method.requestStream) { if (method.responseStream) { // Bidi streaming @@ -541,21 +631,22 @@ function generateServiceHandlerInterface(formatter: TextFormatter, serviceType: formatter.writeLine('}'); } -function generateServiceDefinitionInterface(formatter: TextFormatter, serviceType: Protobuf.Service) { - formatter.writeLine(`export interface ${serviceType.name}Definition {`); +function generateServiceDefinitionInterface(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) { + const {inputName, outputName} = useNameFmter(options); + formatter.writeLine(`export interface ${serviceType.name}Definition extends grpc.ServiceDefinition {`); formatter.indent(); for (const methodName of Object.keys(serviceType.methods).sort()) { const method = serviceType.methods[methodName]; const requestType = getTypeInterfaceName(method.resolvedRequestType!); const responseType = getTypeInterfaceName(method.resolvedResponseType!); - formatter.writeLine(`${methodName}: MethodDefinition<${requestType}, ${responseType}, ${requestType}__Output, ${responseType}__Output>`); + formatter.writeLine(`${methodName}: MethodDefinition<${inputName(requestType)}, ${inputName(responseType)}, ${outputName(requestType)}, ${outputName(responseType)}>`); } formatter.unindent(); formatter.writeLine('}') } function generateServiceInterfaces(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) { - formatter.writeLine(`// Original file: ${serviceType.filename}`); + formatter.writeLine(`// Original file: ${(serviceType.filename ?? 'null')?.replace(/\\/g, '/')}`); formatter.writeLine(''); const grpcImportPath = options.grpcLib.startsWith('.') ? getPathToRoot(serviceType) + options.grpcLib : options.grpcLib; formatter.writeLine(`import type * as grpc from '${grpcImportPath}'`); @@ -566,7 +657,7 @@ function generateServiceInterfaces(formatter: TextFormatter, serviceType: Protob dependencies.add(method.resolvedResponseType!); } for (const dep of Array.from(dependencies.values()).sort(compareName)) { - formatter.writeLine(getImportLine(dep, serviceType)); + formatter.writeLine(getImportLine(dep, serviceType, options)); } formatter.writeLine(''); @@ -576,13 +667,41 @@ function generateServiceInterfaces(formatter: TextFormatter, serviceType: Protob generateServiceHandlerInterface(formatter, serviceType, options); formatter.writeLine(''); - generateServiceDefinitionInterface(formatter, serviceType); + generateServiceDefinitionInterface(formatter, serviceType, options); +} + +function containsDefinition(definitionType: typeof Protobuf.Type | typeof Protobuf.Enum, namespace: Protobuf.NamespaceBase): boolean { + for (const nested of namespace.nestedArray.sort(compareName)) { + if (nested instanceof definitionType) { + return true; + } else if (isNamespaceBase(nested) && !(nested instanceof Protobuf.Type) && !(nested instanceof Protobuf.Enum) && containsDefinition(definitionType, nested)) { + return true; + } + } + + return false; +} + +function generateDefinitionImports(formatter: TextFormatter, namespace: Protobuf.NamespaceBase, options: GeneratorOptions) { + const imports = []; + + if (containsDefinition(Protobuf.Enum, namespace)) { + imports.push('EnumTypeDefinition'); + } + + if (containsDefinition(Protobuf.Type, namespace)) { + imports.push('MessageTypeDefinition'); + } + + if (imports.length) { + formatter.writeLine(`import type { ${imports.join(', ')} } from '@grpc/proto-loader';`); + } } function generateServiceImports(formatter: TextFormatter, namespace: Protobuf.NamespaceBase, options: GeneratorOptions) { for (const nested of namespace.nestedArray.sort(compareName)) { if (nested instanceof Protobuf.Service) { - formatter.writeLine(getImportLine(nested)); + formatter.writeLine(getImportLine(nested, undefined, options)); } else if (isNamespaceBase(nested) && !(nested instanceof Protobuf.Type) && !(nested instanceof Protobuf.Enum)) { generateServiceImports(formatter, nested, options); } @@ -617,7 +736,7 @@ function generateLoadedDefinitionTypes(formatter: TextFormatter, namespace: Prot function generateRootFile(formatter: TextFormatter, root: Protobuf.Root, options: GeneratorOptions) { formatter.writeLine(`import type * as grpc from '${options.grpcLib}';`); - formatter.writeLine("import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader';"); + generateDefinitionImports(formatter, root, options); formatter.writeLine(''); generateServiceImports(formatter, root, options); @@ -704,26 +823,40 @@ async function writeAllFiles(protoFiles: string[], options: GeneratorOptions) { } } -function runScript() { +async function runScript() { + const boolDefaultFalseOption = { + boolean: true, + default: false, + }; const argv = yargs .parserConfiguration({ 'parse-positional-numbers': false }) - .string(['includeDirs', 'grpcLib']) - .normalize(['includeDirs', 'outDir']) - .array('includeDirs') - .boolean(['keepCase', 'defaults', 'arrays', 'objects', 'oneofs', 'json', 'verbose', 'includeComments']) - .string(['longs', 'enums', 'bytes']) - .default('keepCase', false) - .default('defaults', false) - .default('arrays', false) - .default('objects', false) - .default('oneofs', false) - .default('json', false) - .default('includeComments', false) - .default('longs', 'Long') - .default('enums', 'number') - .default('bytes', 'Buffer') + .option('keepCase', boolDefaultFalseOption) + .option('longs', { string: true, default: 'Long' }) + .option('enums', { string: true, default: 'number' }) + .option('bytes', { string: true, default: 'Buffer' }) + .option('defaults', boolDefaultFalseOption) + .option('arrays', boolDefaultFalseOption) + .option('objects', boolDefaultFalseOption) + .option('oneofs', boolDefaultFalseOption) + .option('json', boolDefaultFalseOption) + .boolean('verbose') + .option('includeComments', boolDefaultFalseOption) + .option('includeDirs', { + normalize: true, + array: true, + alias: 'I' + }) + .option('outDir', { + alias: 'O', + normalize: true, + }) + .option('grpcLib', { string: true }) + .option('inputTemplate', { string: true, default: `${templateStr}` }) + .option('outputTemplate', { string: true, default: `${templateStr}__Output` }) + .option('inputBranded', boolDefaultFalseOption) + .option('outputBranded', boolDefaultFalseOption) .coerce('longs', value => { switch (value) { case 'String': return String; @@ -742,9 +875,8 @@ function runScript() { case 'String': return String; default: return undefined; } - }).alias({ - includeDirs: 'I', - outDir: 'O', + }) + .alias({ verbose: 'v' }).describe({ keepCase: 'Preserve the case of field names', @@ -759,7 +891,11 @@ function runScript() { includeComments: 'Generate doc comments from comments in the original files', includeDirs: 'Directories to search for included files', outDir: 'Directory in which to output files', - grpcLib: 'The gRPC implementation library that these types will be used with' + grpcLib: 'The gRPC implementation library that these types will be used with', + inputTemplate: 'Template for mapping input or "permissive" type names', + outputTemplate: 'Template for mapping output or "restricted" type names', + inputBranded: 'Output property for branded type for "permissive" types with fullName of the Message as its value', + outputBranded: 'Output property for branded type for "restricted" types with fullName of the Message as its value', }).demandOption(['outDir', 'grpcLib']) .demand(1) .usage('$0 [options] filenames...') diff --git a/packages/proto-loader/golden-generated/echo.ts b/packages/proto-loader/golden-generated/echo.ts index f257a40e4..600e2864c 100644 --- a/packages/proto-loader/golden-generated/echo.ts +++ b/packages/proto-loader/golden-generated/echo.ts @@ -1,5 +1,5 @@ import type * as grpc from '@grpc/grpc-js'; -import type { ServiceDefinition, EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; import type { OperationsClient as _google_longrunning_OperationsClient, OperationsDefinition as _google_longrunning_OperationsDefinition } from './google/longrunning/Operations'; import type { EchoClient as _google_showcase_v1beta1_EchoClient, EchoDefinition as _google_showcase_v1beta1_EchoDefinition } from './google/showcase/v1beta1/Echo'; diff --git a/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts b/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts index 2b6490be6..2f6e20297 100644 --- a/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts +++ b/packages/proto-loader/golden-generated/google/api/CustomHttpPattern.ts @@ -4,7 +4,7 @@ /** * A custom pattern is used for defining custom HTTP verb. */ -export interface CustomHttpPattern { +export interface ICustomHttpPattern { /** * The name of this custom HTTP verb. */ @@ -18,7 +18,7 @@ export interface CustomHttpPattern { /** * A custom pattern is used for defining custom HTTP verb. */ -export interface CustomHttpPattern__Output { +export interface OCustomHttpPattern { /** * The name of this custom HTTP verb. */ diff --git a/packages/proto-loader/golden-generated/google/api/FieldBehavior.ts b/packages/proto-loader/golden-generated/google/api/FieldBehavior.ts index 8ab676709..189d25be5 100644 --- a/packages/proto-loader/golden-generated/google/api/FieldBehavior.ts +++ b/packages/proto-loader/golden-generated/google/api/FieldBehavior.ts @@ -8,40 +8,101 @@ * * Note: This enum **may** receive new values in the future. */ -export enum FieldBehavior { +export const FieldBehavior = { /** * Conventional default for enums. Do not use this. */ - FIELD_BEHAVIOR_UNSPECIFIED = 0, + FIELD_BEHAVIOR_UNSPECIFIED: 'FIELD_BEHAVIOR_UNSPECIFIED', /** * Specifically denotes a field as optional. * While all fields in protocol buffers are optional, this may be specified * for emphasis if appropriate. */ - OPTIONAL = 1, + OPTIONAL: 'OPTIONAL', /** * Denotes a field as required. * This indicates that the field **must** be provided as part of the request, * and failure to do so will cause an error (usually `INVALID_ARGUMENT`). */ - REQUIRED = 2, + REQUIRED: 'REQUIRED', /** * Denotes a field as output only. * This indicates that the field is provided in responses, but including the * field in a request does nothing (the server *must* ignore it and * *must not* throw an error as a result of the field's presence). */ - OUTPUT_ONLY = 3, + OUTPUT_ONLY: 'OUTPUT_ONLY', /** * Denotes a field as input only. * This indicates that the field is provided in requests, and the * corresponding field is not included in output. */ - INPUT_ONLY = 4, + INPUT_ONLY: 'INPUT_ONLY', /** * Denotes a field as immutable. * This indicates that the field may be set once in a request to create a * resource, but may not be changed thereafter. */ - IMMUTABLE = 5, -} + IMMUTABLE: 'IMMUTABLE', +} as const; + +/** + * An indicator of the behavior of a given field (for example, that a field + * is required in requests, or given as output but ignored as input). + * This **does not** change the behavior in protocol buffers itself; it only + * denotes the behavior and may affect how API tooling handles the field. + * + * Note: This enum **may** receive new values in the future. + */ +export type IFieldBehavior = + /** + * Conventional default for enums. Do not use this. + */ + | 'FIELD_BEHAVIOR_UNSPECIFIED' + | 0 + /** + * Specifically denotes a field as optional. + * While all fields in protocol buffers are optional, this may be specified + * for emphasis if appropriate. + */ + | 'OPTIONAL' + | 1 + /** + * Denotes a field as required. + * This indicates that the field **must** be provided as part of the request, + * and failure to do so will cause an error (usually `INVALID_ARGUMENT`). + */ + | 'REQUIRED' + | 2 + /** + * Denotes a field as output only. + * This indicates that the field is provided in responses, but including the + * field in a request does nothing (the server *must* ignore it and + * *must not* throw an error as a result of the field's presence). + */ + | 'OUTPUT_ONLY' + | 3 + /** + * Denotes a field as input only. + * This indicates that the field is provided in requests, and the + * corresponding field is not included in output. + */ + | 'INPUT_ONLY' + | 4 + /** + * Denotes a field as immutable. + * This indicates that the field may be set once in a request to create a + * resource, but may not be changed thereafter. + */ + | 'IMMUTABLE' + | 5 + +/** + * An indicator of the behavior of a given field (for example, that a field + * is required in requests, or given as output but ignored as input). + * This **does not** change the behavior in protocol buffers itself; it only + * denotes the behavior and may affect how API tooling handles the field. + * + * Note: This enum **may** receive new values in the future. + */ +export type OFieldBehavior = typeof FieldBehavior[keyof typeof FieldBehavior] diff --git a/packages/proto-loader/golden-generated/google/api/Http.ts b/packages/proto-loader/golden-generated/google/api/Http.ts index e9b3cb309..6b6ae8a63 100644 --- a/packages/proto-loader/golden-generated/google/api/Http.ts +++ b/packages/proto-loader/golden-generated/google/api/Http.ts @@ -1,19 +1,19 @@ // Original file: deps/googleapis/google/api/http.proto -import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; +import type { IHttpRule as I_google_api_HttpRule, OHttpRule as O_google_api_HttpRule } from '../../google/api/HttpRule'; /** * Defines the HTTP configuration for an API service. It contains a list of * [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method * to one or more HTTP REST API methods. */ -export interface Http { +export interface IHttp { /** * A list of HTTP configuration rules that apply to individual API methods. * * **NOTE:** All service configuration rules follow "last one wins" order. */ - 'rules'?: (_google_api_HttpRule)[]; + 'rules'?: (I_google_api_HttpRule)[]; /** * When set to true, URL path parameters will be fully URI-decoded except in * cases of single segment matches in reserved expansion, where "%2F" will be @@ -30,13 +30,13 @@ export interface Http { * [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method * to one or more HTTP REST API methods. */ -export interface Http__Output { +export interface OHttp { /** * A list of HTTP configuration rules that apply to individual API methods. * * **NOTE:** All service configuration rules follow "last one wins" order. */ - 'rules': (_google_api_HttpRule__Output)[]; + 'rules': (O_google_api_HttpRule)[]; /** * When set to true, URL path parameters will be fully URI-decoded except in * cases of single segment matches in reserved expansion, where "%2F" will be diff --git a/packages/proto-loader/golden-generated/google/api/HttpRule.ts b/packages/proto-loader/golden-generated/google/api/HttpRule.ts index 243a99f80..90efdc00d 100644 --- a/packages/proto-loader/golden-generated/google/api/HttpRule.ts +++ b/packages/proto-loader/golden-generated/google/api/HttpRule.ts @@ -1,7 +1,7 @@ // Original file: deps/googleapis/google/api/http.proto -import type { CustomHttpPattern as _google_api_CustomHttpPattern, CustomHttpPattern__Output as _google_api_CustomHttpPattern__Output } from '../../google/api/CustomHttpPattern'; -import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; +import type { ICustomHttpPattern as I_google_api_CustomHttpPattern, OCustomHttpPattern as O_google_api_CustomHttpPattern } from '../../google/api/CustomHttpPattern'; +import type { IHttpRule as I_google_api_HttpRule, OHttpRule as O_google_api_HttpRule } from '../../google/api/HttpRule'; /** * # gRPC Transcoding @@ -274,7 +274,7 @@ import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_ * the request or response body to a repeated field. However, some gRPC * Transcoding implementations may not support this feature. */ -export interface HttpRule { +export interface IHttpRule { /** * Selects a method to which this rule applies. * @@ -317,13 +317,13 @@ export interface HttpRule { * HTTP method unspecified for this rule. The wild-card rule is useful * for services that provide content to Web (HTML) clients. */ - 'custom'?: (_google_api_CustomHttpPattern | null); + 'custom'?: (I_google_api_CustomHttpPattern | null); /** * Additional HTTP bindings for the selector. Nested bindings must * not contain an `additional_bindings` field themselves (that is, * the nesting may only be one level deep). */ - 'additional_bindings'?: (_google_api_HttpRule)[]; + 'additional_bindings'?: (I_google_api_HttpRule)[]; /** * Optional. The name of the response field whose value is mapped to the HTTP * response body. When omitted, the entire response message will be used @@ -612,7 +612,7 @@ export interface HttpRule { * the request or response body to a repeated field. However, some gRPC * Transcoding implementations may not support this feature. */ -export interface HttpRule__Output { +export interface OHttpRule { /** * Selects a method to which this rule applies. * @@ -655,13 +655,13 @@ export interface HttpRule__Output { * HTTP method unspecified for this rule. The wild-card rule is useful * for services that provide content to Web (HTML) clients. */ - 'custom'?: (_google_api_CustomHttpPattern__Output | null); + 'custom'?: (O_google_api_CustomHttpPattern | null); /** * Additional HTTP bindings for the selector. Nested bindings must * not contain an `additional_bindings` field themselves (that is, * the nesting may only be one level deep). */ - 'additional_bindings': (_google_api_HttpRule__Output)[]; + 'additional_bindings': (O_google_api_HttpRule)[]; /** * Optional. The name of the response field whose value is mapped to the HTTP * response body. When omitted, the entire response message will be used diff --git a/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts index 05fbc842e..7e0f15ed8 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/CancelOperationRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]. */ -export interface CancelOperationRequest { +export interface ICancelOperationRequest { /** * The name of the operation resource to be cancelled. */ @@ -14,7 +14,7 @@ export interface CancelOperationRequest { /** * The request message for [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]. */ -export interface CancelOperationRequest__Output { +export interface OCancelOperationRequest { /** * The name of the operation resource to be cancelled. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts index 0ad87cde9..39d669d0a 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/DeleteOperationRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.DeleteOperation][google.longrunning.Operations.DeleteOperation]. */ -export interface DeleteOperationRequest { +export interface IDeleteOperationRequest { /** * The name of the operation resource to be deleted. */ @@ -14,7 +14,7 @@ export interface DeleteOperationRequest { /** * The request message for [Operations.DeleteOperation][google.longrunning.Operations.DeleteOperation]. */ -export interface DeleteOperationRequest__Output { +export interface ODeleteOperationRequest { /** * The name of the operation resource to be deleted. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts index 039f01674..9667e2e87 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/GetOperationRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.GetOperation][google.longrunning.Operations.GetOperation]. */ -export interface GetOperationRequest { +export interface IGetOperationRequest { /** * The name of the operation resource. */ @@ -14,7 +14,7 @@ export interface GetOperationRequest { /** * The request message for [Operations.GetOperation][google.longrunning.Operations.GetOperation]. */ -export interface GetOperationRequest__Output { +export interface OGetOperationRequest { /** * The name of the operation resource. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts index 294ec6773..49dcd39f0 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsRequest.ts @@ -4,7 +4,7 @@ /** * The request message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsRequest { +export interface IListOperationsRequest { /** * The standard list filter. */ @@ -26,7 +26,7 @@ export interface ListOperationsRequest { /** * The request message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsRequest__Output { +export interface OListOperationsRequest { /** * The standard list filter. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts index c295aa801..1e8b9ed5a 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/ListOperationsResponse.ts @@ -1,15 +1,15 @@ // Original file: deps/googleapis/google/longrunning/operations.proto -import type { Operation as _google_longrunning_Operation, Operation__Output as _google_longrunning_Operation__Output } from '../../google/longrunning/Operation'; +import type { IOperation as I_google_longrunning_Operation, OOperation as O_google_longrunning_Operation } from '../../google/longrunning/Operation'; /** * The response message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsResponse { +export interface IListOperationsResponse { /** * A list of operations that matches the specified filter in the request. */ - 'operations'?: (_google_longrunning_Operation)[]; + 'operations'?: (I_google_longrunning_Operation)[]; /** * The standard List next-page token. */ @@ -19,11 +19,11 @@ export interface ListOperationsResponse { /** * The response message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. */ -export interface ListOperationsResponse__Output { +export interface OListOperationsResponse { /** * A list of operations that matches the specified filter in the request. */ - 'operations': (_google_longrunning_Operation__Output)[]; + 'operations': (O_google_longrunning_Operation)[]; /** * The standard List next-page token. */ diff --git a/packages/proto-loader/golden-generated/google/longrunning/Operation.ts b/packages/proto-loader/golden-generated/google/longrunning/Operation.ts index 2a4bbe1ee..bbd1d8078 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/Operation.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/Operation.ts @@ -1,13 +1,13 @@ // Original file: deps/googleapis/google/longrunning/operations.proto -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../google/protobuf/Any'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../google/rpc/Status'; +import type { IAny as I_google_protobuf_Any, OAny as O_google_protobuf_Any } from '../../google/protobuf/Any'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../google/rpc/Status'; /** * This resource represents a long-running operation that is the result of a * network API call. */ -export interface Operation { +export interface IOperation { /** * The server-assigned name, which is only unique within the same service that * originally returns it. If you use the default HTTP mapping, the @@ -20,7 +20,7 @@ export interface Operation { * Some services might not provide such metadata. Any method that returns a * long-running operation should document the metadata type, if any. */ - 'metadata'?: (_google_protobuf_Any | null); + 'metadata'?: (I_google_protobuf_Any | null); /** * If the value is `false`, it means the operation is still in progress. * If `true`, the operation is completed, and either `error` or `response` is @@ -30,7 +30,7 @@ export interface Operation { /** * The error result of the operation in case of failure or cancellation. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The normal response of the operation in case of success. If the original * method returns no data on success, such as `Delete`, the response is @@ -41,7 +41,7 @@ export interface Operation { * is `TakeSnapshot()`, the inferred response type is * `TakeSnapshotResponse`. */ - 'response'?: (_google_protobuf_Any | null); + 'response'?: (I_google_protobuf_Any | null); /** * The operation result, which can be either an `error` or a valid `response`. * If `done` == `false`, neither `error` nor `response` is set. @@ -54,7 +54,7 @@ export interface Operation { * This resource represents a long-running operation that is the result of a * network API call. */ -export interface Operation__Output { +export interface OOperation { /** * The server-assigned name, which is only unique within the same service that * originally returns it. If you use the default HTTP mapping, the @@ -67,7 +67,7 @@ export interface Operation__Output { * Some services might not provide such metadata. Any method that returns a * long-running operation should document the metadata type, if any. */ - 'metadata': (_google_protobuf_Any__Output | null); + 'metadata': (O_google_protobuf_Any | null); /** * If the value is `false`, it means the operation is still in progress. * If `true`, the operation is completed, and either `error` or `response` is @@ -77,7 +77,7 @@ export interface Operation__Output { /** * The error result of the operation in case of failure or cancellation. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The normal response of the operation in case of success. If the original * method returns no data on success, such as `Delete`, the response is @@ -88,7 +88,7 @@ export interface Operation__Output { * is `TakeSnapshot()`, the inferred response type is * `TakeSnapshotResponse`. */ - 'response'?: (_google_protobuf_Any__Output | null); + 'response'?: (O_google_protobuf_Any | null); /** * The operation result, which can be either an `error` or a valid `response`. * If `done` == `false`, neither `error` nor `response` is set. diff --git a/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts b/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts index 343e2f8c9..907574412 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/OperationInfo.ts @@ -14,7 +14,7 @@ * }; * } */ -export interface OperationInfo { +export interface IOperationInfo { /** * Required. The message name of the primary return type for this * long-running operation. @@ -51,7 +51,7 @@ export interface OperationInfo { * }; * } */ -export interface OperationInfo__Output { +export interface OOperationInfo { /** * Required. The message name of the primary return type for this * long-running operation. diff --git a/packages/proto-loader/golden-generated/google/longrunning/Operations.ts b/packages/proto-loader/golden-generated/google/longrunning/Operations.ts index 8e5684ada..00d6a95d2 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/Operations.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/Operations.ts @@ -2,14 +2,14 @@ import type * as grpc from '@grpc/grpc-js' import type { MethodDefinition } from '@grpc/proto-loader' -import type { CancelOperationRequest as _google_longrunning_CancelOperationRequest, CancelOperationRequest__Output as _google_longrunning_CancelOperationRequest__Output } from '../../google/longrunning/CancelOperationRequest'; -import type { DeleteOperationRequest as _google_longrunning_DeleteOperationRequest, DeleteOperationRequest__Output as _google_longrunning_DeleteOperationRequest__Output } from '../../google/longrunning/DeleteOperationRequest'; -import type { Empty as _google_protobuf_Empty, Empty__Output as _google_protobuf_Empty__Output } from '../../google/protobuf/Empty'; -import type { GetOperationRequest as _google_longrunning_GetOperationRequest, GetOperationRequest__Output as _google_longrunning_GetOperationRequest__Output } from '../../google/longrunning/GetOperationRequest'; -import type { ListOperationsRequest as _google_longrunning_ListOperationsRequest, ListOperationsRequest__Output as _google_longrunning_ListOperationsRequest__Output } from '../../google/longrunning/ListOperationsRequest'; -import type { ListOperationsResponse as _google_longrunning_ListOperationsResponse, ListOperationsResponse__Output as _google_longrunning_ListOperationsResponse__Output } from '../../google/longrunning/ListOperationsResponse'; -import type { Operation as _google_longrunning_Operation, Operation__Output as _google_longrunning_Operation__Output } from '../../google/longrunning/Operation'; -import type { WaitOperationRequest as _google_longrunning_WaitOperationRequest, WaitOperationRequest__Output as _google_longrunning_WaitOperationRequest__Output } from '../../google/longrunning/WaitOperationRequest'; +import type { ICancelOperationRequest as I_google_longrunning_CancelOperationRequest, OCancelOperationRequest as O_google_longrunning_CancelOperationRequest } from '../../google/longrunning/CancelOperationRequest'; +import type { IDeleteOperationRequest as I_google_longrunning_DeleteOperationRequest, ODeleteOperationRequest as O_google_longrunning_DeleteOperationRequest } from '../../google/longrunning/DeleteOperationRequest'; +import type { IEmpty as I_google_protobuf_Empty, OEmpty as O_google_protobuf_Empty } from '../../google/protobuf/Empty'; +import type { IGetOperationRequest as I_google_longrunning_GetOperationRequest, OGetOperationRequest as O_google_longrunning_GetOperationRequest } from '../../google/longrunning/GetOperationRequest'; +import type { IListOperationsRequest as I_google_longrunning_ListOperationsRequest, OListOperationsRequest as O_google_longrunning_ListOperationsRequest } from '../../google/longrunning/ListOperationsRequest'; +import type { IListOperationsResponse as I_google_longrunning_ListOperationsResponse, OListOperationsResponse as O_google_longrunning_ListOperationsResponse } from '../../google/longrunning/ListOperationsResponse'; +import type { IOperation as I_google_longrunning_Operation, OOperation as O_google_longrunning_Operation } from '../../google/longrunning/Operation'; +import type { IWaitOperationRequest as I_google_longrunning_WaitOperationRequest, OWaitOperationRequest as O_google_longrunning_WaitOperationRequest } from '../../google/longrunning/WaitOperationRequest'; /** * Manages long-running operations with an API service. @@ -35,10 +35,10 @@ export interface OperationsClient extends grpc.Client { * an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1, * corresponding to `Code.CANCELLED`. */ - CancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - CancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - CancelOperation(argument: _google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - CancelOperation(argument: _google_longrunning_CancelOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + CancelOperation(argument: I_google_longrunning_CancelOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Starts asynchronous cancellation on a long-running operation. The server * makes a best effort to cancel the operation, but success is not @@ -51,10 +51,10 @@ export interface OperationsClient extends grpc.Client { * an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1, * corresponding to `Code.CANCELLED`. */ - cancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - cancelOperation(argument: _google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - cancelOperation(argument: _google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - cancelOperation(argument: _google_longrunning_CancelOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + cancelOperation(argument: I_google_longrunning_CancelOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Deletes a long-running operation. This method indicates that the client is @@ -62,39 +62,39 @@ export interface OperationsClient extends grpc.Client { * operation. If the server doesn't support this method, it returns * `google.rpc.Code.UNIMPLEMENTED`. */ - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - DeleteOperation(argument: _google_longrunning_DeleteOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + DeleteOperation(argument: I_google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Deletes a long-running operation. This method indicates that the client is * no longer interested in the operation result. It does not cancel the * operation. If the server doesn't support this method, it returns * `google.rpc.Code.UNIMPLEMENTED`. */ - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; - deleteOperation(argument: _google_longrunning_DeleteOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_protobuf_Empty__Output) => void): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + deleteOperation(argument: I_google_longrunning_DeleteOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Gets the latest state of a long-running operation. Clients can use this * method to poll the operation result at intervals as recommended by the API * service. */ - GetOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - GetOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - GetOperation(argument: _google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - GetOperation(argument: _google_longrunning_GetOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + GetOperation(argument: I_google_longrunning_GetOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Gets the latest state of a long-running operation. Clients can use this * method to poll the operation result at intervals as recommended by the API * service. */ - getOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - getOperation(argument: _google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - getOperation(argument: _google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - getOperation(argument: _google_longrunning_GetOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getOperation(argument: I_google_longrunning_GetOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Lists operations that match the specified filter in the request. If the @@ -108,10 +108,10 @@ export interface OperationsClient extends grpc.Client { * collection id, however overriding users must ensure the name binding * is the parent resource, without the operations collection id. */ - ListOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; - ListOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; - ListOperations(argument: _google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; - ListOperations(argument: _google_longrunning_ListOperationsRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + ListOperations(argument: I_google_longrunning_ListOperationsRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Lists operations that match the specified filter in the request. If the * server doesn't support this method, it returns `UNIMPLEMENTED`. @@ -124,10 +124,10 @@ export interface OperationsClient extends grpc.Client { * collection id, however overriding users must ensure the name binding * is the parent resource, without the operations collection id. */ - listOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; - listOperations(argument: _google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; - listOperations(argument: _google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; - listOperations(argument: _google_longrunning_ListOperationsRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_ListOperationsResponse__Output) => void): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + listOperations(argument: I_google_longrunning_ListOperationsRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Waits for the specified long-running operation until it is done or reaches @@ -140,10 +140,10 @@ export interface OperationsClient extends grpc.Client { * state before the specified timeout (including immediately), meaning even an * immediate response is no guarantee that the operation is done. */ - WaitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - WaitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - WaitOperation(argument: _google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - WaitOperation(argument: _google_longrunning_WaitOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + WaitOperation(argument: I_google_longrunning_WaitOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * Waits for the specified long-running operation until it is done or reaches * at most a specified timeout, returning the latest state. If the operation @@ -155,10 +155,10 @@ export interface OperationsClient extends grpc.Client { * state before the specified timeout (including immediately), meaning even an * immediate response is no guarantee that the operation is done. */ - waitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - waitOperation(argument: _google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - waitOperation(argument: _google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - waitOperation(argument: _google_longrunning_WaitOperationRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + waitOperation(argument: I_google_longrunning_WaitOperationRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; } @@ -186,7 +186,7 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * an [Operation.error][google.longrunning.Operation.error] value with a [google.rpc.Status.code][google.rpc.Status.code] of 1, * corresponding to `Code.CANCELLED`. */ - CancelOperation: grpc.handleUnaryCall<_google_longrunning_CancelOperationRequest__Output, _google_protobuf_Empty>; + CancelOperation: grpc.handleUnaryCall; /** * Deletes a long-running operation. This method indicates that the client is @@ -194,14 +194,14 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * operation. If the server doesn't support this method, it returns * `google.rpc.Code.UNIMPLEMENTED`. */ - DeleteOperation: grpc.handleUnaryCall<_google_longrunning_DeleteOperationRequest__Output, _google_protobuf_Empty>; + DeleteOperation: grpc.handleUnaryCall; /** * Gets the latest state of a long-running operation. Clients can use this * method to poll the operation result at intervals as recommended by the API * service. */ - GetOperation: grpc.handleUnaryCall<_google_longrunning_GetOperationRequest__Output, _google_longrunning_Operation>; + GetOperation: grpc.handleUnaryCall; /** * Lists operations that match the specified filter in the request. If the @@ -215,7 +215,7 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * collection id, however overriding users must ensure the name binding * is the parent resource, without the operations collection id. */ - ListOperations: grpc.handleUnaryCall<_google_longrunning_ListOperationsRequest__Output, _google_longrunning_ListOperationsResponse>; + ListOperations: grpc.handleUnaryCall; /** * Waits for the specified long-running operation until it is done or reaches @@ -228,14 +228,14 @@ export interface OperationsHandlers extends grpc.UntypedServiceImplementation { * state before the specified timeout (including immediately), meaning even an * immediate response is no guarantee that the operation is done. */ - WaitOperation: grpc.handleUnaryCall<_google_longrunning_WaitOperationRequest__Output, _google_longrunning_Operation>; + WaitOperation: grpc.handleUnaryCall; } -export interface OperationsDefinition { - CancelOperation: MethodDefinition<_google_longrunning_CancelOperationRequest, _google_protobuf_Empty, _google_longrunning_CancelOperationRequest__Output, _google_protobuf_Empty__Output> - DeleteOperation: MethodDefinition<_google_longrunning_DeleteOperationRequest, _google_protobuf_Empty, _google_longrunning_DeleteOperationRequest__Output, _google_protobuf_Empty__Output> - GetOperation: MethodDefinition<_google_longrunning_GetOperationRequest, _google_longrunning_Operation, _google_longrunning_GetOperationRequest__Output, _google_longrunning_Operation__Output> - ListOperations: MethodDefinition<_google_longrunning_ListOperationsRequest, _google_longrunning_ListOperationsResponse, _google_longrunning_ListOperationsRequest__Output, _google_longrunning_ListOperationsResponse__Output> - WaitOperation: MethodDefinition<_google_longrunning_WaitOperationRequest, _google_longrunning_Operation, _google_longrunning_WaitOperationRequest__Output, _google_longrunning_Operation__Output> +export interface OperationsDefinition extends grpc.ServiceDefinition { + CancelOperation: MethodDefinition + DeleteOperation: MethodDefinition + GetOperation: MethodDefinition + ListOperations: MethodDefinition + WaitOperation: MethodDefinition } diff --git a/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts b/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts index f97e39dc4..2f11f7580 100644 --- a/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts +++ b/packages/proto-loader/golden-generated/google/longrunning/WaitOperationRequest.ts @@ -1,11 +1,11 @@ // Original file: deps/googleapis/google/longrunning/operations.proto -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../google/protobuf/Duration'; +import type { IDuration as I_google_protobuf_Duration, ODuration as O_google_protobuf_Duration } from '../../google/protobuf/Duration'; /** * The request message for [Operations.WaitOperation][google.longrunning.Operations.WaitOperation]. */ -export interface WaitOperationRequest { +export interface IWaitOperationRequest { /** * The name of the operation resource to wait on. */ @@ -15,13 +15,13 @@ export interface WaitOperationRequest { * will be at most the time permitted by the underlying HTTP/RPC protocol. * If RPC context deadline is also specified, the shorter one will be used. */ - 'timeout'?: (_google_protobuf_Duration | null); + 'timeout'?: (I_google_protobuf_Duration | null); } /** * The request message for [Operations.WaitOperation][google.longrunning.Operations.WaitOperation]. */ -export interface WaitOperationRequest__Output { +export interface OWaitOperationRequest { /** * The name of the operation resource to wait on. */ @@ -31,5 +31,5 @@ export interface WaitOperationRequest__Output { * will be at most the time permitted by the underlying HTTP/RPC protocol. * If RPC context deadline is also specified, the shorter one will be used. */ - 'timeout': (_google_protobuf_Duration__Output | null); + 'timeout': (O_google_protobuf_Duration | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Any.ts b/packages/proto-loader/golden-generated/google/protobuf/Any.ts index fe0d05f12..d9ee4e200 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Any.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Any.ts @@ -2,12 +2,12 @@ import type { AnyExtension } from '@grpc/proto-loader'; -export type Any = AnyExtension | { +export type IAny = AnyExtension | { type_url: string; value: Buffer | Uint8Array | string; } -export type Any__Output = AnyExtension | { +export type OAny = AnyExtension | { type_url: string; value: Buffer; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts index f729437f4..5f568ca2c 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/DescriptorProto.ts @@ -1,53 +1,53 @@ // Original file: null -import type { FieldDescriptorProto as _google_protobuf_FieldDescriptorProto, FieldDescriptorProto__Output as _google_protobuf_FieldDescriptorProto__Output } from '../../google/protobuf/FieldDescriptorProto'; -import type { DescriptorProto as _google_protobuf_DescriptorProto, DescriptorProto__Output as _google_protobuf_DescriptorProto__Output } from '../../google/protobuf/DescriptorProto'; -import type { EnumDescriptorProto as _google_protobuf_EnumDescriptorProto, EnumDescriptorProto__Output as _google_protobuf_EnumDescriptorProto__Output } from '../../google/protobuf/EnumDescriptorProto'; -import type { MessageOptions as _google_protobuf_MessageOptions, MessageOptions__Output as _google_protobuf_MessageOptions__Output } from '../../google/protobuf/MessageOptions'; -import type { OneofDescriptorProto as _google_protobuf_OneofDescriptorProto, OneofDescriptorProto__Output as _google_protobuf_OneofDescriptorProto__Output } from '../../google/protobuf/OneofDescriptorProto'; +import type { IFieldDescriptorProto as I_google_protobuf_FieldDescriptorProto, OFieldDescriptorProto as O_google_protobuf_FieldDescriptorProto } from '../../google/protobuf/FieldDescriptorProto'; +import type { IDescriptorProto as I_google_protobuf_DescriptorProto, ODescriptorProto as O_google_protobuf_DescriptorProto } from '../../google/protobuf/DescriptorProto'; +import type { IEnumDescriptorProto as I_google_protobuf_EnumDescriptorProto, OEnumDescriptorProto as O_google_protobuf_EnumDescriptorProto } from '../../google/protobuf/EnumDescriptorProto'; +import type { IMessageOptions as I_google_protobuf_MessageOptions, OMessageOptions as O_google_protobuf_MessageOptions } from '../../google/protobuf/MessageOptions'; +import type { IOneofDescriptorProto as I_google_protobuf_OneofDescriptorProto, OOneofDescriptorProto as O_google_protobuf_OneofDescriptorProto } from '../../google/protobuf/OneofDescriptorProto'; -export interface _google_protobuf_DescriptorProto_ExtensionRange { +export interface I_google_protobuf_DescriptorProto_ExtensionRange { 'start'?: (number); 'end'?: (number); } -export interface _google_protobuf_DescriptorProto_ExtensionRange__Output { +export interface O_google_protobuf_DescriptorProto_ExtensionRange { 'start': (number); 'end': (number); } -export interface _google_protobuf_DescriptorProto_ReservedRange { +export interface I_google_protobuf_DescriptorProto_ReservedRange { 'start'?: (number); 'end'?: (number); } -export interface _google_protobuf_DescriptorProto_ReservedRange__Output { +export interface O_google_protobuf_DescriptorProto_ReservedRange { 'start': (number); 'end': (number); } -export interface DescriptorProto { +export interface IDescriptorProto { 'name'?: (string); - 'field'?: (_google_protobuf_FieldDescriptorProto)[]; - 'nestedType'?: (_google_protobuf_DescriptorProto)[]; - 'enumType'?: (_google_protobuf_EnumDescriptorProto)[]; - 'extensionRange'?: (_google_protobuf_DescriptorProto_ExtensionRange)[]; - 'extension'?: (_google_protobuf_FieldDescriptorProto)[]; - 'options'?: (_google_protobuf_MessageOptions | null); - 'oneofDecl'?: (_google_protobuf_OneofDescriptorProto)[]; - 'reservedRange'?: (_google_protobuf_DescriptorProto_ReservedRange)[]; + 'field'?: (I_google_protobuf_FieldDescriptorProto)[]; + 'nestedType'?: (I_google_protobuf_DescriptorProto)[]; + 'enumType'?: (I_google_protobuf_EnumDescriptorProto)[]; + 'extensionRange'?: (I_google_protobuf_DescriptorProto_ExtensionRange)[]; + 'extension'?: (I_google_protobuf_FieldDescriptorProto)[]; + 'options'?: (I_google_protobuf_MessageOptions | null); + 'oneofDecl'?: (I_google_protobuf_OneofDescriptorProto)[]; + 'reservedRange'?: (I_google_protobuf_DescriptorProto_ReservedRange)[]; 'reservedName'?: (string)[]; } -export interface DescriptorProto__Output { +export interface ODescriptorProto { 'name': (string); - 'field': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'nestedType': (_google_protobuf_DescriptorProto__Output)[]; - 'enumType': (_google_protobuf_EnumDescriptorProto__Output)[]; - 'extensionRange': (_google_protobuf_DescriptorProto_ExtensionRange__Output)[]; - 'extension': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'options': (_google_protobuf_MessageOptions__Output | null); - 'oneofDecl': (_google_protobuf_OneofDescriptorProto__Output)[]; - 'reservedRange': (_google_protobuf_DescriptorProto_ReservedRange__Output)[]; + 'field': (O_google_protobuf_FieldDescriptorProto)[]; + 'nestedType': (O_google_protobuf_DescriptorProto)[]; + 'enumType': (O_google_protobuf_EnumDescriptorProto)[]; + 'extensionRange': (O_google_protobuf_DescriptorProto_ExtensionRange)[]; + 'extension': (O_google_protobuf_FieldDescriptorProto)[]; + 'options': (O_google_protobuf_MessageOptions | null); + 'oneofDecl': (O_google_protobuf_OneofDescriptorProto)[]; + 'reservedRange': (O_google_protobuf_DescriptorProto_ReservedRange)[]; 'reservedName': (string)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Duration.ts b/packages/proto-loader/golden-generated/google/protobuf/Duration.ts index 8595377a0..d5e3be89a 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Duration.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Duration.ts @@ -2,12 +2,12 @@ import type { Long } from '@grpc/proto-loader'; -export interface Duration { +export interface IDuration { 'seconds'?: (number | string | Long); 'nanos'?: (number); } -export interface Duration__Output { +export interface ODuration { 'seconds': (string); 'nanos': (number); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Empty.ts b/packages/proto-loader/golden-generated/google/protobuf/Empty.ts index f32c2a284..6594cc86c 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Empty.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Empty.ts @@ -1,8 +1,8 @@ // Original file: null -export interface Empty { +export interface IEmpty { } -export interface Empty__Output { +export interface OEmpty { } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts index dc4c9673e..30f52c610 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumDescriptorProto.ts @@ -1,16 +1,16 @@ // Original file: null -import type { EnumValueDescriptorProto as _google_protobuf_EnumValueDescriptorProto, EnumValueDescriptorProto__Output as _google_protobuf_EnumValueDescriptorProto__Output } from '../../google/protobuf/EnumValueDescriptorProto'; -import type { EnumOptions as _google_protobuf_EnumOptions, EnumOptions__Output as _google_protobuf_EnumOptions__Output } from '../../google/protobuf/EnumOptions'; +import type { IEnumValueDescriptorProto as I_google_protobuf_EnumValueDescriptorProto, OEnumValueDescriptorProto as O_google_protobuf_EnumValueDescriptorProto } from '../../google/protobuf/EnumValueDescriptorProto'; +import type { IEnumOptions as I_google_protobuf_EnumOptions, OEnumOptions as O_google_protobuf_EnumOptions } from '../../google/protobuf/EnumOptions'; -export interface EnumDescriptorProto { +export interface IEnumDescriptorProto { 'name'?: (string); - 'value'?: (_google_protobuf_EnumValueDescriptorProto)[]; - 'options'?: (_google_protobuf_EnumOptions | null); + 'value'?: (I_google_protobuf_EnumValueDescriptorProto)[]; + 'options'?: (I_google_protobuf_EnumOptions | null); } -export interface EnumDescriptorProto__Output { +export interface OEnumDescriptorProto { 'name': (string); - 'value': (_google_protobuf_EnumValueDescriptorProto__Output)[]; - 'options': (_google_protobuf_EnumOptions__Output | null); + 'value': (O_google_protobuf_EnumValueDescriptorProto)[]; + 'options': (O_google_protobuf_EnumOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts index b92ade4f9..6d2a0c2c6 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumOptions.ts @@ -1,15 +1,15 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface EnumOptions { +export interface IEnumOptions { 'allowAlias'?: (boolean); 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface EnumOptions__Output { +export interface OEnumOptions { 'allowAlias': (boolean); 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts index 7f8e57ea5..44cfcde4a 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumValueDescriptorProto.ts @@ -1,15 +1,15 @@ // Original file: null -import type { EnumValueOptions as _google_protobuf_EnumValueOptions, EnumValueOptions__Output as _google_protobuf_EnumValueOptions__Output } from '../../google/protobuf/EnumValueOptions'; +import type { IEnumValueOptions as I_google_protobuf_EnumValueOptions, OEnumValueOptions as O_google_protobuf_EnumValueOptions } from '../../google/protobuf/EnumValueOptions'; -export interface EnumValueDescriptorProto { +export interface IEnumValueDescriptorProto { 'name'?: (string); 'number'?: (number); - 'options'?: (_google_protobuf_EnumValueOptions | null); + 'options'?: (I_google_protobuf_EnumValueOptions | null); } -export interface EnumValueDescriptorProto__Output { +export interface OEnumValueDescriptorProto { 'name': (string); 'number': (number); - 'options': (_google_protobuf_EnumValueOptions__Output | null); + 'options': (O_google_protobuf_EnumValueOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts index e60ee6f4c..143381113 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/EnumValueOptions.ts @@ -1,13 +1,13 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface EnumValueOptions { +export interface IEnumValueOptions { 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface EnumValueOptions__Output { +export interface OEnumValueOptions { 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts index c511e2eff..1bcb69abe 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FieldDescriptorProto.ts @@ -1,60 +1,110 @@ // Original file: null -import type { FieldOptions as _google_protobuf_FieldOptions, FieldOptions__Output as _google_protobuf_FieldOptions__Output } from '../../google/protobuf/FieldOptions'; +import type { IFieldOptions as I_google_protobuf_FieldOptions, OFieldOptions as O_google_protobuf_FieldOptions } from '../../google/protobuf/FieldOptions'; // Original file: null -export enum _google_protobuf_FieldDescriptorProto_Label { - LABEL_OPTIONAL = 1, - LABEL_REQUIRED = 2, - LABEL_REPEATED = 3, -} +export const _google_protobuf_FieldDescriptorProto_Label = { + LABEL_OPTIONAL: 'LABEL_OPTIONAL', + LABEL_REQUIRED: 'LABEL_REQUIRED', + LABEL_REPEATED: 'LABEL_REPEATED', +} as const; + +export type I_google_protobuf_FieldDescriptorProto_Label = + | 'LABEL_OPTIONAL' + | 1 + | 'LABEL_REQUIRED' + | 2 + | 'LABEL_REPEATED' + | 3 + +export type O_google_protobuf_FieldDescriptorProto_Label = typeof _google_protobuf_FieldDescriptorProto_Label[keyof typeof _google_protobuf_FieldDescriptorProto_Label] // Original file: null -export enum _google_protobuf_FieldDescriptorProto_Type { - TYPE_DOUBLE = 1, - TYPE_FLOAT = 2, - TYPE_INT64 = 3, - TYPE_UINT64 = 4, - TYPE_INT32 = 5, - TYPE_FIXED64 = 6, - TYPE_FIXED32 = 7, - TYPE_BOOL = 8, - TYPE_STRING = 9, - TYPE_GROUP = 10, - TYPE_MESSAGE = 11, - TYPE_BYTES = 12, - TYPE_UINT32 = 13, - TYPE_ENUM = 14, - TYPE_SFIXED32 = 15, - TYPE_SFIXED64 = 16, - TYPE_SINT32 = 17, - TYPE_SINT64 = 18, -} +export const _google_protobuf_FieldDescriptorProto_Type = { + TYPE_DOUBLE: 'TYPE_DOUBLE', + TYPE_FLOAT: 'TYPE_FLOAT', + TYPE_INT64: 'TYPE_INT64', + TYPE_UINT64: 'TYPE_UINT64', + TYPE_INT32: 'TYPE_INT32', + TYPE_FIXED64: 'TYPE_FIXED64', + TYPE_FIXED32: 'TYPE_FIXED32', + TYPE_BOOL: 'TYPE_BOOL', + TYPE_STRING: 'TYPE_STRING', + TYPE_GROUP: 'TYPE_GROUP', + TYPE_MESSAGE: 'TYPE_MESSAGE', + TYPE_BYTES: 'TYPE_BYTES', + TYPE_UINT32: 'TYPE_UINT32', + TYPE_ENUM: 'TYPE_ENUM', + TYPE_SFIXED32: 'TYPE_SFIXED32', + TYPE_SFIXED64: 'TYPE_SFIXED64', + TYPE_SINT32: 'TYPE_SINT32', + TYPE_SINT64: 'TYPE_SINT64', +} as const; + +export type I_google_protobuf_FieldDescriptorProto_Type = + | 'TYPE_DOUBLE' + | 1 + | 'TYPE_FLOAT' + | 2 + | 'TYPE_INT64' + | 3 + | 'TYPE_UINT64' + | 4 + | 'TYPE_INT32' + | 5 + | 'TYPE_FIXED64' + | 6 + | 'TYPE_FIXED32' + | 7 + | 'TYPE_BOOL' + | 8 + | 'TYPE_STRING' + | 9 + | 'TYPE_GROUP' + | 10 + | 'TYPE_MESSAGE' + | 11 + | 'TYPE_BYTES' + | 12 + | 'TYPE_UINT32' + | 13 + | 'TYPE_ENUM' + | 14 + | 'TYPE_SFIXED32' + | 15 + | 'TYPE_SFIXED64' + | 16 + | 'TYPE_SINT32' + | 17 + | 'TYPE_SINT64' + | 18 + +export type O_google_protobuf_FieldDescriptorProto_Type = typeof _google_protobuf_FieldDescriptorProto_Type[keyof typeof _google_protobuf_FieldDescriptorProto_Type] -export interface FieldDescriptorProto { +export interface IFieldDescriptorProto { 'name'?: (string); 'extendee'?: (string); 'number'?: (number); - 'label'?: (_google_protobuf_FieldDescriptorProto_Label | keyof typeof _google_protobuf_FieldDescriptorProto_Label); - 'type'?: (_google_protobuf_FieldDescriptorProto_Type | keyof typeof _google_protobuf_FieldDescriptorProto_Type); + 'label'?: (I_google_protobuf_FieldDescriptorProto_Label); + 'type'?: (I_google_protobuf_FieldDescriptorProto_Type); 'typeName'?: (string); 'defaultValue'?: (string); - 'options'?: (_google_protobuf_FieldOptions | null); + 'options'?: (I_google_protobuf_FieldOptions | null); 'oneofIndex'?: (number); 'jsonName'?: (string); } -export interface FieldDescriptorProto__Output { +export interface OFieldDescriptorProto { 'name': (string); 'extendee': (string); 'number': (number); - 'label': (keyof typeof _google_protobuf_FieldDescriptorProto_Label); - 'type': (keyof typeof _google_protobuf_FieldDescriptorProto_Type); + 'label': (O_google_protobuf_FieldDescriptorProto_Label); + 'type': (O_google_protobuf_FieldDescriptorProto_Type); 'typeName': (string); 'defaultValue': (string); - 'options': (_google_protobuf_FieldOptions__Output | null); + 'options': (O_google_protobuf_FieldOptions | null); 'oneofIndex': (number); 'jsonName': (string); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts index 8304053f1..16e532d95 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FieldOptions.ts @@ -1,42 +1,62 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; -import type { FieldBehavior as _google_api_FieldBehavior } from '../../google/api/FieldBehavior'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; +import type { IFieldBehavior as I_google_api_FieldBehavior, OFieldBehavior as O_google_api_FieldBehavior } from '../../google/api/FieldBehavior'; // Original file: null -export enum _google_protobuf_FieldOptions_CType { - STRING = 0, - CORD = 1, - STRING_PIECE = 2, -} +export const _google_protobuf_FieldOptions_CType = { + STRING: 'STRING', + CORD: 'CORD', + STRING_PIECE: 'STRING_PIECE', +} as const; + +export type I_google_protobuf_FieldOptions_CType = + | 'STRING' + | 0 + | 'CORD' + | 1 + | 'STRING_PIECE' + | 2 + +export type O_google_protobuf_FieldOptions_CType = typeof _google_protobuf_FieldOptions_CType[keyof typeof _google_protobuf_FieldOptions_CType] // Original file: null -export enum _google_protobuf_FieldOptions_JSType { - JS_NORMAL = 0, - JS_STRING = 1, - JS_NUMBER = 2, -} +export const _google_protobuf_FieldOptions_JSType = { + JS_NORMAL: 'JS_NORMAL', + JS_STRING: 'JS_STRING', + JS_NUMBER: 'JS_NUMBER', +} as const; + +export type I_google_protobuf_FieldOptions_JSType = + | 'JS_NORMAL' + | 0 + | 'JS_STRING' + | 1 + | 'JS_NUMBER' + | 2 + +export type O_google_protobuf_FieldOptions_JSType = typeof _google_protobuf_FieldOptions_JSType[keyof typeof _google_protobuf_FieldOptions_JSType] -export interface FieldOptions { - 'ctype'?: (_google_protobuf_FieldOptions_CType | keyof typeof _google_protobuf_FieldOptions_CType); +export interface IFieldOptions { + 'ctype'?: (I_google_protobuf_FieldOptions_CType); 'packed'?: (boolean); 'deprecated'?: (boolean); 'lazy'?: (boolean); - 'jstype'?: (_google_protobuf_FieldOptions_JSType | keyof typeof _google_protobuf_FieldOptions_JSType); + 'jstype'?: (I_google_protobuf_FieldOptions_JSType); 'weak'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; - '.google.api.field_behavior'?: (_google_api_FieldBehavior | keyof typeof _google_api_FieldBehavior)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; + '.google.api.field_behavior'?: (I_google_api_FieldBehavior)[]; } -export interface FieldOptions__Output { - 'ctype': (keyof typeof _google_protobuf_FieldOptions_CType); +export interface OFieldOptions { + 'ctype': (O_google_protobuf_FieldOptions_CType); 'packed': (boolean); 'deprecated': (boolean); 'lazy': (boolean); - 'jstype': (keyof typeof _google_protobuf_FieldOptions_JSType); + 'jstype': (O_google_protobuf_FieldOptions_JSType); 'weak': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; - '.google.api.field_behavior': (keyof typeof _google_api_FieldBehavior)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; + '.google.api.field_behavior': (O_google_api_FieldBehavior)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts index b723da7c0..c98732f9d 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorProto.ts @@ -1,37 +1,37 @@ // Original file: null -import type { DescriptorProto as _google_protobuf_DescriptorProto, DescriptorProto__Output as _google_protobuf_DescriptorProto__Output } from '../../google/protobuf/DescriptorProto'; -import type { EnumDescriptorProto as _google_protobuf_EnumDescriptorProto, EnumDescriptorProto__Output as _google_protobuf_EnumDescriptorProto__Output } from '../../google/protobuf/EnumDescriptorProto'; -import type { ServiceDescriptorProto as _google_protobuf_ServiceDescriptorProto, ServiceDescriptorProto__Output as _google_protobuf_ServiceDescriptorProto__Output } from '../../google/protobuf/ServiceDescriptorProto'; -import type { FieldDescriptorProto as _google_protobuf_FieldDescriptorProto, FieldDescriptorProto__Output as _google_protobuf_FieldDescriptorProto__Output } from '../../google/protobuf/FieldDescriptorProto'; -import type { FileOptions as _google_protobuf_FileOptions, FileOptions__Output as _google_protobuf_FileOptions__Output } from '../../google/protobuf/FileOptions'; -import type { SourceCodeInfo as _google_protobuf_SourceCodeInfo, SourceCodeInfo__Output as _google_protobuf_SourceCodeInfo__Output } from '../../google/protobuf/SourceCodeInfo'; +import type { IDescriptorProto as I_google_protobuf_DescriptorProto, ODescriptorProto as O_google_protobuf_DescriptorProto } from '../../google/protobuf/DescriptorProto'; +import type { IEnumDescriptorProto as I_google_protobuf_EnumDescriptorProto, OEnumDescriptorProto as O_google_protobuf_EnumDescriptorProto } from '../../google/protobuf/EnumDescriptorProto'; +import type { IServiceDescriptorProto as I_google_protobuf_ServiceDescriptorProto, OServiceDescriptorProto as O_google_protobuf_ServiceDescriptorProto } from '../../google/protobuf/ServiceDescriptorProto'; +import type { IFieldDescriptorProto as I_google_protobuf_FieldDescriptorProto, OFieldDescriptorProto as O_google_protobuf_FieldDescriptorProto } from '../../google/protobuf/FieldDescriptorProto'; +import type { IFileOptions as I_google_protobuf_FileOptions, OFileOptions as O_google_protobuf_FileOptions } from '../../google/protobuf/FileOptions'; +import type { ISourceCodeInfo as I_google_protobuf_SourceCodeInfo, OSourceCodeInfo as O_google_protobuf_SourceCodeInfo } from '../../google/protobuf/SourceCodeInfo'; -export interface FileDescriptorProto { +export interface IFileDescriptorProto { 'name'?: (string); 'package'?: (string); 'dependency'?: (string)[]; - 'messageType'?: (_google_protobuf_DescriptorProto)[]; - 'enumType'?: (_google_protobuf_EnumDescriptorProto)[]; - 'service'?: (_google_protobuf_ServiceDescriptorProto)[]; - 'extension'?: (_google_protobuf_FieldDescriptorProto)[]; - 'options'?: (_google_protobuf_FileOptions | null); - 'sourceCodeInfo'?: (_google_protobuf_SourceCodeInfo | null); + 'messageType'?: (I_google_protobuf_DescriptorProto)[]; + 'enumType'?: (I_google_protobuf_EnumDescriptorProto)[]; + 'service'?: (I_google_protobuf_ServiceDescriptorProto)[]; + 'extension'?: (I_google_protobuf_FieldDescriptorProto)[]; + 'options'?: (I_google_protobuf_FileOptions | null); + 'sourceCodeInfo'?: (I_google_protobuf_SourceCodeInfo | null); 'publicDependency'?: (number)[]; 'weakDependency'?: (number)[]; 'syntax'?: (string); } -export interface FileDescriptorProto__Output { +export interface OFileDescriptorProto { 'name': (string); 'package': (string); 'dependency': (string)[]; - 'messageType': (_google_protobuf_DescriptorProto__Output)[]; - 'enumType': (_google_protobuf_EnumDescriptorProto__Output)[]; - 'service': (_google_protobuf_ServiceDescriptorProto__Output)[]; - 'extension': (_google_protobuf_FieldDescriptorProto__Output)[]; - 'options': (_google_protobuf_FileOptions__Output | null); - 'sourceCodeInfo': (_google_protobuf_SourceCodeInfo__Output | null); + 'messageType': (O_google_protobuf_DescriptorProto)[]; + 'enumType': (O_google_protobuf_EnumDescriptorProto)[]; + 'service': (O_google_protobuf_ServiceDescriptorProto)[]; + 'extension': (O_google_protobuf_FieldDescriptorProto)[]; + 'options': (O_google_protobuf_FileOptions | null); + 'sourceCodeInfo': (O_google_protobuf_SourceCodeInfo | null); 'publicDependency': (number)[]; 'weakDependency': (number)[]; 'syntax': (string); diff --git a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts index 74ded2471..9c940ed5e 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FileDescriptorSet.ts @@ -1,11 +1,11 @@ // Original file: null -import type { FileDescriptorProto as _google_protobuf_FileDescriptorProto, FileDescriptorProto__Output as _google_protobuf_FileDescriptorProto__Output } from '../../google/protobuf/FileDescriptorProto'; +import type { IFileDescriptorProto as I_google_protobuf_FileDescriptorProto, OFileDescriptorProto as O_google_protobuf_FileDescriptorProto } from '../../google/protobuf/FileDescriptorProto'; -export interface FileDescriptorSet { - 'file'?: (_google_protobuf_FileDescriptorProto)[]; +export interface IFileDescriptorSet { + 'file'?: (I_google_protobuf_FileDescriptorProto)[]; } -export interface FileDescriptorSet__Output { - 'file': (_google_protobuf_FileDescriptorProto__Output)[]; +export interface OFileDescriptorSet { + 'file': (O_google_protobuf_FileDescriptorProto)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts index 573e847c0..fdeac9cd4 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/FileOptions.ts @@ -1,19 +1,29 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; // Original file: null -export enum _google_protobuf_FileOptions_OptimizeMode { - SPEED = 1, - CODE_SIZE = 2, - LITE_RUNTIME = 3, -} +export const _google_protobuf_FileOptions_OptimizeMode = { + SPEED: 'SPEED', + CODE_SIZE: 'CODE_SIZE', + LITE_RUNTIME: 'LITE_RUNTIME', +} as const; + +export type I_google_protobuf_FileOptions_OptimizeMode = + | 'SPEED' + | 1 + | 'CODE_SIZE' + | 2 + | 'LITE_RUNTIME' + | 3 + +export type O_google_protobuf_FileOptions_OptimizeMode = typeof _google_protobuf_FileOptions_OptimizeMode[keyof typeof _google_protobuf_FileOptions_OptimizeMode] -export interface FileOptions { +export interface IFileOptions { 'javaPackage'?: (string); 'javaOuterClassname'?: (string); - 'optimizeFor'?: (_google_protobuf_FileOptions_OptimizeMode | keyof typeof _google_protobuf_FileOptions_OptimizeMode); + 'optimizeFor'?: (I_google_protobuf_FileOptions_OptimizeMode); 'javaMultipleFiles'?: (boolean); 'goPackage'?: (string); 'ccGenericServices'?: (boolean); @@ -25,13 +35,13 @@ export interface FileOptions { 'ccEnableArenas'?: (boolean); 'objcClassPrefix'?: (string); 'csharpNamespace'?: (string); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface FileOptions__Output { +export interface OFileOptions { 'javaPackage': (string); 'javaOuterClassname': (string); - 'optimizeFor': (keyof typeof _google_protobuf_FileOptions_OptimizeMode); + 'optimizeFor': (O_google_protobuf_FileOptions_OptimizeMode); 'javaMultipleFiles': (boolean); 'goPackage': (string); 'ccGenericServices': (boolean); @@ -43,5 +53,5 @@ export interface FileOptions__Output { 'ccEnableArenas': (boolean); 'objcClassPrefix': (string); 'csharpNamespace': (string); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts b/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts index 019fb0e15..62f9dc715 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/GeneratedCodeInfo.ts @@ -1,24 +1,24 @@ // Original file: null -export interface _google_protobuf_GeneratedCodeInfo_Annotation { +export interface I_google_protobuf_GeneratedCodeInfo_Annotation { 'path'?: (number)[]; 'sourceFile'?: (string); 'begin'?: (number); 'end'?: (number); } -export interface _google_protobuf_GeneratedCodeInfo_Annotation__Output { +export interface O_google_protobuf_GeneratedCodeInfo_Annotation { 'path': (number)[]; 'sourceFile': (string); 'begin': (number); 'end': (number); } -export interface GeneratedCodeInfo { - 'annotation'?: (_google_protobuf_GeneratedCodeInfo_Annotation)[]; +export interface IGeneratedCodeInfo { + 'annotation'?: (I_google_protobuf_GeneratedCodeInfo_Annotation)[]; } -export interface GeneratedCodeInfo__Output { - 'annotation': (_google_protobuf_GeneratedCodeInfo_Annotation__Output)[]; +export interface OGeneratedCodeInfo { + 'annotation': (O_google_protobuf_GeneratedCodeInfo_Annotation)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts index 31f669eb0..8c8885e63 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/MessageOptions.ts @@ -1,19 +1,19 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface MessageOptions { +export interface IMessageOptions { 'messageSetWireFormat'?: (boolean); 'noStandardDescriptorAccessor'?: (boolean); 'deprecated'?: (boolean); 'mapEntry'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface MessageOptions__Output { +export interface OMessageOptions { 'messageSetWireFormat': (boolean); 'noStandardDescriptorAccessor': (boolean); 'deprecated': (boolean); 'mapEntry': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts index c76c0ea23..0826370df 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/MethodDescriptorProto.ts @@ -1,21 +1,21 @@ // Original file: null -import type { MethodOptions as _google_protobuf_MethodOptions, MethodOptions__Output as _google_protobuf_MethodOptions__Output } from '../../google/protobuf/MethodOptions'; +import type { IMethodOptions as I_google_protobuf_MethodOptions, OMethodOptions as O_google_protobuf_MethodOptions } from '../../google/protobuf/MethodOptions'; -export interface MethodDescriptorProto { +export interface IMethodDescriptorProto { 'name'?: (string); 'inputType'?: (string); 'outputType'?: (string); - 'options'?: (_google_protobuf_MethodOptions | null); + 'options'?: (I_google_protobuf_MethodOptions | null); 'clientStreaming'?: (boolean); 'serverStreaming'?: (boolean); } -export interface MethodDescriptorProto__Output { +export interface OMethodDescriptorProto { 'name': (string); 'inputType': (string); 'outputType': (string); - 'options': (_google_protobuf_MethodOptions__Output | null); + 'options': (O_google_protobuf_MethodOptions | null); 'clientStreaming': (boolean); 'serverStreaming': (boolean); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts index 7581b9643..5f0b69008 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/MethodOptions.ts @@ -1,21 +1,21 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; -import type { OperationInfo as _google_longrunning_OperationInfo, OperationInfo__Output as _google_longrunning_OperationInfo__Output } from '../../google/longrunning/OperationInfo'; -import type { HttpRule as _google_api_HttpRule, HttpRule__Output as _google_api_HttpRule__Output } from '../../google/api/HttpRule'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; +import type { IOperationInfo as I_google_longrunning_OperationInfo, OOperationInfo as O_google_longrunning_OperationInfo } from '../../google/longrunning/OperationInfo'; +import type { IHttpRule as I_google_api_HttpRule, OHttpRule as O_google_api_HttpRule } from '../../google/api/HttpRule'; -export interface MethodOptions { +export interface IMethodOptions { 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; - '.google.longrunning.operation_info'?: (_google_longrunning_OperationInfo | null); + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; + '.google.longrunning.operation_info'?: (I_google_longrunning_OperationInfo | null); '.google.api.method_signature'?: (string)[]; - '.google.api.http'?: (_google_api_HttpRule | null); + '.google.api.http'?: (I_google_api_HttpRule | null); } -export interface MethodOptions__Output { +export interface OMethodOptions { 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; - '.google.longrunning.operation_info': (_google_longrunning_OperationInfo__Output | null); + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; + '.google.longrunning.operation_info': (O_google_longrunning_OperationInfo | null); '.google.api.method_signature': (string)[]; - '.google.api.http': (_google_api_HttpRule__Output | null); + '.google.api.http': (O_google_api_HttpRule | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts index 636f13ed4..6394270ea 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/OneofDescriptorProto.ts @@ -1,13 +1,13 @@ // Original file: null -import type { OneofOptions as _google_protobuf_OneofOptions, OneofOptions__Output as _google_protobuf_OneofOptions__Output } from '../../google/protobuf/OneofOptions'; +import type { IOneofOptions as I_google_protobuf_OneofOptions, OOneofOptions as O_google_protobuf_OneofOptions } from '../../google/protobuf/OneofOptions'; -export interface OneofDescriptorProto { +export interface IOneofDescriptorProto { 'name'?: (string); - 'options'?: (_google_protobuf_OneofOptions | null); + 'options'?: (I_google_protobuf_OneofOptions | null); } -export interface OneofDescriptorProto__Output { +export interface OOneofDescriptorProto { 'name': (string); - 'options': (_google_protobuf_OneofOptions__Output | null); + 'options': (O_google_protobuf_OneofOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts index d81d34797..73280ad73 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/OneofOptions.ts @@ -1,11 +1,11 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface OneofOptions { - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; +export interface IOneofOptions { + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; } -export interface OneofOptions__Output { - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; +export interface OOneofOptions { + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts b/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts index 40c9263ea..a0427fda5 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/ServiceDescriptorProto.ts @@ -1,16 +1,16 @@ // Original file: null -import type { MethodDescriptorProto as _google_protobuf_MethodDescriptorProto, MethodDescriptorProto__Output as _google_protobuf_MethodDescriptorProto__Output } from '../../google/protobuf/MethodDescriptorProto'; -import type { ServiceOptions as _google_protobuf_ServiceOptions, ServiceOptions__Output as _google_protobuf_ServiceOptions__Output } from '../../google/protobuf/ServiceOptions'; +import type { IMethodDescriptorProto as I_google_protobuf_MethodDescriptorProto, OMethodDescriptorProto as O_google_protobuf_MethodDescriptorProto } from '../../google/protobuf/MethodDescriptorProto'; +import type { IServiceOptions as I_google_protobuf_ServiceOptions, OServiceOptions as O_google_protobuf_ServiceOptions } from '../../google/protobuf/ServiceOptions'; -export interface ServiceDescriptorProto { +export interface IServiceDescriptorProto { 'name'?: (string); - 'method'?: (_google_protobuf_MethodDescriptorProto)[]; - 'options'?: (_google_protobuf_ServiceOptions | null); + 'method'?: (I_google_protobuf_MethodDescriptorProto)[]; + 'options'?: (I_google_protobuf_ServiceOptions | null); } -export interface ServiceDescriptorProto__Output { +export interface OServiceDescriptorProto { 'name': (string); - 'method': (_google_protobuf_MethodDescriptorProto__Output)[]; - 'options': (_google_protobuf_ServiceOptions__Output | null); + 'method': (O_google_protobuf_MethodDescriptorProto)[]; + 'options': (O_google_protobuf_ServiceOptions | null); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts b/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts index c0522eca3..0ddc8e187 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/ServiceOptions.ts @@ -1,17 +1,17 @@ // Original file: null -import type { UninterpretedOption as _google_protobuf_UninterpretedOption, UninterpretedOption__Output as _google_protobuf_UninterpretedOption__Output } from '../../google/protobuf/UninterpretedOption'; +import type { IUninterpretedOption as I_google_protobuf_UninterpretedOption, OUninterpretedOption as O_google_protobuf_UninterpretedOption } from '../../google/protobuf/UninterpretedOption'; -export interface ServiceOptions { +export interface IServiceOptions { 'deprecated'?: (boolean); - 'uninterpretedOption'?: (_google_protobuf_UninterpretedOption)[]; + 'uninterpretedOption'?: (I_google_protobuf_UninterpretedOption)[]; '.google.api.default_host'?: (string); '.google.api.oauth_scopes'?: (string); } -export interface ServiceOptions__Output { +export interface OServiceOptions { 'deprecated': (boolean); - 'uninterpretedOption': (_google_protobuf_UninterpretedOption__Output)[]; + 'uninterpretedOption': (O_google_protobuf_UninterpretedOption)[]; '.google.api.default_host': (string); '.google.api.oauth_scopes': (string); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts b/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts index d30e59b4f..4d0856604 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/SourceCodeInfo.ts @@ -1,7 +1,7 @@ // Original file: null -export interface _google_protobuf_SourceCodeInfo_Location { +export interface I_google_protobuf_SourceCodeInfo_Location { 'path'?: (number)[]; 'span'?: (number)[]; 'leadingComments'?: (string); @@ -9,7 +9,7 @@ export interface _google_protobuf_SourceCodeInfo_Location { 'leadingDetachedComments'?: (string)[]; } -export interface _google_protobuf_SourceCodeInfo_Location__Output { +export interface O_google_protobuf_SourceCodeInfo_Location { 'path': (number)[]; 'span': (number)[]; 'leadingComments': (string); @@ -17,10 +17,10 @@ export interface _google_protobuf_SourceCodeInfo_Location__Output { 'leadingDetachedComments': (string)[]; } -export interface SourceCodeInfo { - 'location'?: (_google_protobuf_SourceCodeInfo_Location)[]; +export interface ISourceCodeInfo { + 'location'?: (I_google_protobuf_SourceCodeInfo_Location)[]; } -export interface SourceCodeInfo__Output { - 'location': (_google_protobuf_SourceCodeInfo_Location__Output)[]; +export interface OSourceCodeInfo { + 'location': (O_google_protobuf_SourceCodeInfo_Location)[]; } diff --git a/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts b/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts index ceaa32b5f..06d756134 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/Timestamp.ts @@ -2,12 +2,12 @@ import type { Long } from '@grpc/proto-loader'; -export interface Timestamp { +export interface ITimestamp { 'seconds'?: (number | string | Long); 'nanos'?: (number); } -export interface Timestamp__Output { +export interface OTimestamp { 'seconds': (string); 'nanos': (number); } diff --git a/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts b/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts index 433820f55..fa0feaf52 100644 --- a/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts +++ b/packages/proto-loader/golden-generated/google/protobuf/UninterpretedOption.ts @@ -2,18 +2,18 @@ import type { Long } from '@grpc/proto-loader'; -export interface _google_protobuf_UninterpretedOption_NamePart { +export interface I_google_protobuf_UninterpretedOption_NamePart { 'namePart'?: (string); 'isExtension'?: (boolean); } -export interface _google_protobuf_UninterpretedOption_NamePart__Output { +export interface O_google_protobuf_UninterpretedOption_NamePart { 'namePart': (string); 'isExtension': (boolean); } -export interface UninterpretedOption { - 'name'?: (_google_protobuf_UninterpretedOption_NamePart)[]; +export interface IUninterpretedOption { + 'name'?: (I_google_protobuf_UninterpretedOption_NamePart)[]; 'identifierValue'?: (string); 'positiveIntValue'?: (number | string | Long); 'negativeIntValue'?: (number | string | Long); @@ -22,8 +22,8 @@ export interface UninterpretedOption { 'aggregateValue'?: (string); } -export interface UninterpretedOption__Output { - 'name': (_google_protobuf_UninterpretedOption_NamePart__Output)[]; +export interface OUninterpretedOption { + 'name': (O_google_protobuf_UninterpretedOption_NamePart)[]; 'identifierValue': (string); 'positiveIntValue': (string); 'negativeIntValue': (string); diff --git a/packages/proto-loader/golden-generated/google/rpc/Status.ts b/packages/proto-loader/golden-generated/google/rpc/Status.ts index 4ce45b6a9..05cf71c5f 100644 --- a/packages/proto-loader/golden-generated/google/rpc/Status.ts +++ b/packages/proto-loader/golden-generated/google/rpc/Status.ts @@ -1,6 +1,6 @@ // Original file: deps/googleapis/google/rpc/status.proto -import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../google/protobuf/Any'; +import type { IAny as I_google_protobuf_Any, OAny as O_google_protobuf_Any } from '../../google/protobuf/Any'; /** * The `Status` type defines a logical error model that is suitable for @@ -11,7 +11,7 @@ import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__ * You can find out more about this error model and how to work with it in the * [API Design Guide](https://cloud.google.com/apis/design/errors). */ -export interface Status { +export interface IStatus { /** * The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. */ @@ -26,7 +26,7 @@ export interface Status { * A list of messages that carry the error details. There is a common set of * message types for APIs to use. */ - 'details'?: (_google_protobuf_Any)[]; + 'details'?: (I_google_protobuf_Any)[]; } /** @@ -38,7 +38,7 @@ export interface Status { * You can find out more about this error model and how to work with it in the * [API Design Guide](https://cloud.google.com/apis/design/errors). */ -export interface Status__Output { +export interface OStatus { /** * The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. */ @@ -53,5 +53,5 @@ export interface Status__Output { * A list of messages that carry the error details. There is a common set of * message types for APIs to use. */ - 'details': (_google_protobuf_Any__Output)[]; + 'details': (O_google_protobuf_Any)[]; } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts index 383c409c5..29d10f6dd 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockRequest.ts @@ -1,45 +1,45 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; -import type { BlockResponse as _google_showcase_v1beta1_BlockResponse, BlockResponse__Output as _google_showcase_v1beta1_BlockResponse__Output } from '../../../google/showcase/v1beta1/BlockResponse'; +import type { IDuration as I_google_protobuf_Duration, ODuration as O_google_protobuf_Duration } from '../../../google/protobuf/Duration'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; +import type { IBlockResponse as I_google_showcase_v1beta1_BlockResponse, OBlockResponse as O_google_showcase_v1beta1_BlockResponse } from '../../../google/showcase/v1beta1/BlockResponse'; /** * The request for Block method. */ -export interface BlockRequest { +export interface IBlockRequest { /** * The amount of time to block before returning a response. */ - 'response_delay'?: (_google_protobuf_Duration | null); + 'response_delay'?: (I_google_protobuf_Duration | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The response to be returned that will signify successful method call. */ - 'success'?: (_google_showcase_v1beta1_BlockResponse | null); + 'success'?: (I_google_showcase_v1beta1_BlockResponse | null); 'response'?: "error"|"success"; } /** * The request for Block method. */ -export interface BlockRequest__Output { +export interface OBlockRequest { /** * The amount of time to block before returning a response. */ - 'response_delay': (_google_protobuf_Duration__Output | null); + 'response_delay': (O_google_protobuf_Duration | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The response to be returned that will signify successful method call. */ - 'success'?: (_google_showcase_v1beta1_BlockResponse__Output | null); + 'success'?: (O_google_showcase_v1beta1_BlockResponse | null); 'response': "error"|"success"; } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts index 5634b19d4..3bb9bddf2 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/BlockResponse.ts @@ -4,7 +4,7 @@ /** * The response for Block method. */ -export interface BlockResponse { +export interface IBlockResponse { /** * This content can contain anything, the server will not depend on a value * here. @@ -15,7 +15,7 @@ export interface BlockResponse { /** * The response for Block method. */ -export interface BlockResponse__Output { +export interface OBlockResponse { /** * This content can contain anything, the server will not depend on a value * here. diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts index acb911270..a0330fe68 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/Echo.ts @@ -2,15 +2,15 @@ import type * as grpc from '@grpc/grpc-js' import type { MethodDefinition } from '@grpc/proto-loader' -import type { BlockRequest as _google_showcase_v1beta1_BlockRequest, BlockRequest__Output as _google_showcase_v1beta1_BlockRequest__Output } from '../../../google/showcase/v1beta1/BlockRequest'; -import type { BlockResponse as _google_showcase_v1beta1_BlockResponse, BlockResponse__Output as _google_showcase_v1beta1_BlockResponse__Output } from '../../../google/showcase/v1beta1/BlockResponse'; -import type { EchoRequest as _google_showcase_v1beta1_EchoRequest, EchoRequest__Output as _google_showcase_v1beta1_EchoRequest__Output } from '../../../google/showcase/v1beta1/EchoRequest'; -import type { EchoResponse as _google_showcase_v1beta1_EchoResponse, EchoResponse__Output as _google_showcase_v1beta1_EchoResponse__Output } from '../../../google/showcase/v1beta1/EchoResponse'; -import type { ExpandRequest as _google_showcase_v1beta1_ExpandRequest, ExpandRequest__Output as _google_showcase_v1beta1_ExpandRequest__Output } from '../../../google/showcase/v1beta1/ExpandRequest'; -import type { Operation as _google_longrunning_Operation, Operation__Output as _google_longrunning_Operation__Output } from '../../../google/longrunning/Operation'; -import type { PagedExpandRequest as _google_showcase_v1beta1_PagedExpandRequest, PagedExpandRequest__Output as _google_showcase_v1beta1_PagedExpandRequest__Output } from '../../../google/showcase/v1beta1/PagedExpandRequest'; -import type { PagedExpandResponse as _google_showcase_v1beta1_PagedExpandResponse, PagedExpandResponse__Output as _google_showcase_v1beta1_PagedExpandResponse__Output } from '../../../google/showcase/v1beta1/PagedExpandResponse'; -import type { WaitRequest as _google_showcase_v1beta1_WaitRequest, WaitRequest__Output as _google_showcase_v1beta1_WaitRequest__Output } from '../../../google/showcase/v1beta1/WaitRequest'; +import type { IBlockRequest as I_google_showcase_v1beta1_BlockRequest, OBlockRequest as O_google_showcase_v1beta1_BlockRequest } from '../../../google/showcase/v1beta1/BlockRequest'; +import type { IBlockResponse as I_google_showcase_v1beta1_BlockResponse, OBlockResponse as O_google_showcase_v1beta1_BlockResponse } from '../../../google/showcase/v1beta1/BlockResponse'; +import type { IEchoRequest as I_google_showcase_v1beta1_EchoRequest, OEchoRequest as O_google_showcase_v1beta1_EchoRequest } from '../../../google/showcase/v1beta1/EchoRequest'; +import type { IEchoResponse as I_google_showcase_v1beta1_EchoResponse, OEchoResponse as O_google_showcase_v1beta1_EchoResponse } from '../../../google/showcase/v1beta1/EchoResponse'; +import type { IExpandRequest as I_google_showcase_v1beta1_ExpandRequest, OExpandRequest as O_google_showcase_v1beta1_ExpandRequest } from '../../../google/showcase/v1beta1/ExpandRequest'; +import type { IOperation as I_google_longrunning_Operation, OOperation as O_google_longrunning_Operation } from '../../../google/longrunning/Operation'; +import type { IPagedExpandRequest as I_google_showcase_v1beta1_PagedExpandRequest, OPagedExpandRequest as O_google_showcase_v1beta1_PagedExpandRequest } from '../../../google/showcase/v1beta1/PagedExpandRequest'; +import type { IPagedExpandResponse as I_google_showcase_v1beta1_PagedExpandResponse, OPagedExpandResponse as O_google_showcase_v1beta1_PagedExpandResponse } from '../../../google/showcase/v1beta1/PagedExpandResponse'; +import type { IWaitRequest as I_google_showcase_v1beta1_WaitRequest, OWaitRequest as O_google_showcase_v1beta1_WaitRequest } from '../../../google/showcase/v1beta1/WaitRequest'; /** * This service is used showcase the four main types of rpcs - unary, server @@ -25,115 +25,115 @@ export interface EchoClient extends grpc.Client { * and then return the response or error. * This method showcases how a client handles delays or retries. */ - Block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; - Block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; - Block(argument: _google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; - Block(argument: _google_showcase_v1beta1_BlockRequest, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Block(argument: I_google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method will block (wait) for the requested amount of time * and then return the response or error. * This method showcases how a client handles delays or retries. */ - block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; - block(argument: _google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; - block(argument: _google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; - block(argument: _google_showcase_v1beta1_BlockRequest, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_BlockResponse__Output) => void): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + block(argument: I_google_showcase_v1beta1_BlockRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method, upon receiving a request on the stream, the same content will * be passed back on the stream. This method showcases bidirectional * streaming rpcs. */ - Chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; - Chat(options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; + Chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream; + Chat(options?: grpc.CallOptions): grpc.ClientDuplexStream; /** * This method, upon receiving a request on the stream, the same content will * be passed back on the stream. This method showcases bidirectional * streaming rpcs. */ - chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; - chat(options?: grpc.CallOptions): grpc.ClientDuplexStream<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse__Output>; + chat(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream; + chat(options?: grpc.CallOptions): grpc.ClientDuplexStream; /** * This method will collect the words given to it. When the stream is closed * by the client, this method will return the a concatenation of the strings * passed to it. This method showcases client-side streaming rpcs. */ - Collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - Collect(metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - Collect(options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - Collect(callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; + Collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + Collect(metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientWritableStream; + Collect(options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + Collect(callback: grpc.requestCallback): grpc.ClientWritableStream; /** * This method will collect the words given to it. When the stream is closed * by the client, this method will return the a concatenation of the strings * passed to it. This method showcases client-side streaming rpcs. */ - collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - collect(metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - collect(options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; - collect(callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientWritableStream<_google_showcase_v1beta1_EchoRequest>; + collect(metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + collect(metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientWritableStream; + collect(options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientWritableStream; + collect(callback: grpc.requestCallback): grpc.ClientWritableStream; /** * This method simply echos the request. This method is showcases unary rpcs. */ - Echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; - Echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; - Echo(argument: _google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; - Echo(argument: _google_showcase_v1beta1_EchoRequest, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Echo(argument: I_google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method simply echos the request. This method is showcases unary rpcs. */ - echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; - echo(argument: _google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; - echo(argument: _google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; - echo(argument: _google_showcase_v1beta1_EchoRequest, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_EchoResponse__Output) => void): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + echo(argument: I_google_showcase_v1beta1_EchoRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method split the given content into words and will pass each word back * through the stream. This method showcases server-side streaming rpcs. */ - Expand(argument: _google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; - Expand(argument: _google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; + Expand(argument: I_google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream; + Expand(argument: I_google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream; /** * This method split the given content into words and will pass each word back * through the stream. This method showcases server-side streaming rpcs. */ - expand(argument: _google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; - expand(argument: _google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream<_google_showcase_v1beta1_EchoResponse__Output>; + expand(argument: I_google_showcase_v1beta1_ExpandRequest, metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientReadableStream; + expand(argument: I_google_showcase_v1beta1_ExpandRequest, options?: grpc.CallOptions): grpc.ClientReadableStream; /** * This is similar to the Expand method but instead of returning a stream of * expanded words, this method returns a paged list of expanded words. */ - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; - PagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + PagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This is similar to the Expand method but instead of returning a stream of * expanded words, this method returns a paged list of expanded words. */ - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; - pagedExpand(argument: _google_showcase_v1beta1_PagedExpandRequest, callback: (error?: grpc.ServiceError, result?: _google_showcase_v1beta1_PagedExpandResponse__Output) => void): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + pagedExpand(argument: I_google_showcase_v1beta1_PagedExpandRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method will wait the requested amount of and then return. * This method showcases how a client handles a request timing out. */ - Wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - Wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - Wait(argument: _google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - Wait(argument: _google_showcase_v1beta1_WaitRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + Wait(argument: I_google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; /** * This method will wait the requested amount of and then return. * This method showcases how a client handles a request timing out. */ - wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - wait(argument: _google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - wait(argument: _google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; - wait(argument: _google_showcase_v1beta1_WaitRequest, callback: (error?: grpc.ServiceError, result?: _google_longrunning_Operation__Output) => void): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, metadata: grpc.Metadata, callback: grpc.requestCallback): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, options: grpc.CallOptions, callback: grpc.requestCallback): grpc.ClientUnaryCall; + wait(argument: I_google_showcase_v1beta1_WaitRequest, callback: grpc.requestCallback): grpc.ClientUnaryCall; } @@ -150,53 +150,53 @@ export interface EchoHandlers extends grpc.UntypedServiceImplementation { * and then return the response or error. * This method showcases how a client handles delays or retries. */ - Block: grpc.handleUnaryCall<_google_showcase_v1beta1_BlockRequest__Output, _google_showcase_v1beta1_BlockResponse>; + Block: grpc.handleUnaryCall; /** * This method, upon receiving a request on the stream, the same content will * be passed back on the stream. This method showcases bidirectional * streaming rpcs. */ - Chat: grpc.handleBidiStreamingCall<_google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Chat: grpc.handleBidiStreamingCall; /** * This method will collect the words given to it. When the stream is closed * by the client, this method will return the a concatenation of the strings * passed to it. This method showcases client-side streaming rpcs. */ - Collect: grpc.handleClientStreamingCall<_google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Collect: grpc.handleClientStreamingCall; /** * This method simply echos the request. This method is showcases unary rpcs. */ - Echo: grpc.handleUnaryCall<_google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Echo: grpc.handleUnaryCall; /** * This method split the given content into words and will pass each word back * through the stream. This method showcases server-side streaming rpcs. */ - Expand: grpc.handleServerStreamingCall<_google_showcase_v1beta1_ExpandRequest__Output, _google_showcase_v1beta1_EchoResponse>; + Expand: grpc.handleServerStreamingCall; /** * This is similar to the Expand method but instead of returning a stream of * expanded words, this method returns a paged list of expanded words. */ - PagedExpand: grpc.handleUnaryCall<_google_showcase_v1beta1_PagedExpandRequest__Output, _google_showcase_v1beta1_PagedExpandResponse>; + PagedExpand: grpc.handleUnaryCall; /** * This method will wait the requested amount of and then return. * This method showcases how a client handles a request timing out. */ - Wait: grpc.handleUnaryCall<_google_showcase_v1beta1_WaitRequest__Output, _google_longrunning_Operation>; + Wait: grpc.handleUnaryCall; } -export interface EchoDefinition { - Block: MethodDefinition<_google_showcase_v1beta1_BlockRequest, _google_showcase_v1beta1_BlockResponse, _google_showcase_v1beta1_BlockRequest__Output, _google_showcase_v1beta1_BlockResponse__Output> - Chat: MethodDefinition<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - Collect: MethodDefinition<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - Echo: MethodDefinition<_google_showcase_v1beta1_EchoRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_EchoRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - Expand: MethodDefinition<_google_showcase_v1beta1_ExpandRequest, _google_showcase_v1beta1_EchoResponse, _google_showcase_v1beta1_ExpandRequest__Output, _google_showcase_v1beta1_EchoResponse__Output> - PagedExpand: MethodDefinition<_google_showcase_v1beta1_PagedExpandRequest, _google_showcase_v1beta1_PagedExpandResponse, _google_showcase_v1beta1_PagedExpandRequest__Output, _google_showcase_v1beta1_PagedExpandResponse__Output> - Wait: MethodDefinition<_google_showcase_v1beta1_WaitRequest, _google_longrunning_Operation, _google_showcase_v1beta1_WaitRequest__Output, _google_longrunning_Operation__Output> +export interface EchoDefinition extends grpc.ServiceDefinition { + Block: MethodDefinition + Chat: MethodDefinition + Collect: MethodDefinition + Echo: MethodDefinition + Expand: MethodDefinition + PagedExpand: MethodDefinition + Wait: MethodDefinition } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts index fb2bb67d3..a5fb8f766 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoRequest.ts @@ -1,7 +1,7 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; -import type { Severity as _google_showcase_v1beta1_Severity } from '../../../google/showcase/v1beta1/Severity'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; +import type { ISeverity as I_google_showcase_v1beta1_Severity, OSeverity as O_google_showcase_v1beta1_Severity } from '../../../google/showcase/v1beta1/Severity'; /** * The request message used for the Echo, Collect and Chat methods. @@ -9,7 +9,7 @@ import type { Severity as _google_showcase_v1beta1_Severity } from '../../../goo * If status is set in this message * then the status will be returned as an error. */ -export interface EchoRequest { +export interface IEchoRequest { /** * The content to be echoed by the server. */ @@ -17,11 +17,11 @@ export interface EchoRequest { /** * The error to be thrown by the server. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The severity to be echoed by the server. */ - 'severity'?: (_google_showcase_v1beta1_Severity | keyof typeof _google_showcase_v1beta1_Severity); + 'severity'?: (I_google_showcase_v1beta1_Severity); 'response'?: "content"|"error"; } @@ -31,7 +31,7 @@ export interface EchoRequest { * If status is set in this message * then the status will be returned as an error. */ -export interface EchoRequest__Output { +export interface OEchoRequest { /** * The content to be echoed by the server. */ @@ -39,10 +39,10 @@ export interface EchoRequest__Output { /** * The error to be thrown by the server. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The severity to be echoed by the server. */ - 'severity': (keyof typeof _google_showcase_v1beta1_Severity); + 'severity': (O_google_showcase_v1beta1_Severity); 'response': "content"|"error"; } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts index 3fda238a1..ac50115bf 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/EchoResponse.ts @@ -1,11 +1,11 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Severity as _google_showcase_v1beta1_Severity } from '../../../google/showcase/v1beta1/Severity'; +import type { ISeverity as I_google_showcase_v1beta1_Severity, OSeverity as O_google_showcase_v1beta1_Severity } from '../../../google/showcase/v1beta1/Severity'; /** * The response message for the Echo methods. */ -export interface EchoResponse { +export interface IEchoResponse { /** * The content specified in the request. */ @@ -13,13 +13,13 @@ export interface EchoResponse { /** * The severity specified in the request. */ - 'severity'?: (_google_showcase_v1beta1_Severity | keyof typeof _google_showcase_v1beta1_Severity); + 'severity'?: (I_google_showcase_v1beta1_Severity); } /** * The response message for the Echo methods. */ -export interface EchoResponse__Output { +export interface OEchoResponse { /** * The content specified in the request. */ @@ -27,5 +27,5 @@ export interface EchoResponse__Output { /** * The severity specified in the request. */ - 'severity': (keyof typeof _google_showcase_v1beta1_Severity); + 'severity': (O_google_showcase_v1beta1_Severity); } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts index 33ce73c1f..4347a617a 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/ExpandRequest.ts @@ -1,11 +1,11 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; /** * The request message for the Expand method. */ -export interface ExpandRequest { +export interface IExpandRequest { /** * The content that will be split into words and returned on the stream. */ @@ -13,13 +13,13 @@ export interface ExpandRequest { /** * The error that is thrown after all words are sent on the stream. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); } /** * The request message for the Expand method. */ -export interface ExpandRequest__Output { +export interface OExpandRequest { /** * The content that will be split into words and returned on the stream. */ @@ -27,5 +27,5 @@ export interface ExpandRequest__Output { /** * The error that is thrown after all words are sent on the stream. */ - 'error': (_google_rpc_Status__Output | null); + 'error': (O_google_rpc_Status | null); } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts index 13c945134..8c68ba990 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandRequest.ts @@ -4,7 +4,7 @@ /** * The request for the PagedExpand method. */ -export interface PagedExpandRequest { +export interface IPagedExpandRequest { /** * The string to expand. */ @@ -22,7 +22,7 @@ export interface PagedExpandRequest { /** * The request for the PagedExpand method. */ -export interface PagedExpandRequest__Output { +export interface OPagedExpandRequest { /** * The string to expand. */ diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts index 823de43ed..3b3ef90c2 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/PagedExpandResponse.ts @@ -1,15 +1,15 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { EchoResponse as _google_showcase_v1beta1_EchoResponse, EchoResponse__Output as _google_showcase_v1beta1_EchoResponse__Output } from '../../../google/showcase/v1beta1/EchoResponse'; +import type { IEchoResponse as I_google_showcase_v1beta1_EchoResponse, OEchoResponse as O_google_showcase_v1beta1_EchoResponse } from '../../../google/showcase/v1beta1/EchoResponse'; /** * The response for the PagedExpand method. */ -export interface PagedExpandResponse { +export interface IPagedExpandResponse { /** * The words that were expanded. */ - 'responses'?: (_google_showcase_v1beta1_EchoResponse)[]; + 'responses'?: (I_google_showcase_v1beta1_EchoResponse)[]; /** * The next page token. */ @@ -19,11 +19,11 @@ export interface PagedExpandResponse { /** * The response for the PagedExpand method. */ -export interface PagedExpandResponse__Output { +export interface OPagedExpandResponse { /** * The words that were expanded. */ - 'responses': (_google_showcase_v1beta1_EchoResponse__Output)[]; + 'responses': (O_google_showcase_v1beta1_EchoResponse)[]; /** * The next page token. */ diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/Severity.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/Severity.ts index fc3fe6415..d109fe1ce 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/Severity.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/Severity.ts @@ -3,9 +3,27 @@ /** * A severity enum used to test enum capabilities in GAPIC surfaces */ -export enum Severity { - UNNECESSARY = 0, - NECESSARY = 1, - URGENT = 2, - CRITICAL = 3, -} +export const Severity = { + UNNECESSARY: 'UNNECESSARY', + NECESSARY: 'NECESSARY', + URGENT: 'URGENT', + CRITICAL: 'CRITICAL', +} as const; + +/** + * A severity enum used to test enum capabilities in GAPIC surfaces + */ +export type ISeverity = + | 'UNNECESSARY' + | 0 + | 'NECESSARY' + | 1 + | 'URGENT' + | 2 + | 'CRITICAL' + | 3 + +/** + * A severity enum used to test enum capabilities in GAPIC surfaces + */ +export type OSeverity = typeof Severity[keyof typeof Severity] diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts index 5f17b4457..ddbe77c22 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitMetadata.ts @@ -1,23 +1,23 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; +import type { ITimestamp as I_google_protobuf_Timestamp, OTimestamp as O_google_protobuf_Timestamp } from '../../../google/protobuf/Timestamp'; /** * The metadata for Wait operation. */ -export interface WaitMetadata { +export interface IWaitMetadata { /** * The time that this operation will complete. */ - 'end_time'?: (_google_protobuf_Timestamp | null); + 'end_time'?: (I_google_protobuf_Timestamp | null); } /** * The metadata for Wait operation. */ -export interface WaitMetadata__Output { +export interface OWaitMetadata { /** * The time that this operation will complete. */ - 'end_time': (_google_protobuf_Timestamp__Output | null); + 'end_time': (O_google_protobuf_Timestamp | null); } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts index 46c095b65..331a66947 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitRequest.ts @@ -1,31 +1,31 @@ // Original file: deps/gapic-showcase/schema/google/showcase/v1beta1/echo.proto -import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp'; -import type { Status as _google_rpc_Status, Status__Output as _google_rpc_Status__Output } from '../../../google/rpc/Status'; -import type { WaitResponse as _google_showcase_v1beta1_WaitResponse, WaitResponse__Output as _google_showcase_v1beta1_WaitResponse__Output } from '../../../google/showcase/v1beta1/WaitResponse'; -import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration'; +import type { ITimestamp as I_google_protobuf_Timestamp, OTimestamp as O_google_protobuf_Timestamp } from '../../../google/protobuf/Timestamp'; +import type { IStatus as I_google_rpc_Status, OStatus as O_google_rpc_Status } from '../../../google/rpc/Status'; +import type { IWaitResponse as I_google_showcase_v1beta1_WaitResponse, OWaitResponse as O_google_showcase_v1beta1_WaitResponse } from '../../../google/showcase/v1beta1/WaitResponse'; +import type { IDuration as I_google_protobuf_Duration, ODuration as O_google_protobuf_Duration } from '../../../google/protobuf/Duration'; /** * The request for Wait method. */ -export interface WaitRequest { +export interface IWaitRequest { /** * The time that this operation will complete. */ - 'end_time'?: (_google_protobuf_Timestamp | null); + 'end_time'?: (I_google_protobuf_Timestamp | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status | null); + 'error'?: (I_google_rpc_Status | null); /** * The response to be returned on operation completion. */ - 'success'?: (_google_showcase_v1beta1_WaitResponse | null); + 'success'?: (I_google_showcase_v1beta1_WaitResponse | null); /** * The duration of this operation. */ - 'ttl'?: (_google_protobuf_Duration | null); + 'ttl'?: (I_google_protobuf_Duration | null); 'end'?: "end_time"|"ttl"; 'response'?: "error"|"success"; } @@ -33,24 +33,24 @@ export interface WaitRequest { /** * The request for Wait method. */ -export interface WaitRequest__Output { +export interface OWaitRequest { /** * The time that this operation will complete. */ - 'end_time'?: (_google_protobuf_Timestamp__Output | null); + 'end_time'?: (O_google_protobuf_Timestamp | null); /** * The error that will be returned by the server. If this code is specified * to be the OK rpc code, an empty response will be returned. */ - 'error'?: (_google_rpc_Status__Output | null); + 'error'?: (O_google_rpc_Status | null); /** * The response to be returned on operation completion. */ - 'success'?: (_google_showcase_v1beta1_WaitResponse__Output | null); + 'success'?: (O_google_showcase_v1beta1_WaitResponse | null); /** * The duration of this operation. */ - 'ttl'?: (_google_protobuf_Duration__Output | null); + 'ttl'?: (O_google_protobuf_Duration | null); 'end': "end_time"|"ttl"; 'response': "error"|"success"; } diff --git a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts index 84b804f6b..667b450e2 100644 --- a/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts +++ b/packages/proto-loader/golden-generated/google/showcase/v1beta1/WaitResponse.ts @@ -4,7 +4,7 @@ /** * The result of the Wait operation. */ -export interface WaitResponse { +export interface IWaitResponse { /** * This content of the result. */ @@ -14,7 +14,7 @@ export interface WaitResponse { /** * The result of the Wait operation. */ -export interface WaitResponse__Output { +export interface OWaitResponse { /** * This content of the result. */ diff --git a/packages/proto-loader/package.json b/packages/proto-loader/package.json index ee49abc40..cae7635f6 100644 --- a/packages/proto-loader/package.json +++ b/packages/proto-loader/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/proto-loader", - "version": "0.6.1", + "version": "0.7.3", "author": "Google Inc.", "contributors": [ { @@ -14,7 +14,7 @@ "typings": "build/src/index.d.ts", "scripts": { "build": "npm run compile", - "clean": "node -e 'require(\"rimraf\")(\"./build\", () => {})'", + "clean": "rimraf ./build", "compile": "tsc -p .", "format": "clang-format -i -style=\"{Language: JavaScript, BasedOnStyle: Google, ColumnLimit: 80}\" src/*.ts test/*.ts", "lint": "tslint -c node_modules/google-ts-style/tslint.json -p . -t codeFrame --type-check", @@ -24,8 +24,8 @@ "fix": "gts fix", "pretest": "npm run compile", "posttest": "npm run check", - "generate-golden": "node ./build/bin/proto-loader-gen-types.js --keepCase --longs=String --enums=String --defaults --oneofs --json --includeComments -I deps/gapic-showcase/schema/ deps/googleapis/ -O ./golden-generated --grpcLib @grpc/grpc-js google/showcase/v1beta1/echo.proto", - "validate-golden": "rm -rf ./golden-generated-old && mv ./golden-generated/ ./golden-generated-old && npm run generate-golden && diff -r ./golden-generated ./golden-generated-old" + "generate-golden": "node ./build/bin/proto-loader-gen-types.js --keepCase --longs=String --enums=String --defaults --oneofs --json --includeComments --inputTemplate=I%s --outputTemplate=O%s -I deps/gapic-showcase/schema/ deps/googleapis/ -O ./golden-generated --grpcLib @grpc/grpc-js google/showcase/v1beta1/echo.proto", + "validate-golden": "rm -rf ./golden-generated-old && mv ./golden-generated/ ./golden-generated-old && npm run generate-golden && diff -rb ./golden-generated ./golden-generated-old" }, "repository": { "type": "git", @@ -38,8 +38,8 @@ "files": [ "LICENSE", "build/src/*.d.ts", - "build/src/*.js", - "build/bin/*.js" + "build/src/*.{js,js.map}", + "build/bin/*.{js,js.map}" ], "bin": { "proto-loader-gen-types": "./build/bin/proto-loader-gen-types.js" @@ -48,19 +48,19 @@ "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^6.10.0", - "yargs": "^16.1.1" + "protobufjs": "^7.0.0", + "yargs": "^16.2.0" }, "devDependencies": { "@types/lodash.camelcase": "^4.3.4", "@types/mkdirp": "^1.0.1", "@types/mocha": "^5.2.7", "@types/node": "^10.17.26", - "@types/yargs": "^15.0.5", + "@types/yargs": "^16.0.4", "clang-format": "^1.2.2", - "gts": "^1.1.0", + "gts": "^3.1.0", "rimraf": "^3.0.2", - "typescript": "~3.8.3" + "typescript": "~4.7.4" }, "engines": { "node": ">=6" diff --git a/packages/proto-loader/src/index.ts b/packages/proto-loader/src/index.ts index 98ca97b51..d607668a9 100644 --- a/packages/proto-loader/src/index.ts +++ b/packages/proto-loader/src/index.ts @@ -22,9 +22,9 @@ import * as descriptor from 'protobufjs/ext/descriptor'; import { loadProtosWithOptionsSync, loadProtosWithOptions, Options, addCommonProtos } from './util'; -export { Long } from 'long'; +import Long = require('long'); -export { Options }; +export { Options, Long }; /** * This type exists for use with code generated by the proto-loader-gen-types @@ -212,6 +212,9 @@ function createDeserializer( function createSerializer(cls: Protobuf.Type): Serialize { return function serialize(arg: object): Buffer { + if (Array.isArray(arg)) { + throw new Error(`Failed to serialize message: expected object with ${cls.name} structure, got array instead`); + } const message = cls.fromObject(arg); return cls.encode(message).finish() as Buffer; }; diff --git a/run-tests.bat b/run-tests.bat index 1eebbd4a6..6b94b78de 100644 --- a/run-tests.bat +++ b/run-tests.bat @@ -21,15 +21,17 @@ powershell -c "[System.Environment]::OSVersion" powershell -c "Get-WmiObject -Class Win32_ComputerSystem" powershell -c "(Get-WmiObject -Class Win32_ComputerSystem).SystemType" -powershell -c "& { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" +powershell -c "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; & { iwr https://raw.githubusercontent.com/grumpycoders/nvm-ps/master/nvm.ps1 | iex }" SET PATH=%APPDATA%\nvm-ps;%APPDATA%\nvm-ps\nodejs;%PATH% SET JOBS=8 call nvm version -call nvm install 8 -call nvm use 8 +call nvm install 16 +call nvm use 16 + +git submodule update --init --recursive SET npm_config_fetch_retries=5 @@ -38,7 +40,7 @@ call npm install || goto :error SET JUNIT_REPORT_STACK=1 SET FAILED=0 -for %%v in (8 10 12) do ( +for %%v in (14 16) do ( call nvm install %%v call nvm use %%v if "%%v"=="4" ( @@ -53,7 +55,6 @@ for %%v in (8 10 12) do ( node -e "process.exit(process.version.startsWith('v%%v') ? 0 : -1)" || goto :error - call .\node_modules\.bin\gulp cleanAll || SET FAILED=1 call .\node_modules\.bin\gulp setup || SET FAILED=1 call .\node_modules\.bin\gulp test || SET FAILED=1 cmd.exe /c "SET GRPC_DNS_RESOLVER=ares& call .\node_modules\.bin\gulp nativeTestOnly" || SET FAILED=1 diff --git a/run-tests.sh b/run-tests.sh index c4bffacda..0adcc0f17 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -28,7 +28,7 @@ cd $ROOT git submodule update --init --recursive if [ ! -n "$node_versions" ] ; then - node_versions="8 10 12" + node_versions="14 16" fi set +ex @@ -46,6 +46,7 @@ export JOBS=8 export JUNIT_REPORT_STACK=1 OS=$(uname) +ARCH=$(uname -m) # TODO(mlumish): Add electron tests @@ -70,11 +71,12 @@ do node -e 'process.exit(process.version.startsWith("v'$version'") ? 0 : -1)' # Install dependencies and link packages together. - ./node_modules/.bin/gulp cleanAll ./node_modules/.bin/gulp setup # npm test calls nyc gulp test npm test || FAILED="true" + + ./test/distrib/run-distrib-test.sh || FAILED="true" done set +ex @@ -87,7 +89,7 @@ if [ "$FAILED" = "true" ] then exit 1 else - if [ "$OS" = "Linux" ] + if [ "$OS" = "Linux" ] && [ "$ARCH" != "aarch64"] then # If we can't download the token file, just skip reporting coverage gsutil cp gs://grpc-testing-secrets/coveralls_credentials/grpc-node.rc /tmp || exit 0 diff --git a/test/aarch64/prepare_qemu.sh b/test/aarch64/prepare_qemu.sh new file mode 100755 index 000000000..f61320222 --- /dev/null +++ b/test/aarch64/prepare_qemu.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# Setup and configure qemu userspace emulator on kokoro worker so that we can seamlessly emulate processes running +# inside docker containers. + +set -ex + +# show pre-existing qemu registration +cat /proc/sys/fs/binfmt_misc/qemu-aarch64 + +# Kokoro ubuntu1604 workers have already qemu-user and qemu-user-static packages installed, but it's and old version that: +# * prints warning about some syscalls (e.g "qemu: Unsupported syscall: 278") +# * doesn't register with binfmt_misc with the persistent ("F") flag we need (see below) +# +# To overcome the above limitations, we use the https://github.com/multiarch/qemu-user-static +# docker image to provide a new enough version of qemu-user-static and register it with +# the desired binfmt_misc flags. The most important flag we need is "F" (set by "--persistent yes"), +# which allows the qemu-aarch64-static binary to be loaded eagerly at the time of registration with binfmt_misc. +# That way, we can emulate aarch64 binaries running inside docker containers transparently, without needing the emulator +# binary to be accessible from the docker image we're emulating. +# Note that on newer distributions (such as glinux), simply "apt install qemu-user-static" is sufficient +# to install qemu-user-static with the right flags. +docker run --rm --privileged multiarch/qemu-user-static:5.2.0-2 --reset --credential yes --persistent yes + +# Print current qemu reqistration to make sure everything is setup correctly. +cat /proc/sys/fs/binfmt_misc/qemu-aarch64 diff --git a/test/api/connectivity_test.js b/test/api/connectivity_test.js index b5d31943d..64764d7d4 100644 --- a/test/api/connectivity_test.js +++ b/test/api/connectivity_test.js @@ -61,7 +61,9 @@ const serviceImpl = { describe(`${anyGrpc.clientName} client -> ${anyGrpc.serverName} server`, function() { it('client should not wait for ready by default', function(done) { this.timeout(15000); - const disconnectedClient = new TestServiceClient('foo.test.google.com:50051', clientGrpc.credentials.createInsecure()); + /* TCP port 47 is reserved according to + * https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers */ + const disconnectedClient = new TestServiceClient('localhost:47', clientGrpc.credentials.createInsecure()); const deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 10); disconnectedClient.unary({}, {deadline: deadline}, (error, value) =>{ @@ -72,7 +74,7 @@ describe(`${anyGrpc.clientName} client -> ${anyGrpc.serverName} server`, functio }); it('client should wait for a connection with waitForReady on', function(done) { this.timeout(15000); - const disconnectedClient = new TestServiceClient('foo.test.google.com:50051', clientGrpc.credentials.createInsecure()); + const disconnectedClient = new TestServiceClient('localhost:47', clientGrpc.credentials.createInsecure()); const metadata = new clientGrpc.Metadata({waitForReady: true}); const deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 10); diff --git a/test/api/interop_extra_test.js b/test/api/interop_extra_test.js index f8db35b38..fa7e03276 100644 --- a/test/api/interop_extra_test.js +++ b/test/api/interop_extra_test.js @@ -147,7 +147,8 @@ describe(`${anyGrpc.clientName} client -> ${anyGrpc.serverName} server`, functio }); }); it('should receive all messages in a long stream', function(done) { - this.timeout(20000); + // the test is slow under aarch64 emulator + this.timeout(80000); var arg = { response_type: 'COMPRESSABLE', response_parameters: [ @@ -197,6 +198,8 @@ describe(`${anyGrpc.clientName} client -> ${anyGrpc.serverName} server`, functio }); }); describe('max message size', function() { + // with the default timeout the test times out under aarch64 emulator + this.timeout(6000); // A size that is larger than the default limit const largeMessageSize = 8 * 1024 * 1024; const largeMessage = Buffer.alloc(largeMessageSize); @@ -238,6 +241,8 @@ describe(`${anyGrpc.clientName} client -> ${anyGrpc.serverName} server`, functio }); }); describe('with a client with no message size limits', function() { + // with the default timeout the test times out under aarch64 emulator + this.timeout(6000); let unrestrictedClient; before(function() { const ca_path = path.join(__dirname, '../data/ca.pem'); @@ -283,6 +288,8 @@ describe(`${anyGrpc.clientName} client -> ${anyGrpc.serverName} server`, functio }); }); describe('with a server with message size limits and a client without limits', function() { + // with the default timeout the test times out under aarch64 emulator + this.timeout(6000); let restrictedServer; let restrictedServerClient; let restrictedServerClient2; diff --git a/test/api/interop_sanity_test.js b/test/api/interop_sanity_test.js index 995650e20..c1e5d92b5 100644 --- a/test/api/interop_sanity_test.js +++ b/test/api/interop_sanity_test.js @@ -48,7 +48,8 @@ var childExecArgv = []; describe(`${anyGrpc.clientName} client -> ${anyGrpc.serverName} server`, function() { describe('Interop tests', function() { - this.timeout(4000); + // with the default timeout the test times out under aarch64 emulator + this.timeout(10000); before(function(done) { for (let arg of process.argv) { if (arg.startsWith('--require=')) { diff --git a/test/channelz/channelz_manual_test.js b/test/channelz/channelz_manual_test.js new file mode 100644 index 000000000..2f77df3cc --- /dev/null +++ b/test/channelz/channelz_manual_test.js @@ -0,0 +1,73 @@ +/* + * + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +'use strict'; + +require('../fixtures/js_js'); +const interopClient = require('../interop/interop_client'); +const interopServer = require('../interop/interop_server'); +const serverGrpc = require('../any_grpc').server; + +const hostOverride = 'foo.test.google.fr'; + +const testCases = [ + 'empty_unary', + 'large_unary', + 'client_streaming', + 'server_streaming', + 'ping_pong', + 'empty_stream', + 'cancel_after_begin', + 'cancel_after_first_response', + 'timeout_on_sleeping_server', + 'custom_metadata', + 'status_code_and_message', + 'special_status_message', + 'unimplemented_service', + 'unimplemented_method' +]; + +function getRandomTest() { + return testCases[(Math.random() * testCases.length) | 0]; +} + +let testCompleteCount = 0; + +interopServer.getServer('0', true, (error, result) => { + if (error) { + throw error; + } + const channelzServer = new serverGrpc.Server(); + channelzServer.bindAsync('localhost:0', serverGrpc.ServerCredentials.createInsecure(), (error, port) => { + if (error) { + throw error; + } + console.log(`Serving channelz at port ${port}`); + serverGrpc.addAdminServicesToServer(channelzServer); + channelzServer.start(); + result.server.start(); + setInterval(() => { + interopClient.runTest(`localhost:${result.port}`, hostOverride, getRandomTest(), true, true, () => { + testCompleteCount += 1; + if (testCompleteCount % 100 === 0) { + console.log(`Completed ${testCompleteCount} tests`); + } + }); + }, 100); + }); +}) \ No newline at end of file diff --git a/test/distrib/distrib-test.js b/test/distrib/distrib-test.js new file mode 100644 index 000000000..708c93eb8 --- /dev/null +++ b/test/distrib/distrib-test.js @@ -0,0 +1,22 @@ +/* + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +const grpcJs = require('@grpc/grpc-js'); + +const grpcJsXds = require('@grpc/grpc-js-xds'); + +const protoLoader = require('@grpc/proto-loader'); diff --git a/test/distrib/run-distrib-test.sh b/test/distrib/run-distrib-test.sh new file mode 100755 index 000000000..e2ed0853c --- /dev/null +++ b/test/distrib/run-distrib-test.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -ex + +cd $(dirname $0) +base=$(pwd) + +cd ../../packages/grpc-js +npm pack +cd ../grpc-js-xds +npm pack +cd ../proto-loader +npm pack + +cd $base +npm install ../../packages/grpc-js/grpc-grpc-js-*.tgz +npm install ../../packages/grpc-js-xds/grpc-grpc-js-xds-*.tgz +npm install ../../packages/proto-loader/grpc-proto-loader-*.tgz + +node ./distrib-test.js diff --git a/test/gulpfile.ts b/test/gulpfile.ts index 2024f02cb..6d43d4472 100644 --- a/test/gulpfile.ts +++ b/test/gulpfile.ts @@ -25,6 +25,10 @@ import * as semver from 'semver'; const testDir = __dirname; const apiTestDir = path.resolve(testDir, 'api'); +/* The native library has some misbehavior in specific tests when running in + * Node 14 and above. */ +const NATIVE_SUPPORT_RANGE = '<14'; + const runInstall = () => { return execa('npm', ['install'], {cwd: testDir, stdio: 'inherit'}); }; @@ -51,11 +55,11 @@ const testJsClientNativeServer = runTestsWithFixture('native', 'js'); const testNativeClientJsServer = runTestsWithFixture('js', 'native'); const testJsClientJsServer = runTestsWithFixture('js', 'js'); -const test = gulp.series( +const test = semver.satisfies(process.version, NATIVE_SUPPORT_RANGE)? gulp.series( testJsClientJsServer, testJsClientNativeServer, testNativeClientJsServer - ); + ) : testJsClientJsServer; export { install, diff --git a/test/interop/interop_client.js b/test/interop/interop_client.js index d7df128da..57f4f1846 100644 --- a/test/interop/interop_client.js +++ b/test/interop/interop_client.js @@ -484,7 +484,7 @@ function getApplicationCreds(scope, callback) { } function getOauth2Creds(scope, callback) { - (new GoogleAuth()).getAccessToken().then((token) => { + (new GoogleAuth({scopes: scope})).getAccessToken().then((token) => { var updateMd = function(service_url, callback) { var metadata = new grpc.Metadata(); metadata.add('authorization', 'Bearer ' + token); diff --git a/test/interop/interop_server.js b/test/interop/interop_server.js index cf7ae354e..b67ec5a8a 100644 --- a/test/interop/interop_server.js +++ b/test/interop/interop_server.js @@ -200,7 +200,7 @@ function handleHalfDuplex(call) { * Get a server object bound to the given port * @param {string} port Port to which to bind * @param {boolean} tls Indicates that the bound port should use TLS - * @param {function(Error, {{server: Server, port: number}})} callback Callback + * @param {function(Error, {server: Server, port: number})} callback Callback * to call with result or error * @param {object?} options Optional additional options to use when * constructing the server diff --git a/test/kokoro/linux.cfg b/test/kokoro/linux.cfg index f40e6db43..63f88d399 100644 --- a/test/kokoro/linux.cfg +++ b/test/kokoro/linux.cfg @@ -11,7 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - # Config file for Kokoro (in protobuf text format) # Location of the continuous shell script in repository. @@ -21,4 +20,4 @@ action { define_artifacts { regex: "github/grpc-node/reports/**/sponge_log.xml" } -} +} \ No newline at end of file diff --git a/test/kokoro/linux_aarch64.cfg b/test/kokoro/linux_aarch64.cfg new file mode 100644 index 000000000..638748ab8 --- /dev/null +++ b/test/kokoro/linux_aarch64.cfg @@ -0,0 +1,24 @@ +# Copyright 2017 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Config file for Kokoro (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc-node/test/kokoro_linux_aarch64.sh" +timeout_mins: 60 +action { + define_artifacts { + regex: "github/grpc-node/reports/**/sponge_log.xml" + } +} diff --git a/test/kokoro/xds-v3-interop.cfg b/test/kokoro/xds-v3-interop.cfg new file mode 100644 index 000000000..75377fe16 --- /dev/null +++ b/test/kokoro/xds-v3-interop.cfg @@ -0,0 +1,24 @@ +# Copyright 2021 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Config file for Kokoro (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc-node/packages/grpc-js-xds/scripts/xds-v3.sh" +timeout_mins: 360 +action { + define_artifacts { + regex: "github/grpc/reports/**" + } +} diff --git a/test/kokoro/xds_k8s_lb.cfg b/test/kokoro/xds_k8s_lb.cfg new file mode 100644 index 000000000..09aa3d17d --- /dev/null +++ b/test/kokoro/xds_k8s_lb.cfg @@ -0,0 +1,26 @@ +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Config file for Kokoro (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc-node/packages/grpc-js-xds/scripts/xds_k8s_lb.sh" +timeout_mins: 180 +action { + define_artifacts { + regex: "artifacts/**/*sponge_log.xml" + regex: "artifacts/**/*.log" + strip_prefix: "artifacts" + } +} diff --git a/test/kokoro/xds_k8s_url_map.cfg b/test/kokoro/xds_k8s_url_map.cfg new file mode 100644 index 000000000..50d523b66 --- /dev/null +++ b/test/kokoro/xds_k8s_url_map.cfg @@ -0,0 +1,26 @@ +# Copyright 2022 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Config file for Kokoro (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc-node/packages/grpc-js-xds/scripts/xds_k8s_url_map.sh" +timeout_mins: 180 +action { + define_artifacts { + regex: "artifacts/**/*sponge_log.xml" + regex: "artifacts/**/*.log" + strip_prefix: "artifacts" + } +} diff --git a/test/kokoro_linux_aarch64.sh b/test/kokoro_linux_aarch64.sh new file mode 100755 index 000000000..508881e5f --- /dev/null +++ b/test/kokoro_linux_aarch64.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -ex +cd $(dirname $0)/.. + +test/aarch64/prepare_qemu.sh + +# better update submodules here. We could update the submodule when running +# under an emulator as well, but it comes with performance penalty. +git submodule update --init --recursive + +if [[ -t 0 ]]; then + DOCKER_TTY_ARGS="-it" +else + # The input device on kokoro is not a TTY, so -it does not work. + DOCKER_TTY_ARGS= +fi + +# the test command to run under an emulated aarch64 docker container. +# we only run tests for a single version of node, since tests under an emulator are significantly slower. +TEST_NODE_COMMAND="node_versions='12' ./run-tests.sh" + +# use an actual aarch64 docker image (with a real aarch64 node) to run build & test grpc-js under an emulator +# * mount the protobuf root as /work to be able to access the crosscompiled files +# * to avoid running the process inside docker as root (which can pollute the workspace with files owned by root), we force +# running under current user's UID and GID. To be able to do that, we need to provide a home directory for the user +# otherwise the UID would be homeless under the docker container (which can lead to various issues). For simplicity, +# we just run map the user's home to a throwaway temporary directory. +# TODO(jtattermusch): we're using arm64v8/node:12-stretch instead of arm64v8/node:12-buster because the buster-based image +# has a newer version of ssl that considers some of the ssl keys used for testing too short, making the tests +# fails with "error:140AB18F:SSL routines:SSL_CTX_use_certificate:ee key too small". +# See https://github.com/grpc/grpc-node/issues/1795 +docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -v "$(mktemp -d):/home/fake-user" -v "$(pwd)":/work -w /work arm64v8/node:12-stretch bash -c "$TEST_NODE_COMMAND" diff --git a/tools/release/native/Dockerfile b/tools/release/native/Dockerfile index bc03bf178..7346d9aff 100644 --- a/tools/release/native/Dockerfile +++ b/tools/release/native/Dockerfile @@ -1,12 +1,7 @@ -FROM debian:jessie +FROM debian:stretch -RUN echo "deb http://archive.debian.org/debian jessie-backports main" > /etc/apt/sources.list.d/backports.list -RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf -RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update -RUN apt-get -t jessie-backports install -y cmake -RUN apt-get install -y curl build-essential python libc6-dev-i386 lib32stdc++-4.9-dev jq -RUN curl -fsSL get.docker.com | bash +RUN apt-get install -y cmake curl build-essential python libc6-dev-i386 lib32stdc++-6-dev jq RUN mkdir /usr/local/nvm ENV NVM_DIR /usr/local/nvm